X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/48dcdd627698354063fa1b551cfa1917dea1b25e..7b72c68e954905d8127b3eb964e798a259db5e15:/gtk.c diff --git a/gtk.c b/gtk.c index 84e5e72..37dcf23 100644 --- a/gtk.c +++ b/gtk.c @@ -76,8 +76,11 @@ struct frontend { config_item *cfg; int cfg_which, cfgret; GtkWidget *cfgbox; - char *paste_data; + void *paste_data; int paste_data_len; + char *laststatus; + int pw, ph; /* pixmap size (w, h are area size) */ + int ox, oy; /* offset of pixmap in drawing area */ }; void get_random_seed(void **randseed, int *randseedsize) @@ -103,9 +106,14 @@ void status_bar(frontend *fe, char *text) assert(fe->statusbar); rewritten = midend_rewrite_statusbar(fe->me, text); - gtk_statusbar_pop(GTK_STATUSBAR(fe->statusbar), fe->statusctx); - gtk_statusbar_push(GTK_STATUSBAR(fe->statusbar), fe->statusctx, rewritten); - sfree(rewritten); + if (!fe->laststatus || strcmp(rewritten, fe->laststatus)) { + gtk_statusbar_pop(GTK_STATUSBAR(fe->statusbar), fe->statusctx); + gtk_statusbar_push(GTK_STATUSBAR(fe->statusbar), fe->statusctx, rewritten); + sfree(fe->laststatus); + fe->laststatus = rewritten; + } else { + sfree(rewritten); + } } void start_draw(frontend *fe) @@ -305,7 +313,7 @@ void end_draw(frontend *fe) fe->area->style->fg_gc[GTK_WIDGET_STATE(fe->area)], fe->pixmap, fe->bbox_l, fe->bbox_u, - fe->bbox_l, fe->bbox_u, + fe->ox + fe->bbox_l, fe->oy + fe->bbox_u, fe->bbox_r - fe->bbox_l, fe->bbox_d - fe->bbox_u); } } @@ -381,17 +389,18 @@ static gint button_event(GtkWidget *widget, GdkEventButton *event, if (event->button == 2 || (event->state & GDK_SHIFT_MASK)) button = MIDDLE_BUTTON; + else if (event->button == 3 || (event->state & GDK_MOD1_MASK)) + button = RIGHT_BUTTON; else if (event->button == 1) button = LEFT_BUTTON; - else if (event->button == 3) - button = RIGHT_BUTTON; else return FALSE; /* don't even know what button! */ if (event->type == GDK_BUTTON_RELEASE) button += LEFT_RELEASE - LEFT_BUTTON; - if (!midend_process_key(fe->me, event->x, event->y, button)) + if (!midend_process_key(fe->me, event->x - fe->ox, + event->y - fe->oy, button)) gtk_widget_destroy(fe->window); return TRUE; @@ -415,7 +424,8 @@ static gint motion_event(GtkWidget *widget, GdkEventMotion *event, else return FALSE; /* don't even know what button! */ - if (!midend_process_key(fe->me, event->x, event->y, button)) + if (!midend_process_key(fe->me, event->x - fe->ox, + event->y - fe->oy, button)) gtk_widget_destroy(fe->window); return TRUE; @@ -430,7 +440,7 @@ static gint expose_area(GtkWidget *widget, GdkEventExpose *event, gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], fe->pixmap, - event->area.x, event->area.y, + event->area.x - fe->ox, event->area.y - fe->oy, event->area.x, event->area.y, event->area.width, event->area.height); } @@ -457,18 +467,27 @@ static gint configure_area(GtkWidget *widget, { frontend *fe = (frontend *)data; GdkGC *gc; + int x, y; if (fe->pixmap) gdk_pixmap_unref(fe->pixmap); - fe->pixmap = gdk_pixmap_new(widget->window, fe->w, fe->h, -1); + x = fe->w = event->width; + y = fe->h = event->height; + midend_size(fe->me, &x, &y, TRUE); + fe->pw = x; + fe->ph = y; + fe->ox = (fe->w - fe->pw) / 2; + fe->oy = (fe->h - fe->ph) / 2; + + fe->pixmap = gdk_pixmap_new(widget->window, fe->pw, fe->ph, -1); gc = gdk_gc_new(fe->area->window); gdk_gc_set_foreground(gc, &fe->colours[0]); - gdk_draw_rectangle(fe->pixmap, gc, 1, 0, 0, fe->w, fe->h); + gdk_draw_rectangle(fe->pixmap, gc, 1, 0, 0, fe->pw, fe->ph); gdk_gc_unref(gc); - midend_redraw(fe->me); + midend_force_redraw(fe->me); return TRUE; } @@ -560,7 +579,7 @@ void message_box(GtkWidget *parent, char *title, char *msg, int centre) GTK_SIGNAL_FUNC(win_key_press), ok); gtk_window_set_modal(GTK_WINDOW(window), TRUE); gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(parent)); - //set_transient_window_pos(parent, window); + /* set_transient_window_pos(parent, window); */ gtk_widget_show(window); gtk_main(); } @@ -792,7 +811,7 @@ static int get_config(frontend *fe, int which) gtk_window_set_modal(GTK_WINDOW(fe->cfgbox), TRUE); gtk_window_set_transient_for(GTK_WINDOW(fe->cfgbox), GTK_WINDOW(fe->window)); - //set_transient_window_pos(fe->window, fe->cfgbox); + /* set_transient_window_pos(fe->window, fe->cfgbox); */ gtk_widget_show(fe->cfgbox); gtk_main(); @@ -810,6 +829,34 @@ static void menu_key_event(GtkMenuItem *menuitem, gpointer data) gtk_widget_destroy(fe->window); } +static void get_size(frontend *fe, int *px, int *py) +{ + int x, y; + + /* + * Currently I don't want to make the GTK port scale large + * puzzles to fit on the screen. This is because X does permit + * extremely large windows and many window managers provide a + * means of navigating round them, and the users I consulted + * before deciding said that they'd rather have enormous puzzle + * windows spanning multiple screen pages than have them + * shrunk. I could change my mind later or introduce + * configurability; this would be the place to do so, by + * replacing the initial values of x and y with the screen + * dimensions. + */ + x = INT_MAX; + y = INT_MAX; + midend_size(fe->me, &x, &y, FALSE); + *px = x; + *py = y; +} + +#if !GTK_CHECK_VERSION(2,0,0) +#define gtk_window_resize(win, x, y) \ + gdk_window_resize(GTK_WIDGET(win)->window, x, y) +#endif + static void menu_preset_event(GtkMenuItem *menuitem, gpointer data) { frontend *fe = (frontend *)data; @@ -819,10 +866,11 @@ static void menu_preset_event(GtkMenuItem *menuitem, gpointer data) midend_set_params(fe->me, params); midend_new_game(fe->me); - midend_size(fe->me, &x, &y); - gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y); + get_size(fe, &x, &y); fe->w = x; fe->h = y; + gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y); + gtk_window_resize(GTK_WINDOW(fe->window), 1, 1); } GdkAtom compound_text_atom, utf8_string_atom; @@ -830,6 +878,8 @@ int paste_initialised = FALSE; void init_paste() { + unsigned char empty[] = { 0 }; + if (paste_initialised) return; @@ -843,21 +893,21 @@ void init_paste() * ICCCM, we must do this before we start using cut buffers. */ XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER0, XA_STRING, 8, PropModeAppend, "", 0); + XA_CUT_BUFFER0, XA_STRING, 8, PropModeAppend, empty, 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER1, XA_STRING, 8, PropModeAppend, "", 0); + XA_CUT_BUFFER1, XA_STRING, 8, PropModeAppend, empty, 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER2, XA_STRING, 8, PropModeAppend, "", 0); + XA_CUT_BUFFER2, XA_STRING, 8, PropModeAppend, empty, 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER3, XA_STRING, 8, PropModeAppend, "", 0); + XA_CUT_BUFFER3, XA_STRING, 8, PropModeAppend, empty, 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER4, XA_STRING, 8, PropModeAppend, "", 0); + XA_CUT_BUFFER4, XA_STRING, 8, PropModeAppend, empty, 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER5, XA_STRING, 8, PropModeAppend, "", 0); + XA_CUT_BUFFER5, XA_STRING, 8, PropModeAppend, empty, 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER6, XA_STRING, 8, PropModeAppend, "", 0); + XA_CUT_BUFFER6, XA_STRING, 8, PropModeAppend, empty, 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER7, XA_STRING, 8, PropModeAppend, "", 0); + XA_CUT_BUFFER7, XA_STRING, 8, PropModeAppend, empty, 0); } /* Store data in a cut-buffer. */ @@ -961,10 +1011,11 @@ static void menu_config_event(GtkMenuItem *menuitem, gpointer data) return; midend_new_game(fe->me); - midend_size(fe->me, &x, &y); - gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y); + get_size(fe, &x, &y); fe->w = x; fe->h = y; + gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y); + gtk_window_resize(GTK_WINDOW(fe->window), 1, 1); } static void menu_about_event(GtkMenuItem *menuitem, gpointer data) @@ -1011,7 +1062,11 @@ static frontend *new_window(char *game_id, char **error) fe = snew(frontend); + fe->timer_active = FALSE; + fe->timer_id = -1; + fe->me = midend_new(fe, &thegame); + if (game_id) { *error = midend_game_id(fe->me, game_id); if (*error) { @@ -1189,18 +1244,18 @@ static frontend *new_window(char *game_id, char **error) fe->statusbar = NULL; fe->area = gtk_drawing_area_new(); - midend_size(fe->me, &x, &y); + get_size(fe, &x, &y); gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y); fe->w = x; fe->h = y; - gtk_box_pack_end(vbox, fe->area, FALSE, FALSE, 0); + gtk_box_pack_end(vbox, fe->area, TRUE, TRUE, 0); fe->pixmap = NULL; fe->fonts = NULL; fe->nfonts = fe->fontsize = 0; - fe->timer_active = FALSE; + fe->laststatus = NULL; fe->paste_data = NULL; fe->paste_data_len = 0; @@ -1234,6 +1289,9 @@ static frontend *new_window(char *game_id, char **error) gtk_widget_show(fe->area); gtk_widget_show(fe->window); + gdk_window_set_background(fe->area->window, &fe->colours[0]); + gdk_window_set_background(fe->window->window, &fe->colours[0]); + return fe; } @@ -1307,7 +1365,7 @@ int main(int argc, char **argv) while (n-- > 0) { game_aux_info *aux = NULL; - char *desc = thegame.new_desc(par, rs, &aux); + char *desc = thegame.new_desc(par, rs, &aux, FALSE); printf("%s:%s\n", parstr, desc); sfree(desc); if (aux)