[gtk+/wip/attach-params: 5/20] gtkmenu: add gtk_menu_popup_with_params ()



commit feb803f649b568c2b28fce52672e6a632b9c2b79
Author: William Hua <william hua canonical com>
Date:   Wed Jan 20 02:20:20 2016 -0600

    gtkmenu: add gtk_menu_popup_with_params ()
    
    https://bugzilla.gnome.org/show_bug.cgi?id=756579

 docs/reference/gtk/gtk3-sections.txt |    3 +
 gtk/gtkmenu.c                        |  538 ++++++++++++++++++++++++++++------
 gtk/gtkmenu.h                        |   25 ++
 gtk/gtkmenuprivate.h                 |    3 +
 4 files changed, 480 insertions(+), 89 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index fd7c85a..8305cde 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -2241,6 +2241,9 @@ gtk_menu_new_from_model
 gtk_menu_set_screen
 gtk_menu_reorder_child
 gtk_menu_attach
+gtk_menu_create_params
+gtk_menu_update_scroll_offset
+gtk_menu_popup_with_params
 gtk_menu_popup_for_device
 gtk_menu_popup
 gtk_menu_set_accel_group
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index cdf2aec..9ae1568 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -1538,53 +1538,17 @@ associate_menu_grab_transfer_window (GtkMenu *menu)
   g_object_set_data (G_OBJECT (toplevel_window), I_("gdk-attached-grab-window"), transfer_window);
 }
 
