[glabels] Improved menu positioning functions



commit ab8bb6ad208670b587d23f55c9edb5ba8c754050
Author: Jim Evins <evins snaught com>
Date:   Mon Oct 26 20:12:06 2009 -0400

    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 1c83ac8..3593275 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 = &GTK_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 a5e99d2..0334efd 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 = &GTK_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 a289272..4000d41 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 = &GTK_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 d094497..49b0d7e 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 = &GTK_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;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]