]> Pileus Git - ~andy/gtk/commitdiff
Don't close menus on clicks on their border area (bug #423761). (modified
authorMichael Natterer <mitch@imendio.com>
Thu, 29 Mar 2007 15:47:49 +0000 (15:47 +0000)
committerMichael Natterer <mitch@src.gnome.org>
Thu, 29 Mar 2007 15:47:49 +0000 (15:47 +0000)
2007-03-29  Michael Natterer  <mitch@imendio.com>

Don't close menus on clicks on their border area (bug #423761).
(modified patch from maemo-gtk).

* gtk/gtkmenu.c (gtk_menu_button_press)
(gtk_menu_button_release): bail out early if the click was on the
menu's border (not on any item and not outside the window).

(pointer_in_menu_window): new utility function which checks if
passed root coords are inside the menu_shell or one of its
parent shells.

svn path=/trunk/; revision=17571

ChangeLog
gtk/gtkmenu.c

index 136981d8cf83253e54ae1a96539b553e56090b52..cd0da1c29a34e3767802bf6f2edbf958174957b1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2007-03-29  Michael Natterer  <mitch@imendio.com>
+
+       Don't close menus on clicks on their border area (bug #423761).
+       (modified patch from maemo-gtk).
+
+       * gtk/gtkmenu.c (gtk_menu_button_press)
+       (gtk_menu_button_release): bail out early if the click was on the
+       menu's border (not on any item and not outside the window).
+
+       (pointer_in_menu_window): new utility function which checks if
+       passed root coords are inside the menu_shell or one of its
+       parent shells.
+
 2007-03-29  Michael Natterer  <mitch@imendio.com>
 
        * gtk/gtkmenu.c: get rid of local GtkSettings variables by moving
index 93214ac438987eea9e6bd0aedaf34342f0a958b9..92eb569bd730328fc3f25c7a1acedb7ccf772d0e 100644 (file)
@@ -2578,6 +2578,34 @@ gtk_menu_button_scroll (GtkMenu        *menu,
   return FALSE;
 }
 
+static gboolean
+pointer_in_menu_window (GtkWidget *widget,
+                        gdouble    x_root,
+                        gdouble    y_root)
+{
+  GtkMenu *menu = GTK_MENU (widget);
+
+  if (GTK_WIDGET_MAPPED (menu->toplevel))
+    {
+      GtkMenuShell *menu_shell;
+      gint          window_x, window_y;
+
+      gdk_window_get_position (menu->toplevel->window, &window_x, &window_y);
+
+      if (x_root >= window_x && x_root < window_x + widget->allocation.width &&
+          y_root >= window_y && y_root < window_y + widget->allocation.height)
+        return TRUE;
+
+      menu_shell = GTK_MENU_SHELL (widget);
+
+      if (GTK_IS_MENU (menu_shell->parent_menu_shell))
+        return pointer_in_menu_window (menu_shell->parent_menu_shell,
+                                       x_root, y_root);
+    }
+
+  return FALSE;
+}
+
 static gboolean
 gtk_menu_button_press (GtkWidget      *widget,
                        GdkEventButton *event)
@@ -2585,11 +2613,22 @@ gtk_menu_button_press (GtkWidget      *widget,
   if (event->type != GDK_BUTTON_PRESS)
     return FALSE;
 
-  /* Don't pop down the menu for presses over scroll arrows
+  /* Don't pass down to menu shell for presses over scroll arrows
    */
   if (gtk_menu_button_scroll (GTK_MENU (widget), event))
     return TRUE;
 
+  /*  Don't pass down to menu shell if a non-menuitem part of the menu
+   *  was clicked. The check for the event_widget being a GtkMenuShell
+   *  works because we have the pointer grabbed on menu_shell->window
+   *  with owner_events=TRUE, so all events that are either outside
+   *  the menu or on its border are delivered relative to
+   *  menu_shell->window.
+   */
+  if (GTK_IS_MENU_SHELL (gtk_get_event_widget ((GdkEvent *) event)) &&
+      pointer_in_menu_window (widget, event->x_root, event->y_root))
+    return TRUE;
+
   return GTK_WIDGET_CLASS (gtk_menu_parent_class)->button_press_event (widget, event);
 }
 
@@ -2608,11 +2647,18 @@ gtk_menu_button_release (GtkWidget      *widget,
   if (event->type != GDK_BUTTON_RELEASE)
     return FALSE;
 
-  /* Don't pop down the menu for releases over scroll arrows
+  /* Don't pass down to menu shell for releases over scroll arrows
    */
   if (gtk_menu_button_scroll (GTK_MENU (widget), event))
     return TRUE;
 
+  /*  Don't pass down to menu shell if a non-menuitem part of the menu
+   *  was clicked (see comment in button_press()).
+   */
+  if (GTK_IS_MENU_SHELL (gtk_get_event_widget ((GdkEvent *) event)) &&
+      pointer_in_menu_window (widget, event->x_root, event->y_root))
+    return TRUE;
+
   return GTK_WIDGET_CLASS (gtk_menu_parent_class)->button_release_event (widget, event);
 }