[gtk+/wip/attente/popup-at: 5/5] port to new gtk_menu_popup_at_* () functions



commit 152f85ee08a152e4b784fba08a6173890c8c69e7
Author: William Hua <william hua canonical com>
Date:   Wed Jun 15 11:03:49 2016 -0400

    port to new gtk_menu_popup_at_* () functions

 gtk/gtkmenuitem.c |  130 ++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 100 insertions(+), 30 deletions(-)
---
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
index 7910806..fa47b55 100644
--- a/gtk/gtkmenuitem.c
+++ b/gtk/gtkmenuitem.c
@@ -171,11 +171,6 @@ static gboolean gtk_menu_item_mnemonic_activate     (GtkWidget   *widget,
 
 static void gtk_menu_item_ensure_label   (GtkMenuItem      *menu_item);
 static gint gtk_menu_item_popup_timeout  (gpointer          data);
-static void gtk_menu_item_position_menu  (GtkMenu          *menu,
-                                          gint             *x,
-                                          gint             *y,
-                                          gboolean         *push_in,
-                                          gpointer          user_data);
 static void gtk_menu_item_show_all       (GtkWidget        *widget);
 
 static void gtk_menu_item_forall         (GtkContainer    *container,
@@ -1909,11 +1904,17 @@ free_timeval (GTimeVal *val)
 }
 
 static void
-gtk_menu_item_real_popup_submenu (GtkWidget *widget,
-                                  gboolean   remember_exact_time)
+gtk_menu_item_real_popup_submenu (GtkWidget      *widget,
+                                  const GdkEvent *trigger_event,
+                                  gboolean        remember_exact_time)
 {
   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
   GtkMenuItemPrivate *priv = menu_item->priv;
+  GtkStyleContext *context;
+  GtkBorder parent_padding;
+  GtkBorder menu_padding;
+  gint horizontal_offset;
+  gint vertical_offset;
   GtkWidget *parent;
 
   parent = gtk_widget_get_parent (widget);
@@ -1921,7 +1922,6 @@ gtk_menu_item_real_popup_submenu (GtkWidget *widget,
   if (gtk_widget_is_sensitive (priv->submenu) && parent)
     {
       gboolean take_focus;
-      GtkMenuPositionFunc menu_position_func;
 
       take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (parent));
       gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (priv->submenu), take_focus);
@@ -1942,24 +1942,80 @@ gtk_menu_item_real_popup_submenu (GtkWidget *widget,
                              "gtk-menu-exact-popup-time", NULL);
         }
 
-      /* gtk_menu_item_position_menu positions the submenu from the
-       * menuitems position. If the menuitem doesn't have a window,
-       * that doesn't work. In that case we use the default
-       * positioning function instead which places the submenu at the
+      /* Position the submenu from the menuitems position. If the menuitem
+       * doesn't have a window, that doesn't work. In that case we use the
+       * default positioning function instead which places the submenu at the
        * mouse cursor.
        */
       if (gtk_widget_get_window (widget))
-        menu_position_func = gtk_menu_item_position_menu;
+        {
+          switch (priv->submenu_placement)
+            {
+            case GTK_TOP_BOTTOM:
+              g_object_set (priv->submenu,
+                            "anchor-hints", GDK_ANCHOR_FLIP_Y |
+                                            GDK_ANCHOR_SLIDE |
+                                            GDK_ANCHOR_RESIZE,
+                            "menu-type-hint", priv->from_menubar ?
+                                              GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU :
+                                              GDK_WINDOW_TYPE_HINT_POPUP_MENU,
+                            NULL);
+              gtk_menu_popup_at_widget (GTK_MENU (priv->submenu),
+                                        widget,
+                                        GDK_GRAVITY_SOUTH_WEST,
+                                        GDK_GRAVITY_NORTH_WEST,
+                                        trigger_event);
+              break;
+
+            case GTK_LEFT_RIGHT:
+              gtk_widget_style_get (priv->submenu,
+                                    "horizontal-offset", &horizontal_offset,
+                                    "vertical-offset", &vertical_offset,
+                                    NULL);
+
+              context = gtk_widget_get_style_context (parent);
+              gtk_style_context_get_padding (context, gtk_style_context_get_state (context), 
&parent_padding);
+              context = gtk_widget_get_style_context (priv->submenu);
+              gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &menu_padding);
+
+              g_object_set (priv->submenu,
+                            "anchor-hints", GDK_ANCHOR_FLIP_X |
+                                            GDK_ANCHOR_SLIDE |
+                                            GDK_ANCHOR_RESIZE,
+                            "rect-anchor-dy", vertical_offset - menu_padding.top,
+                            NULL);
+
+              switch (priv->submenu_direction)
+                {
+                case GTK_DIRECTION_RIGHT:
+                  g_object_set (priv->submenu,
+                                "rect-anchor-dx", horizontal_offset + parent_padding.right + 
menu_padding.left,
+                                NULL);
+                  gtk_menu_popup_at_widget (GTK_MENU (priv->submenu),
+                                            widget,
+                                            GDK_GRAVITY_NORTH_EAST,
+                                            GDK_GRAVITY_NORTH_WEST,
+                                            trigger_event);
+                  break;
+
+                case GTK_DIRECTION_LEFT:
+                  g_object_set (priv->submenu,
+                                "rect-anchor-dx", -(horizontal_offset + parent_padding.left + 
menu_padding.right),
+                                NULL);
+                  gtk_menu_popup_at_widget (GTK_MENU (priv->submenu),
+                                            widget,
+                                            GDK_GRAVITY_NORTH_WEST,
+                                            GDK_GRAVITY_NORTH_EAST,
+                                            trigger_event);
+                  break;
+                }
+
+              break;
+            }
+        }
       else