-/**
- * gtk_menu_popup_for_device:
- * @menu: a #GtkMenu
- * @device: (allow-none): a #GdkDevice
- * @parent_menu_shell: (allow-none): the menu shell containing the triggering
- *     menu item, or %NULL
- * @parent_menu_item: (allow-none): the menu item whose activation triggered
- *     the popup, or %NULL
- * @func: (allow-none): a user supplied function used to position the menu,
- *     or %NULL
- * @data: (allow-none): user supplied data to be passed to @func
- * @destroy: (allow-none): destroy notify for @data
- * @button: the mouse button which was pressed to initiate the event
- * @activate_time: the time at which the activation event occurred
- *
- * Displays a menu and makes it available for selection.
- *
- * Applications can use this function to display context-sensitive menus,
- * and will typically supply %NULL for the @parent_menu_shell,
- * @parent_menu_item, @func, @data and @destroy parameters. The default
- * menu positioning function will position the menu at the current position
- * of @device (or its corresponding pointer).
- *
- * The @button parameter should be the mouse button pressed to initiate
- * the menu popup. If the menu popup was initiated by something other than
- * a mouse button press, such as a mouse button release or a keypress,
- * @button should be 0.
- *
- * The @activate_time parameter is used to conflict-resolve initiation of
- * concurrent requests for mouse/keyboard grab requests. To function
- * properly, this needs to be the time stamp of the user event (such as
- * a mouse click or key press) that caused the initiation of the popup.
- * Only if no such event is available, gtk_get_current_event_time() can
- * be used instead.
- *
- * Since: 3.0
- */
-void
-gtk_menu_popup_for_device (GtkMenu             *menu,
-                           GdkDevice           *device,
-                           GtkWidget           *parent_menu_shell,
-                           GtkWidget           *parent_menu_item,
-                           GtkMenuPositionFunc  func,
-                           gpointer             data,
-                           GDestroyNotify       destroy,
-                           guint                button,
-                           guint32              activate_time)
+static void
+gtk_menu_popup_internal (GtkMenu             *menu,
+                         GdkSeat             *seat,
+                         GtkWidget           *parent_menu_shell,
+                         GtkWidget           *parent_menu_item,
+                         GtkMenuPositionFunc  func,
+                         gpointer             data,
+                         GDestroyNotify       destroy,
+                         guint                button,
+                         guint32              activate_time,
+                         GdkAttachParams     *params)
 {
   GtkMenuPrivate *priv = menu->priv;
   GtkWidget *widget;
@@ -1594,31 +1558,42 @@ gtk_menu_popup_for_device (GtkMenu             *menu,
   GtkMenuShell *menu_shell;
   gboolean grab_keyboard;
   GtkWidget *parent_toplevel;
-  GdkDevice *pointer, *source_device = NULL;
+  GdkDevice *pointer = NULL;
+  GdkDevice *source_device = NULL;
   GdkDisplay *display;
 
+  if (!GTK_IS_MENU (menu) || (seat && !GDK_IS_SEAT (seat)))
+    g_clear_pointer (&params, gdk_attach_params_free);
+
   g_return_if_fail (GTK_IS_MENU (menu));
-  g_return_if_fail (device == NULL || GDK_IS_DEVICE (device));
+  g_return_if_fail (!seat || GDK_IS_SEAT (seat));
+
+  if (!seat)
+    {
+      current_event = gtk_get_current_event ();
+
+      if (current_event)
+        {
+          g_set_object (&seat, gdk_event_get_seat (current_event));
+          gdk_event_free (current_event);
+        }
+    }
+  else
+    g_object_ref (seat);
 
   display = gtk_widget_get_display (GTK_WIDGET (menu));
 
-  if (device == NULL)
-    device = gtk_get_current_event_device ();
+  if (seat && gdk_seat_get_display (seat) != display)
+    g_clear_object (&seat);
 
-  if (device && gdk_device_get_display (device) != display)
-    device = NULL;
+  if (!seat)
+    g_set_object (&seat, gdk_display_get_default_seat (display));
 
-  if (device == NULL)
-    device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
+  g_set_object (&pointer, gdk_seat_get_pointer (seat));
+  g_clear_object (&seat);
 
   widget = GTK_WIDGET (menu);
   menu_shell = GTK_MENU_SHELL (menu);
-
-  if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
-    pointer = gdk_device_get_associated_device (device);
-  else
-    pointer = device;
-
   menu_shell->priv->parent_menu_shell = parent_menu_shell;
 
   priv->seen_item_enter = FALSE;
@@ -1697,6 +1672,10 @@ gtk_menu_popup_for_device (GtkMenu             *menu,
        */
       menu_shell->priv->parent_menu_shell = NULL;
       menu_grab_transfer_window_destroy (menu);
+
+      g_clear_object (&pointer);
+      g_clear_pointer (&params, gdk_attach_params_free);
+
       return;
     }
 
@@ -1750,6 +1729,14 @@ gtk_menu_popup_for_device (GtkMenu             *menu,
   priv->position_func_data_destroy = destroy;
   menu_shell->priv->activate_time = activate_time;
 
+  if (params != priv->attach_params)
+    {
+      g_clear_pointer (&priv->attach_params, gdk_attach_params_free);
+      priv->attach_params = params;
+    }
+  else if (params)
+    g_warning ("%s (): menu already owns params", G_STRFUNC);
+
   /* We need to show the menu here rather in the init function
    * because code expects to be able to tell if the menu is onscreen
    * by looking at gtk_widget_get_visible (menu)
@@ -1788,6 +1775,386 @@ gtk_menu_popup_for_device (GtkMenu             *menu,
     _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE);
 
   _gtk_menu_shell_update_mnemonics (menu_shell);
+
+  g_clear_object (&pointer);
+}
+
+/**
+ * gtk_menu_create_params:
+ * @menu: a #GtkMenu
+ *
+ * Creates a new #GdkAttachParams with some common parameters initialized from
+ * @menu, such as shadow width.
+ *
+ * Returns: (transfer full): a new #GdkAttachParams that should be freed with
+ *          gdk_attach_params_free()
+ *
+ * Since: 3.20
+ */
+GdkAttachParams *
+gtk_menu_create_params (GtkMenu *menu)
+{
+  GdkAttachParams *params = gdk_attach_params_new ();
+  GtkBorder shadow;
+  GdkBorder padding;
+
+  g_return_val_if_fail (GTK_IS_MENU (menu), params);
+
+  /* Compute the window size */
+  gtk_widget_show (GTK_WIDGET (menu));
+
+  /* Compute the shadow width */
+  gtk_widget_realize (menu->priv->toplevel);
+
+  _gtk_window_get_shadow_width (GTK_WINDOW (menu->priv->toplevel), &shadow);
+
+  padding.top = shadow.top;
+  padding.left = shadow.left;
+  padding.right = shadow.right;
+  padding.bottom = shadow.bottom;
+
+  gdk_attach_params_set_window_padding (params, &padding);
+
+  return params;
+}
+
+static void
+get_arrows_border (GtkMenu   *menu,
+                   GtkBorder *border)
+{
+  GtkMenuPrivate *priv = menu->priv;
+  guint scroll_arrow_height;
+  GtkArrowPlacement arrow_placement;
+
+  gtk_widget_style_get (GTK_WIDGET (menu),
+                        "scroll-arrow-vlength", &scroll_arrow_height,
+                        "arrow_placement", &arrow_placement,
+                        NULL);
+
+  switch (arrow_placement)
+    {
+    case GTK_ARROWS_BOTH:
+      border->top = priv->upper_arrow_visible ? scroll_arrow_height : 0;
+      border->bottom = priv->lower_arrow_visible ? scroll_arrow_height : 0;
+      break;
+
+    case GTK_ARROWS_START:
+      border->top = (priv->upper_arrow_visible ||
+                     priv->lower_arrow_visible) ? scroll_arrow_height : 0;
+      border->bottom = 0;
+      break;
+
+    case GTK_ARROWS_END:
+      border->top = 0;
+      border->bottom = (priv->upper_arrow_visible ||
+                        priv->lower_arrow_visible) ? scroll_arrow_height : 0;
+      break;
+    }
+
+  border->left = border->right = 0;
+}
+
+/**
+ * gtk_menu_update_scroll_offset:
+ * @window: the #GdkWindow that was moved
+ * @params: (nullable): the #GdkAttachParams that was used
+ * @x: the final x-coordinate of @window
+ * @y: the final y-coordinate of @window
+ * @offset_x: the horizontal displacement applied to keep @window on-screen
+ * @offset_y: the vertical displacement applied to keep @window on-screen
+ * @flipped_x: %TRUE if @window was flipped horizontally
+ * @flipped_y: %TRUE if @window was flipped vertically
+ * @user_data: (not nullable): the #GtkMenu whose scroll offset should be
+ *             updated
+ *
+ * Updates the scroll offset for the #GtkMenu @user_data. This function has
+ * type #GdkAttachCallback and can be passed to
+ * gdk_attach_params_set_position_callback().
+ *
+ * Since: 3.20
+ */
+void
+gtk_menu_update_scroll_offset (GdkWindow             *window,
+                               const GdkAttachParams *params,
+                               gint                   x,
+                               gint                   y,
+                               gint                   offset_x,
+                               gint                   offset_y,
+                               gboolean               flipped_x,
+                               gboolean               flipped_y,
+                               gpointer               user_data)
+{
+  GtkMenu *menu;
+  GtkBorder border;
+
+  g_return_if_fail (GTK_IS_MENU (user_data));
+
+  menu = user_data;
+  get_arrows_border (menu, &border);
+  menu->priv->scroll_offset = offset_y + border.top;
+  gtk_menu_scroll_to (menu, menu->priv->scroll_offset);
+}
+
+static void
+set_attach_widget (GdkAttachParams *params,
+                   GtkWidget       *widget)
+{
+  GtkAllocation allocation;
+
+  g_return_if_fail (params);
+
+  if (widget)
+    {
+      gtk_widget_get_allocation (widget, &allocation);
+      gdk_attach_params_set_attach_rect (params, &allocation, gtk_widget_get_window (widget));
+    }
+  else
+    gdk_attach_params_set_attach_rect (params, NULL, NULL);
+}
+
+static GdkWindowEdge
+flip_anchor_horizontally (GdkWindowEdge edge)
+{
+  switch (edge)
+    {
+    case GDK_WINDOW_EDGE_NORTH_WEST:
+      return GDK_WINDOW_EDGE_NORTH_EAST;
+
+    case GDK_WINDOW_EDGE_NORTH:
+      return GDK_WINDOW_EDGE_NORTH;
+
+    case GDK_WINDOW_EDGE_NORTH_EAST:
+      return GDK_WINDOW_EDGE_NORTH_WEST;
+
+    case GDK_WINDOW_EDGE_WEST:
+      return GDK_WINDOW_EDGE_EAST;
+
+    case GDK_WINDOW_EDGE_CENTER:
+      return GDK_WINDOW_EDGE_CENTER;
+
+    case GDK_WINDOW_EDGE_EAST:
+      return GDK_WINDOW_EDGE_WEST;
+
+    case GDK_WINDOW_EDGE_SOUTH_WEST:
+      return GDK_WINDOW_EDGE_SOUTH_EAST;
+
+    case GDK_WINDOW_EDGE_SOUTH:
+      return GDK_WINDOW_EDGE_SOUTH;
+
+    case GDK_WINDOW_EDGE_SOUTH_EAST:
+      return GDK_WINDOW_EDGE_SOUTH_WEST;
+    }
+
+  g_return_val_if_reached (edge);
+}
+
+static void
+flip_anchors_horizontally (GdkAttachParams *params)
+{
+  GdkWindowEdge attach_anchor;
+  GdkWindowEdge window_anchor;
+
+  gdk_attach_params_get_anchors (params, &attach_anchor, &window_anchor);
+
+  attach_anchor = flip_anchor_horizontally (attach_anchor);
+  window_anchor = flip_anchor_horizontally (window_anchor);
+
+  gdk_attach_params_set_anchors (params, attach_anchor, window_anchor);
+}
+
+/**
+ * gtk_menu_popup_with_params:
+ * @menu: a #GtkMenu
+ * @seat: (transfer none) (nullable): a #GdkSeat
+ * @parent_menu_shell: (transfer none) (nullable): the menu shell containing
+ *                     the triggering menu item or %NULL
+ * @attach_widget: (transfer none) (nullable): the widget to attach @menu to
+ * @button: the mouse button which was pressed to initiate the event
+ * @activate_time: the time at which the activation event occurred
+ * @flip_if_rtl: %TRUE if horizontal constraints should be flipped when the
+ *               text direction is right-to-left
+ * @type_hint: window type hint to use for the popup menu's top-level window
+ * @params: (transfer full) (nullable): a description of how to position @menu
+ *
+ * Displays a menu and makes it available for selection.
+ *
+ * Applications can use this function to display context-sensitive menus,
+ * and will typically supply %NULL for the @parent_menu_shell. The default
+ * menu positioning function will position the menu at the current position
+ * of @seat's master pointer device.
+ *
+ * The @menu will be popped up beside @attach_widget, using the details
+ * supplied in @params. Usually, you create @params using
+ * gtk_menu_create_params(), which initializes the structure with some
+ * common parameters that can be derived from @menu.
+ *
+ * If @flip_if_rtl is %TRUE and the current text direction is right-to-left,
+ * then both the attachment rectangle and window anchors in @params will be
+ * horizontally flipped. For example, %GDK_WINDOW_EDGE_NORTH_WEST will be
+ * replaced with %GDK_WINDOW_EDGE_NORTH_EAST under a right-to-left locale.
+ *
+ * The @button parameter should be the mouse button pressed to initiate
+ * the menu popup. If the menu popup was initiated by something other than
+ * a mouse button press, such as a mouse button release or a keypress,
+ * @button should be 0.
+ *
+ * The @activate_time parameter is used to conflict-resolve initiation of
+ * concurrent requests for mouse/keyboard grab requests. To function
+ * properly, this needs to be the time stamp of the user event (such as
+ * a mouse click or key press) that caused the initiation of the popup.
+ * Only if no such event is available, gtk_get_current_event_time() can
+ * be used instead.
+ *
+ * Since: 3.20
+ */
+void
+gtk_menu_popup_with_params (GtkMenu           *menu,
+                            GdkSeat           *seat,
+                            GtkWidget         *parent_menu_shell,
+                            GtkWidget         *attach_widget,
+                            guint              button,
+                            guint32            activate_time,
+                            gboolean           flip_if_rtl,
+                            GdkWindowTypeHint  type_hint,
+                            GdkAttachParams   *params)
+{
+  GdkDisplay *display;
+  GdkDevice *pointer;
+  GdkEvent *current_event;
+  GdkRectangle rectangle = { 0 };
+
+  if (!GTK_IS_MENU (menu))
+    g_clear_pointer (&params, gdk_attach_params_free);
+
+  g_return_if_fail (GTK_IS_MENU (menu));
+
+  if (seat)
+    g_object_ref (seat);
+
+  if (!params)
+    {
+      params = gtk_menu_create_params (menu);
+
+      if (attach_widget)
+        gdk_attach_params_set_anchors (params, GDK_WINDOW_EDGE_SOUTH_WEST, GDK_WINDOW_EDGE_NORTH_WEST);
+      else
+        {
+          if (!seat)
+            {
+              current_event = gtk_get_current_event ();
+
+              if (current_event)
+                {
+                  g_set_object (&seat, gdk_event_get_seat (current_event));
+                  gdk_event_free (current_event);
+                }
+            }
+
+          display = gtk_widget_get_display (GTK_WIDGET (menu));
+
+          if (seat && gdk_seat_get_display (seat) != display)
+            g_clear_object (&seat);
+
+          if (!seat)
+            g_set_object (&seat, gdk_display_get_default_seat (display));
+
+          pointer = gdk_seat_get_pointer (seat);
+
+          if (pointer)
+            {
+              gdk_device_get_position (pointer, NULL, &rectangle.x, &rectangle.y);
+              rectangle.width = 1;
+              rectangle.height = 1;
+            }
+
+          gdk_attach_params_set_attach_rect (params, &rectangle, NULL);
+
+          gdk_attach_params_set_anchors (params, GDK_WINDOW_EDGE_SOUTH_EAST, GDK_WINDOW_EDGE_NORTH_WEST);
+        }
+    }
+
+  if (attach_widget)
+    set_attach_widget (params, attach_widget);
+
+  if (flip_if_rtl && gtk_widget_get_direction (GTK_WIDGET (menu)) == GTK_TEXT_DIR_RTL)
+    flip_anchors_horizontally (params);
+
+  menu->priv->type_hint = type_hint;
+
+  gtk_menu_popup_internal (menu,
+                           seat,
+                           parent_menu_shell,
+                           GTK_IS_MENU_ITEM (attach_widget) ? attach_widget : NULL,
+                           NULL,
+                           NULL,
+                           NULL,
+                           button,
+                           activate_time,
+                           params);
+
+  g_clear_object (&seat);
+}
+
+/**
+ * gtk_menu_popup_for_device:
+ * @menu: a #GtkMenu
+ * @device: (allow-none): a #GdkDevice
+ * @parent_menu_shell: (allow-none): the menu shell containing the triggering
+ *     menu item, or %NULL
+ * @parent_menu_item: (allow-none): the menu item whose activation triggered
+ *     the popup, or %NULL
+ * @func: (allow-none): a user supplied function used to position the menu,
+ *     or %NULL
+ * @data: (allow-none): user supplied data to be passed to @func
+ * @destroy: (allow-none): destroy notify for @data
+ * @button: the mouse button which was pressed to initiate the event
+ * @activate_time: the time at which the activation event occurred
+ *
+ * Displays a menu and makes it available for selection.
+ *
+ * Applications can use this function to display context-sensitive menus,
+ * and will typically supply %NULL for the @parent_menu_shell,
+ * @parent_menu_item, @func, @data and @destroy parameters. The default
+ * menu positioning function will position the menu at the current position
+ * of @device (or its corresponding pointer).
+ *
+ * The @button parameter should be the mouse button pressed to initiate
+ * the menu popup. If the menu popup was initiated by something other than
+ * a mouse button press, such as a mouse button release or a keypress,
+ * @button should be 0.
+ *
+ * The @activate_time parameter is used to conflict-resolve initiation of
+ * concurrent requests for mouse/keyboard grab requests. To function
+ * properly, this needs to be the time stamp of the user event (such as
+ * a mouse click or key press) that caused the initiation of the popup.
+ * Only if no such event is available, gtk_get_current_event_time() can
+ * be used instead.
+ *
+ * Since: 3.0
+ */
+void
+gtk_menu_popup_for_device (GtkMenu             *menu,
+                           GdkDevice           *device,
+                           GtkWidget           *parent_menu_shell,
+                           GtkWidget           *parent_menu_item,
+                           GtkMenuPositionFunc  func,
+                           gpointer             data,
+                           GDestroyNotify       destroy,
+                           guint                button,
+                           guint32              activate_time)
+{
+  g_return_if_fail (GTK_IS_MENU (menu));
+
+  gtk_menu_popup_internal (menu,
+                           device ? gdk_device_get_seat (device) : NULL,
+                           parent_menu_shell,
+                           parent_menu_item,
+                           func,
+                           data,
+                           destroy,
+                           button,
+                           activate_time,
+                           NULL);
 }
 
 /**
@@ -2507,29 +2874,6 @@ gtk_menu_reorder_child (GtkMenu   *menu,
 }
 
 static void
-get_arrows_border (GtkMenu   *menu,
-                   GtkBorder *border)
-{
-  GtkMenuPrivate *priv = menu->priv;
-  gint top_arrow_height, bottom_arrow_height;
-
-  gtk_css_gadget_get_preferred_size (priv->top_arrow_gadget,
-                                     GTK_ORIENTATION_VERTICAL,
-                                     -1,
-                                     &top_arrow_height, NULL,
-                                     NULL, NULL);
-  gtk_css_gadget_get_preferred_size (priv->bottom_arrow_gadget,
-                                     GTK_ORIENTATION_VERTICAL,
-                                     -1,
-                                     &bottom_arrow_height, NULL,
-                                     NULL, NULL);
-
-  border->top = priv->upper_arrow_visible ? top_arrow_height : 0;
-  border->bottom = priv->lower_arrow_visible ? bottom_arrow_height : 0;
-  border->left = border->right = 0;
-}
-
-static void
 get_menu_padding (GtkWidget *widget,
                   GtkBorder *padding)
 {
@@ -4254,6 +4598,7 @@ gtk_menu_position (GtkMenu  *menu,
                    gboolean  set_scroll_offset)
 {
   GtkMenuPrivate *priv = menu->priv;
+  GdkWindowTypeHint type_hint;
   GtkWidget *widget;
   GtkRequisition requisition;
   gint x, y;
@@ -4264,17 +4609,32 @@ gtk_menu_position (GtkMenu  *menu,
   GdkDevice *pointer;
   GtkBorder border;
 
+  /* Realize so we have the proper width and height to figure out
+   * the right place to popup the menu.
+   */
+  gtk_widget_realize (priv->toplevel);
+
+  if (!gtk_widget_get_mapped (priv->toplevel) && priv->attach_params)
+    {
+      type_hint = priv->type_hint;
+
+      if (type_hint == GDK_WINDOW_TYPE_HINT_NORMAL)
+        type_hint = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
+
+      gtk_window_set_type_hint (GTK_WINDOW (priv->toplevel), type_hint);
+    }
+
+  gdk_window_move_using_params (gtk_widget_get_window (priv->toplevel), priv->attach_params);
+
+  if (priv->attach_params)
+    return;
+
   widget = GTK_WIDGET (menu);
 
   screen = gtk_widget_get_screen (widget);
   pointer = _gtk_menu_shell_get_grab_device (GTK_MENU_SHELL (menu));
   gdk_device_get_position (pointer, &pointer_screen, &x, &y);
 
-  /* Realize so we have the proper width and height to figure out
-   * the right place to popup the menu.
-   */
-  gtk_widget_realize (priv->toplevel);
-
   _gtk_window_get_shadow_width (GTK_WINDOW (priv->toplevel), &border);
 
   requisition.width = gtk_widget_get_allocated_width (widget);
diff --git a/gtk/gtkmenu.h b/gtk/gtkmenu.h
index 76c3ec9..97b271f 100644
--- a/gtk/gtkmenu.h
+++ b/gtk/gtkmenu.h
@@ -153,6 +153,31 @@ void       gtk_menu_popup_for_device      (GtkMenu             *menu,
                                            guint                button,
                                            guint32              activate_time);
 
+GDK_AVAILABLE_IN_3_20
+GdkAttachParams * gtk_menu_create_params  (GtkMenu               *menu);
+
+GDK_AVAILABLE_IN_3_20
+void       gtk_menu_update_scroll_offset  (GdkWindow             *window,
+                                           const GdkAttachParams *params,
+                                           gint                   x,
+                                           gint                   y,
+                                           gint                   offset_x,
+                                           gint                   offset_y,
+                                           gboolean               flipped_x,
+                                           gboolean               flipped_y,
+                                           gpointer               user_data);
+
+GDK_AVAILABLE_IN_3_20
+void       gtk_menu_popup_with_params     (GtkMenu               *menu,
+                                           GdkSeat               *seat,
+                                           GtkWidget             *parent_menu_shell,
+                                           GtkWidget             *attach_widget,
+                                           guint                  button,
+                                           guint32                activate_time,
+                                           gboolean               flip_if_rtl,
+                                           GdkWindowTypeHint      type_hint,
+                                           GdkAttachParams       *params);
+
 /* Position the menu according to its position function. Called
  * from gtkmenuitem.c when a menu-item changes its allocation
  */
diff --git a/gtk/gtkmenuprivate.h b/gtk/gtkmenuprivate.h
index cb6ec25..70f68a5 100644
--- a/gtk/gtkmenuprivate.h
+++ b/gtk/gtkmenuprivate.h
@@ -53,6 +53,9 @@ struct _GtkMenuPrivate
   gint                position_x;
   gint                position_y;
 
+  GdkAttachParams   *attach_params;
+  GdkWindowTypeHint  type_hint;
+
   guint toggle_size;
   guint accel_size;
 


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