mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Work around an annoying GTK behaviour I noticed the other day on my
Ubuntu 12.04 machine. What seems to happen is that we set up a window containing a menu bar, a drawing area and a status bar, and set the size of the drawing area; then the window is displayed _without_ the menu bar; then we reduce the drawing area's size request to (1,1) to let the user resize the window smaller; and now GTK gets round to constructing the menu bar, and the drawing area helpfully shrinks a bit to make room for it. My fix is to set a 'shrink pending' flag instead of shrinking the drawing area's size request, and defer the actual shrink operation until the menu bar and status bar are both present. [originally from svn r9711]
This commit is contained in:
93
gtk.c
93
gtk.c
@ -117,6 +117,7 @@ struct frontend {
|
|||||||
GtkAccelGroup *accelgroup;
|
GtkAccelGroup *accelgroup;
|
||||||
GtkWidget *area;
|
GtkWidget *area;
|
||||||
GtkWidget *statusbar;
|
GtkWidget *statusbar;
|
||||||
|
GtkWidget *menubar;
|
||||||
guint statusctx;
|
guint statusctx;
|
||||||
int w, h;
|
int w, h;
|
||||||
midend *me;
|
midend *me;
|
||||||
@ -149,6 +150,7 @@ struct frontend {
|
|||||||
#ifdef OLD_FILESEL
|
#ifdef OLD_FILESEL
|
||||||
char *filesel_name;
|
char *filesel_name;
|
||||||
#endif
|
#endif
|
||||||
|
int drawing_area_shrink_pending;
|
||||||
GSList *preset_radio;
|
GSList *preset_radio;
|
||||||
int n_preset_menu_items;
|
int n_preset_menu_items;
|
||||||
int preset_threaded;
|
int preset_threaded;
|
||||||
@ -1661,6 +1663,63 @@ static void changed_preset(frontend *fe)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean not_size_allocated_yet(GtkWidget *w)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function tests whether a widget has not yet taken up space
|
||||||
|
* on the screen which it will occupy in future. (Therefore, it
|
||||||
|
* returns true only if the widget does exist but does not have a
|
||||||
|
* size allocation. A null widget is already taking up all the
|
||||||
|
* space it ever will.)
|
||||||
|
*/
|
||||||
|
GtkAllocation a;
|
||||||
|
|
||||||
|
if (!w)
|
||||||
|
return FALSE; /* nonexistent widgets aren't a problem */
|
||||||
|
|
||||||
|
gtk_widget_get_allocation(w, &a);
|
||||||
|
return a.height == 0 || a.width == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void try_shrink_drawing_area(frontend *fe)
|
||||||
|
{
|
||||||
|
if (fe->drawing_area_shrink_pending &&
|
||||||
|
!not_size_allocated_yet(fe->menubar) &&
|
||||||
|
!not_size_allocated_yet(fe->statusbar)) {
|
||||||
|
/*
|
||||||
|
* In order to permit the user to resize the window smaller as
|
||||||
|
* well as bigger, we call this function after the window size
|
||||||
|
* has ended up where we want it. This shouldn't shrink the
|
||||||
|
* window immediately; it just arranges that the next time the
|
||||||
|
* user tries to shrink it, they can.
|
||||||
|
*
|
||||||
|
* However, at puzzle creation time, we defer the first of
|
||||||
|
* these operations until after the menu bar and status bar
|
||||||
|
* are actually visible. On Ubuntu 12.04 I've found that these
|
||||||
|
* can take a while to be displayed, and that it's a mistake
|
||||||
|
* to reduce the drawing area's size allocation before they've
|
||||||
|
* turned up or else the drawing area makes room for them by
|
||||||
|
* shrinking to less than the size we intended.
|
||||||
|
*/
|
||||||
|
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), 1, 1);
|
||||||
|
fe->drawing_area_shrink_pending = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint configure_window(GtkWidget *widget,
|
||||||
|
GdkEventConfigure *event, gpointer data)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)data;
|
||||||
|
/*
|
||||||
|
* When the main puzzle window changes size, it might be because
|
||||||
|
* the menu bar or status bar has turned up after starting off
|
||||||
|
* absent, in which case we should have another go at enacting a
|
||||||
|
* pending shrink of the drawing area.
|
||||||
|
*/
|
||||||
|
try_shrink_drawing_area(fe);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void resize_fe(frontend *fe)
|
static void resize_fe(frontend *fe)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
@ -1668,18 +1727,15 @@ static void resize_fe(frontend *fe)
|
|||||||
get_size(fe, &x, &y);
|
get_size(fe, &x, &y);
|
||||||
fe->w = x;
|
fe->w = x;
|
||||||
fe->h = y;
|
fe->h = y;
|
||||||
|
fe->drawing_area_shrink_pending = FALSE;
|
||||||
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
||||||
{
|
{
|
||||||
GtkRequisition req;
|
GtkRequisition req;
|
||||||
gtk_widget_size_request(GTK_WIDGET(fe->window), &req);
|
gtk_widget_size_request(GTK_WIDGET(fe->window), &req);
|
||||||
gtk_window_resize(GTK_WINDOW(fe->window), req.width, req.height);
|
gtk_window_resize(GTK_WINDOW(fe->window), req.width, req.height);
|
||||||
}
|
}
|
||||||
/*
|
fe->drawing_area_shrink_pending = TRUE;
|
||||||
* Now that we've established the preferred size of the window,
|
try_shrink_drawing_area(fe);
|
||||||
* reduce the drawing area's size request so the user can shrink
|
|
||||||
* the window.
|
|
||||||
*/
|
|
||||||
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), 1, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void menu_preset_event(GtkMenuItem *menuitem, gpointer data)
|
static void menu_preset_event(GtkMenuItem *menuitem, gpointer data)
|
||||||
@ -2036,7 +2092,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||||||
{
|
{
|
||||||
frontend *fe;
|
frontend *fe;
|
||||||
GtkBox *vbox, *hbox;
|
GtkBox *vbox, *hbox;
|
||||||
GtkWidget *menubar, *menu, *menuitem;
|
GtkWidget *menu, *menuitem;
|
||||||
GdkPixmap *iconpm;
|
GdkPixmap *iconpm;
|
||||||
GList *iconlist;
|
GList *iconlist;
|
||||||
int x, y, n;
|
int x, y, n;
|
||||||
@ -2125,12 +2181,12 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||||||
gtk_box_pack_start(vbox, GTK_WIDGET(hbox), FALSE, FALSE, 0);
|
gtk_box_pack_start(vbox, GTK_WIDGET(hbox), FALSE, FALSE, 0);
|
||||||
gtk_widget_show(GTK_WIDGET(hbox));
|
gtk_widget_show(GTK_WIDGET(hbox));
|
||||||
|
|
||||||
menubar = gtk_menu_bar_new();
|
fe->menubar = gtk_menu_bar_new();
|
||||||
gtk_box_pack_start(hbox, menubar, TRUE, TRUE, 0);
|
gtk_box_pack_start(hbox, fe->menubar, TRUE, TRUE, 0);
|
||||||
gtk_widget_show(menubar);
|
gtk_widget_show(fe->menubar);
|
||||||
|
|
||||||
menuitem = gtk_menu_item_new_with_mnemonic("_Game");
|
menuitem = gtk_menu_item_new_with_mnemonic("_Game");
|
||||||
gtk_container_add(GTK_CONTAINER(menubar), menuitem);
|
gtk_container_add(GTK_CONTAINER(fe->menubar), menuitem);
|
||||||
gtk_widget_show(menuitem);
|
gtk_widget_show(menuitem);
|
||||||
|
|
||||||
menu = gtk_menu_new();
|
menu = gtk_menu_new();
|
||||||
@ -2169,7 +2225,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
menuitem = gtk_menu_item_new_with_mnemonic("_Type");
|
menuitem = gtk_menu_item_new_with_mnemonic("_Type");
|
||||||
gtk_container_add(GTK_CONTAINER(menubar), menuitem);
|
gtk_container_add(GTK_CONTAINER(fe->menubar), menuitem);
|
||||||
gtk_widget_show(menuitem);
|
gtk_widget_show(menuitem);
|
||||||
|
|
||||||
submenu = gtk_menu_new();
|
submenu = gtk_menu_new();
|
||||||
@ -2248,7 +2304,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Exit", 'q');
|
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Exit", 'q');
|
||||||
|
|
||||||
menuitem = gtk_menu_item_new_with_mnemonic("_Help");
|
menuitem = gtk_menu_item_new_with_mnemonic("_Help");
|
||||||
gtk_container_add(GTK_CONTAINER(menubar), menuitem);
|
gtk_container_add(GTK_CONTAINER(fe->menubar), menuitem);
|
||||||
gtk_widget_show(menuitem);
|
gtk_widget_show(menuitem);
|
||||||
|
|
||||||
menu = gtk_menu_new();
|
menu = gtk_menu_new();
|
||||||
@ -2328,6 +2384,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||||||
GTK_WIDGET_UNSET_FLAGS(fe->area, GTK_DOUBLE_BUFFERED);
|
GTK_WIDGET_UNSET_FLAGS(fe->area, GTK_DOUBLE_BUFFERED);
|
||||||
#endif
|
#endif
|
||||||
get_size(fe, &x, &y);
|
get_size(fe, &x, &y);
|
||||||
|
fe->drawing_area_shrink_pending = FALSE;
|
||||||
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
||||||
fe->w = x;
|
fe->w = x;
|
||||||
fe->h = y;
|
fe->h = y;
|
||||||
@ -2361,6 +2418,8 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||||||
GTK_SIGNAL_FUNC(map_window), fe);
|
GTK_SIGNAL_FUNC(map_window), fe);
|
||||||
gtk_signal_connect(GTK_OBJECT(fe->area), "configure_event",
|
gtk_signal_connect(GTK_OBJECT(fe->area), "configure_event",
|
||||||
GTK_SIGNAL_FUNC(configure_area), fe);
|
GTK_SIGNAL_FUNC(configure_area), fe);
|
||||||
|
gtk_signal_connect(GTK_OBJECT(fe->window), "configure_event",
|
||||||
|
GTK_SIGNAL_FUNC(configure_window), fe);
|
||||||
|
|
||||||
gtk_widget_add_events(GTK_WIDGET(fe->area),
|
gtk_widget_add_events(GTK_WIDGET(fe->area),
|
||||||
GDK_BUTTON_PRESS_MASK |
|
GDK_BUTTON_PRESS_MASK |
|
||||||
@ -2386,12 +2445,8 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||||||
gtk_widget_show(fe->area);
|
gtk_widget_show(fe->area);
|
||||||
gtk_widget_show(fe->window);
|
gtk_widget_show(fe->window);
|
||||||
|
|
||||||
/*
|
fe->drawing_area_shrink_pending = TRUE;
|
||||||
* Now that we've established the preferred size of the window,
|
try_shrink_drawing_area(fe);
|
||||||
* reduce the drawing area's size request so the user can shrink
|
|
||||||
* the window.
|
|
||||||
*/
|
|
||||||
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), 1, 1);
|
|
||||||
set_window_background(fe, 0);
|
set_window_background(fe, 0);
|
||||||
|
|
||||||
return fe;
|
return fe;
|
||||||
|
Reference in New Issue
Block a user