-        menu_position_func = NULL;
-
-      gtk_menu_popup (GTK_MENU (priv->submenu),
-                      parent,
-                      widget,
-                      menu_position_func,
-                      menu_item,
-                      GTK_MENU_SHELL (parent)->priv->button,
-                      0);
+        gtk_menu_popup_at_pointer (GTK_MENU (priv->submenu),
+                                   trigger_event);
     }
 
   /* Enable themeing of the parent menu item depending on whether
@@ -1968,10 +2024,17 @@ gtk_menu_item_real_popup_submenu (GtkWidget *widget,
   gtk_widget_queue_draw (widget);
 }
 
+typedef struct
+{
+  GtkMenuItem *menu_item;
+  GdkEvent    *trigger_event;
+} PopupInfo;
+
 static gint
 gtk_menu_item_popup_timeout (gpointer data)
 {
-  GtkMenuItem *menu_item = GTK_MENU_ITEM (data);
+  PopupInfo *info = data;
+  GtkMenuItem *menu_item = info->menu_item;
   GtkMenuItemPrivate *priv = menu_item->priv;
   GtkWidget *parent;
 
@@ -1980,13 +2043,16 @@ gtk_menu_item_popup_timeout (gpointer data)
   if ((GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->priv->active) ||
       (GTK_IS_MENU (parent) && GTK_MENU (parent)->priv->torn_off))
     {
-      gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), TRUE);
+      gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), info->trigger_event, TRUE);
       if (priv->timer_from_keypress && priv->submenu)
         GTK_MENU_SHELL (priv->submenu)->priv->ignore_enter = TRUE;
     }
 
   priv->timer = 0;
 
+  gdk_event_free (info->trigger_event);
+  g_slice_free (PopupInfo, info);
+
   return FALSE;
 }
 
@@ -2008,6 +2074,7 @@ _gtk_menu_item_popup_submenu (GtkWidget *widget,
 {
   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
   GtkMenuItemPrivate *priv = menu_item->priv;
+  GdkEvent *event = gtk_get_current_event ();
 
   if (priv->timer)
     {
@@ -2022,11 +2089,14 @@ _gtk_menu_item_popup_submenu (GtkWidget *widget,
 
       if (popup_delay > 0)
         {
-          GdkEvent *event = gtk_get_current_event ();
+          PopupInfo *info = g_slice_new (PopupInfo);
+
+          info->menu_item = menu_item;
+          info->trigger_event = event;
 
           priv->timer = gdk_threads_add_timeout (popup_delay,
                                                  gtk_menu_item_popup_timeout,
-                                                 menu_item);
+                                                 info);
           g_source_set_name_by_id (priv->timer, "[gtk+] gtk_menu_item_popup_timeout");
 
           if (event &&
@@ -2036,14 +2106,14 @@ _gtk_menu_item_popup_submenu (GtkWidget *widget,
           else
             priv->timer_from_keypress = FALSE;
 
-          if (event)
-            gdk_event_free (event);
-
           return;
         }
     }
 
-  gtk_menu_item_real_popup_submenu (widget, FALSE);
+  gtk_menu_item_real_popup_submenu (widget, event, FALSE);
+
+  if (event)
+    gdk_event_free (event);
 }
 
 void


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