From 03413577a1ee364109a181c5c7711c2b118a703b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann?= Date: Wed, 22 Dec 2004 16:52:23 +0000 Subject: [PATCH] Bug #147497, make menu items activate immediately when you release the MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wed Dec 22 11:35:41 2004 Søren Sandmann Bug #147497, make menu items activate immediately when you release the button. * gtk/gtkmenu.c (gtk_menu_enter_notify, menu_motion_notify): Make items activate immediately. * gtk/gtkmenu.c (definitely_within_item): New function * gtk/gtkmenu.c (check_threshold): New function --- gtk/gtkmenu.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 71048e84a6..7266bb7569 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -76,6 +76,8 @@ struct _GtkMenuAttachData struct _GtkMenuPrivate { + gboolean seen_item_enter; + gboolean have_position; gint x; gint y; @@ -1278,6 +1280,7 @@ gtk_menu_popup (GtkMenu *menu, GtkWidget *parent; GdkEvent *current_event; GtkMenuShell *menu_shell; + GtkMenuPrivate *priv = gtk_menu_get_private (menu); g_return_if_fail (GTK_IS_MENU (menu)); @@ -1285,6 +1288,8 @@ gtk_menu_popup (GtkMenu *menu, menu_shell = GTK_MENU_SHELL (menu); menu_shell->parent_menu_shell = parent_menu_shell; + + priv->seen_item_enter = FALSE; /* Find the last viewable ancestor, and make an X grab on it */ @@ -2717,6 +2722,35 @@ gtk_menu_key_press (GtkWidget *widget, return TRUE; } +static gboolean +check_threshold (GtkWidget *widget, + int start_x, int start_y, + int x, int y) +{ +#define THRESHOLD 8 + + return + ABS (start_x - x) > THRESHOLD || + ABS (start_y - y) > THRESHOLD; +} + +static gboolean +definitely_within_item (GtkWidget *widget, + int x, + int y) +{ + GdkWindow *window = GTK_MENU_ITEM (widget)->event_window; + int w, h; + + gdk_drawable_get_size (window, &w, &h); + + return + check_threshold (widget, 0, 0, x, y) && + check_threshold (widget, w - 1, 0, x, y) && + check_threshold (widget, w - 1, h - 1, x, y) && + check_threshold (widget, 0, h - 1, x, y); +} + static gboolean gtk_menu_motion_notify (GtkWidget *widget, GdkEventMotion *event) @@ -2724,6 +2758,7 @@ gtk_menu_motion_notify (GtkWidget *widget, GtkWidget *menu_item; GtkMenu *menu; GtkMenuShell *menu_shell; + GtkMenuPrivate *priv; gboolean need_enter; @@ -2746,6 +2781,11 @@ gtk_menu_motion_notify (GtkWidget *widget, menu_shell = GTK_MENU_SHELL (menu_item->parent); menu = GTK_MENU (menu_shell); + + priv = gtk_menu_get_private (GTK_MENU (widget)); + + if (definitely_within_item (menu_item, event->x, event->y)) + menu_shell->activate_time = 0; need_enter = (menu->navigation_region != NULL || menu_shell->ignore_enter); @@ -2993,6 +3033,42 @@ gtk_menu_enter_notify (GtkWidget *widget, if (!menu_shell->ignore_enter) gtk_menu_handle_scrolling (GTK_MENU (widget), TRUE); } + + if (menu_item && GTK_IS_MENU_ITEM (menu_item)) + { + GtkWidget *menu = menu_item->parent; + + if (menu && GTK_IS_MENU (menu)) + { + GtkMenuPrivate *priv = gtk_menu_get_private (GTK_MENU (menu)); + GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu); + + if (priv->seen_item_enter) + { + /* This is the second enter we see for an item + * on this menu. This means a release should always + * mean activate. + */ + menu_shell->activate_time = 0; + } + else if ((event->detail != GDK_NOTIFY_NONLINEAR && + event->detail != GDK_NOTIFY_NONLINEAR_VIRTUAL)) + { + if (definitely_within_item (menu_item, event->x, event->y)) + { + /* This is an actual user-enter (ie. not a pop-under) + * In this case, the user must either have entered + * sufficiently far enough into the item, or he must move + * far enough away from the enter point. (see + * gtk_menu_motion_notify()) + */ + menu_shell->activate_time = 0; + } + } + + priv->seen_item_enter = TRUE; + } + } /* If this is a faked enter (see gtk_menu_motion_notify), 'widget' * will not correspond to the event widget's parent. Check to see