#define TIMER_UPDATE_MS 33
+#define SPLIT_NUMERATOR 75
+#define SPLIT_DENOMINATOR 100
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
#define PROGNAME "rrace"
static const char *progname = PROGNAME;
static const struct option lopts[] = { LOPTS_INITIALIZER, {0} };
return;
}
- app = XtWidgetToApplicationContext(state->timer);
+ app = XtWidgetToApplicationContext(state->game);
ui_timer_update(state, game_elapsed(&state->board));
state->timer_tick = XtAppAddTimeOut(app, TIMER_UPDATE_MS,
timer_tick, state);
static void set_view_goal(struct app_state *state, int view_goal)
{
- state->view_goal_on_game = view_goal;
+ state->view_goal_on_game = !!view_goal;
x11_redraw_game(state, game_check_goal(&state->board));
}
XmDrawingAreaCallbackStruct *cbs = cb_data;
XButtonEvent *b = &cbs->event->xbutton;
struct app_state *state = data;
- Dimension width, height;
switch (cbs->event->type) {
case ButtonPress:
if (b->state & Button3Mask)
break;
- XtVaGetValues(w, XmNwidth, &width,
- XmNheight, &height,
- (char *)NULL);
-
- do_input_move(state, b->x / (width / 5),
- b->y / (height / 5));
+ do_input_move(state, b->x / state->game_tile_sz,
+ b->y / state->game_tile_sz);
break;
case Button3:
set_view_goal(state, 1);
{
game_reset(&state.board);
- x11_redraw_goal(&state, -1);
+ x11_redraw_goal(&state, -1, get_shell(w));
x11_redraw_game(&state, -1);
- x11_redraw_icon(&state, get_shell(w));
if (!state.timer_tick) {
XtAppContext app = XtWidgetToApplicationContext(w);
ui_show_about(&state, get_shell(w));
}
-static const XtActionsRec menu_actions[] = {
+static void proc_resize(Widget form, XEvent *e, String *argv, Cardinal *argc)
+{
+ Widget game = XtParent(state.game);
+ Widget goal = XtParent(state.goal);
+ Dimension w, h, gamesz, gameborder, goalsz, goalborder;
+ int x, y, gap;
+
+ XtVaGetValues(form, XmNwidth, &w, XmNheight, &h, (char *)NULL);
+ XtVaGetValues(game, XmNshadowThickness, &gameborder, (char *)NULL);
+ XtVaGetValues(goal, XmNshadowThickness, &goalborder,
+ XmNleftOffset, &gap,
+ (char *)NULL);
+
+ gamesz = MIN(h, w * SPLIT_NUMERATOR / SPLIT_DENOMINATOR);
+ state.game_tile_sz = (gamesz - 2*gameborder) / 5;
+ gamesz = 5*state.game_tile_sz + 2*gameborder;
+
+ goalsz = MIN(gamesz*3/5, w - gamesz - gap);
+ state.goal_tile_sz = (goalsz - 2*goalborder) / 3;
+ goalsz = 3*state.goal_tile_sz + 2*goalborder;
+
+ x = (w - gamesz - goalsz - gap) / 2;
+ if (x < 2) x = 0;
+
+ y = (h - gamesz) / 2;
+ if (y < 3) y = 0;
+
+ XtVaSetValues(game, XmNleftOffset, x, XmNtopOffset, y, (char *)NULL);
+ XtVaSetValues(game, XmNwidth, gamesz, XmNheight, gamesz, (char *)NULL);
+ XtVaSetValues(goal, XmNwidth, goalsz, XmNheight, goalsz, (char *)NULL);
+}
+
+static const XtActionsRec app_actions[] = {
{ "gameNew", proc_new_game },
{ "gameExit", proc_exit },
- { "helpAbout", proc_about }
+ { "helpAbout", proc_about },
+
+ { "ResizeGameArea", proc_resize }
};
static XtAppContext app_initialize(int argc, char **argv)
progname = argv[0];
shell = early_setup(&app, argc, argv);
- XtAppAddActions(app, (void *)menu_actions, XtNumber(menu_actions));
+ XtAppAddActions(app, (void *)app_actions, XtNumber(app_actions));
ui_initialize(&state, shell);
x11_initialize(&state, shell);
- XtAddCallback(state.game, XmNinputCallback, game_input, &state);
+ XtAddCallback(state.game, XmNinputCallback, game_input, &state);
/* Begin with the game in winning state */
game_reset(&state.board);
state.use_ewmh_icons = ewmh_probe_wm_icon(shell);
XtRealizeWidget(shell);
- x11_redraw_icon(&state, shell);
+ x11_redraw_goal(&state, 0, shell);
return app;
}