From ab8bb6ad208670b587d23f55c9edb5ba8c754050 Mon Sep 17 00:00:00 2001 From: Jim Evins Date: Mon, 26 Oct 2009 20:12:06 -0400 Subject: [PATCH] Improved menu positioning functions Use requisition instead of allocation for menu size (the allocation does not exist for a newly realized menu, so the position is not always right the first time it is popped up, causing a mangled menu position with ugly scroll buttons.) Query for the actual screen of "this" instead of blindly using the default screen. --- src/color-combo-button.c | 82 ++++++++++++++++++++++++++++----------- src/color-combo.c | 84 ++++++++++++++++++++++++++++------------ src/field-button.c | 84 ++++++++++++++++++++++++++++------------ src/font-combo.c | 84 ++++++++++++++++++++++++++++------------ 4 files changed, 239 insertions(+), 95 deletions(-) diff --git a/src/color-combo-button.c b/src/color-combo-button.c index 1c83ac82..3593275a 100644 --- a/src/color-combo-button.c +++ b/src/color-combo-button.c @@ -296,41 +296,77 @@ button_clicked_cb( glColorComboButton *this ) /* Menu positioning function. */ /*****************************************************************************/ static void -menu_position_function (GtkMenu *menu, - gint *x, - gint *y, - gboolean *push_in, - gpointer user_data) +menu_position_function (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + glColorComboButton *this) { - glColorComboButton *this = GL_COLOR_COMBO_BUTTON (user_data); + GdkScreen *screen; + gint w_screen, h_screen; GdkWindow *window; - gint x1, y1; - gint menu_h, menu_w; - + gint x_window, y_window; + GtkAllocation *allocation; + gint x_this, y_this, h_this; + GtkRequisition menu_requisition; + gint h_menu, w_menu; + + /* + * Screen size + */ + screen = gtk_widget_get_screen (GTK_WIDGET (this)); + w_screen = gdk_screen_get_width (screen); + h_screen = gdk_screen_get_height (screen); + + /* + * Absolute position of "this" window on screen. + */ window = gtk_widget_get_window (GTK_WIDGET (this)); - - gdk_window_get_origin (window, &x1, &y1); - *x = x1 + GTK_WIDGET (this)->allocation.x; - *y = y1 + GTK_WIDGET (this)->allocation.y + - GTK_WIDGET (this)->allocation.height; + gdk_window_get_origin (window, &x_window, &y_window); + + /* + * Position and size of "this" inside window + */ + allocation = >K_WIDGET (this)->allocation; + x_this = allocation->x; + y_this = allocation->y; + h_this = allocation->height; + + /* + * Size of menu. + */ + gtk_widget_size_request (this->priv->menu, &menu_requisition); + h_menu = menu_requisition.height; + w_menu = menu_requisition.width; + + /* + * Default position anchored to lower left corner of "this". + */ + *x = x_window + x_this; + *y = y_window + y_this + h_this; - menu_h = this->priv->menu->allocation.height; - menu_w = this->priv->menu->allocation.width; - - if ((*y + menu_h) > gdk_screen_height ()) + /* + * Adjust vertical position if menu if extends past bottom of screen. + */ + if ( (*y + h_menu) > h_screen ) { - *y = y1 + GTK_WIDGET (this)->allocation.y - menu_h; + *y = y_window + y_this - h_menu; + if ( *y < 0 ) { - *y = gdk_screen_height () - menu_h; + *y = h_screen - h_menu; } } - if ((*x + menu_w) > gdk_screen_width ()) + /* + * Adjust horizontal position if menu if extends past edge of screen. + */ + if ( (*x + w_menu) > w_screen ) { - *x = gdk_screen_width () - menu_w; + *x = w_screen - w_menu; } + *push_in = TRUE; } @@ -358,7 +394,7 @@ dropdown_button_press_event_cb (GtkWidget *widget, gtk_menu_popup (GTK_MENU (this->priv->menu), NULL, NULL, - menu_position_function, this, + (GtkMenuPositionFunc)menu_position_function, this, event->button, event->time); break; diff --git a/src/color-combo.c b/src/color-combo.c index a5e99d22..0334efdc 100644 --- a/src/color-combo.c +++ b/src/color-combo.c @@ -238,41 +238,77 @@ gl_color_combo_get_color (glColorCombo *this, /* Menu positioning function. */ /*****************************************************************************/ static void -menu_position_function (GtkMenu *menu, - gint *x, - gint *y, - gboolean *push_in, - gpointer user_data) +menu_position_function (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + glColorCombo *this) { - glColorCombo *this = GL_COLOR_COMBO (user_data); - GdkWindow *window; - gint x1, y1; - gint menu_h, menu_w; - + GdkScreen *screen; + gint w_screen, h_screen; + GdkWindow *window; + gint x_window, y_window; + GtkAllocation *allocation; + gint x_this, y_this, h_this; + GtkRequisition menu_requisition; + gint h_menu, w_menu; + + /* + * Screen size + */ + screen = gtk_widget_get_screen (GTK_WIDGET (this)); + w_screen = gdk_screen_get_width (screen); + h_screen = gdk_screen_get_height (screen); + + /* + * Absolute position of "this" window on screen. + */ window = gtk_widget_get_window (GTK_WIDGET (this)); - - gdk_window_get_origin (window, &x1, &y1); - *x = x1 + GTK_WIDGET (this)->allocation.x; - *y = y1 + GTK_WIDGET (this)->allocation.y + - GTK_WIDGET (this)->allocation.height; + gdk_window_get_origin (window, &x_window, &y_window); + + /* + * Position and size of "this" inside window + */ + allocation = >K_WIDGET (this)->allocation; + x_this = allocation->x; + y_this = allocation->y; + h_this = allocation->height; + + /* + * Size of menu. + */ + gtk_widget_size_request (this->priv->menu, &menu_requisition); + h_menu = menu_requisition.height; + w_menu = menu_requisition.width; + + /* + * Default position anchored to lower left corner of "this". + */ + *x = x_window + x_this; + *y = y_window + y_this + h_this; - menu_h = this->priv->menu->allocation.height; - menu_w = this->priv->menu->allocation.width; - - if ((*y + menu_h) > gdk_screen_height ()) + /* + * Adjust vertical position if menu if extends past bottom of screen. + */ + if ( (*y + h_menu) > h_screen ) { - *y = y1 + GTK_WIDGET (this)->allocation.y - menu_h; + *y = y_window + y_this - h_menu; + if ( *y < 0 ) { - *y = gdk_screen_height () - menu_h; + *y = h_screen - h_menu; } } - if ((*x + menu_w) > gdk_screen_width ()) + /* + * Adjust horizontal position if menu if extends past edge of screen. + */ + if ( (*x + w_menu) > w_screen ) { - *x = gdk_screen_width () - menu_w; + *x = w_screen - w_menu; } + *push_in = TRUE; } @@ -293,7 +329,7 @@ button_press_event_cb (GtkWidget *widget, gtk_menu_popup (GTK_MENU (this->priv->menu), NULL, NULL, - menu_position_function, this, + (GtkMenuPositionFunc)menu_position_function, this, event->button, event->time); break; diff --git a/src/field-button.c b/src/field-button.c index a2892728..4000d41b 100644 --- a/src/field-button.c +++ b/src/field-button.c @@ -192,41 +192,77 @@ gl_field_button_set_keys (glFieldButton *this, /* Menu positioning function. */ /*****************************************************************************/ static void -menu_position_function (GtkMenu *menu, - gint *x, - gint *y, - gboolean *push_in, - gpointer user_data) +menu_position_function (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + glFieldButton *this) { - glFieldButton *this = GL_FIELD_BUTTON (user_data); - GdkWindow *window; - gint x1, y1; - gint menu_h, menu_w; - + GdkScreen *screen; + gint w_screen, h_screen; + GdkWindow *window; + gint x_window, y_window; + GtkAllocation *allocation; + gint x_this, y_this, h_this; + GtkRequisition menu_requisition; + gint h_menu, w_menu; + + /* + * Screen size + */ + screen = gtk_widget_get_screen (GTK_WIDGET (this)); + w_screen = gdk_screen_get_width (screen); + h_screen = gdk_screen_get_height (screen); + + /* + * Absolute position of "this" window on screen. + */ window = gtk_widget_get_window (GTK_WIDGET (this)); - - gdk_window_get_origin (window, &x1, &y1); - *x = x1 + GTK_WIDGET (this)->allocation.x; - *y = y1 + GTK_WIDGET (this)->allocation.y + - GTK_WIDGET (this)->allocation.height; + gdk_window_get_origin (window, &x_window, &y_window); + + /* + * Position and size of "this" inside window + */ + allocation = >K_WIDGET (this)->allocation; + x_this = allocation->x; + y_this = allocation->y; + h_this = allocation->height; + + /* + * Size of menu. + */ + gtk_widget_size_request (this->priv->menu, &menu_requisition); + h_menu = menu_requisition.height; + w_menu = menu_requisition.width; + + /* + * Default position anchored to lower left corner of "this". + */ + *x = x_window + x_this; + *y = y_window + y_this + h_this; - menu_h = this->priv->menu->allocation.height; - menu_w = this->priv->menu->allocation.width; - - if ((*y + menu_h) > gdk_screen_height ()) + /* + * Adjust vertical position if menu if extends past bottom of screen. + */ + if ( (*y + h_menu) > h_screen ) { - *y = y1 + GTK_WIDGET (this)->allocation.y - menu_h; + *y = y_window + y_this - h_menu; + if ( *y < 0 ) { - *y = gdk_screen_height () - menu_h; + *y = h_screen - h_menu; } } - if ((*x + menu_w) > gdk_screen_width ()) + /* + * Adjust horizontal position if menu if extends past edge of screen. + */ + if ( (*x + w_menu) > w_screen ) { - *x = gdk_screen_width () - menu_w; + *x = w_screen - w_menu; } + *push_in = TRUE; } @@ -247,7 +283,7 @@ button_press_event_cb (GtkWidget *widget, gtk_menu_popup (GTK_MENU (this->priv->menu), NULL, NULL, - menu_position_function, this, + (GtkMenuPositionFunc)menu_position_function, this, event->button, event->time); break; diff --git a/src/font-combo.c b/src/font-combo.c index d094497d..49b0d7ee 100644 --- a/src/font-combo.c +++ b/src/font-combo.c @@ -219,41 +219,77 @@ gl_font_combo_get_family (glFontCombo *this) /* Menu positioning function. */ /*****************************************************************************/ static void -menu_position_function (GtkMenu *menu, - gint *x, - gint *y, - gboolean *push_in, - gpointer user_data) +menu_position_function (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + glFontCombo *this) { - glFontCombo *this = GL_FONT_COMBO (user_data); - GdkWindow *window; - gint x1, y1; - gint menu_h, menu_w; - + GdkScreen *screen; + gint w_screen, h_screen; + GdkWindow *window; + gint x_window, y_window; + GtkAllocation *allocation; + gint x_this, y_this, h_this; + GtkRequisition menu_requisition; + gint h_menu, w_menu; + + /* + * Screen size + */ + screen = gtk_widget_get_screen (GTK_WIDGET (this)); + w_screen = gdk_screen_get_width (screen); + h_screen = gdk_screen_get_height (screen); + + /* + * Absolute position of "this" window on screen. + */ window = gtk_widget_get_window (GTK_WIDGET (this)); - - gdk_window_get_origin (window, &x1, &y1); - *x = x1 + GTK_WIDGET (this)->allocation.x; - *y = y1 + GTK_WIDGET (this)->allocation.y + - GTK_WIDGET (this)->allocation.height; + gdk_window_get_origin (window, &x_window, &y_window); + + /* + * Position and size of "this" inside window + */ + allocation = >K_WIDGET (this)->allocation; + x_this = allocation->x; + y_this = allocation->y; + h_this = allocation->height; + + /* + * Size of menu. + */ + gtk_widget_size_request (this->priv->menu, &menu_requisition); + h_menu = menu_requisition.height; + w_menu = menu_requisition.width; + + /* + * Default position anchored to lower left corner of "this". + */ + *x = x_window + x_this; + *y = y_window + y_this + h_this; - menu_h = this->priv->menu->allocation.height; - menu_w = this->priv->menu->allocation.width; - - if ((*y + menu_h) > gdk_screen_height ()) + /* + * Adjust vertical position if menu if extends past bottom of screen. + */ + if ( (*y + h_menu) > h_screen ) { - *y = y1 + GTK_WIDGET (this)->allocation.y - menu_h; + *y = y_window + y_this - h_menu; + if ( *y < 0 ) { - *y = gdk_screen_height () - menu_h; + *y = h_screen - h_menu; } } - if ((*x + menu_w) > gdk_screen_width ()) + /* + * Adjust horizontal position if menu if extends past edge of screen. + */ + if ( (*x + w_menu) > w_screen ) { - *x = gdk_screen_width () - menu_w; + *x = w_screen - w_menu; } + *push_in = TRUE; } @@ -274,7 +310,7 @@ button_press_event_cb (GtkWidget *widget, gtk_menu_popup (GTK_MENU (this->priv->menu), NULL, NULL, - menu_position_function, this, + (GtkMenuPositionFunc)menu_position_function, this, event->button, event->time); break; -- 2.39.5