mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-12 05:20:17 +00:00
To get around the fact that we may have a owner_events = FALSE grab in
Sat Feb 2 16:43:31 2002 Owen Taylor <otaylor@redhat.com> * gtk/gtkmenu.c (gtk_menu_popup): To get around the fact that we may have a owner_events = FALSE grab in effect when we pop up a window, make a temporary grab on a different window, then grab on the real window. Fixes a problem where if a context menu popped up under the cursor, the first item would be stuck unselected. (#59812, reported by Arnaud Charlet.)
This commit is contained in:
parent
9e31153e9b
commit
2ee08d8ec6
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
||||
Sat Feb 2 16:43:31 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkmenu.c (gtk_menu_popup): To get around the fact
|
||||
that we may have a owner_events = FALSE grab in effect
|
||||
when we pop up a window, make a temporary grab on a
|
||||
different window, then grab on the real window. Fixes
|
||||
a problem where if a context menu popped up under the
|
||||
cursor, the first item would be stuck unselected.
|
||||
(#59812, reported by Arnaud Charlet.)
|
||||
|
||||
2002-02-02 Peter Williams <peterw@ximian.com>
|
||||
|
||||
* gtk/Makefile.am (install-data-local): Install gtkrc.default
|
||||
|
@ -1,3 +1,13 @@
|
||||
Sat Feb 2 16:43:31 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkmenu.c (gtk_menu_popup): To get around the fact
|
||||
that we may have a owner_events = FALSE grab in effect
|
||||
when we pop up a window, make a temporary grab on a
|
||||
different window, then grab on the real window. Fixes
|
||||
a problem where if a context menu popped up under the
|
||||
cursor, the first item would be stuck unselected.
|
||||
(#59812, reported by Arnaud Charlet.)
|
||||
|
||||
2002-02-02 Peter Williams <peterw@ximian.com>
|
||||
|
||||
* gtk/Makefile.am (install-data-local): Install gtkrc.default
|
||||
|
@ -1,3 +1,13 @@
|
||||
Sat Feb 2 16:43:31 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkmenu.c (gtk_menu_popup): To get around the fact
|
||||
that we may have a owner_events = FALSE grab in effect
|
||||
when we pop up a window, make a temporary grab on a
|
||||
different window, then grab on the real window. Fixes
|
||||
a problem where if a context menu popped up under the
|
||||
cursor, the first item would be stuck unselected.
|
||||
(#59812, reported by Arnaud Charlet.)
|
||||
|
||||
2002-02-02 Peter Williams <peterw@ximian.com>
|
||||
|
||||
* gtk/Makefile.am (install-data-local): Install gtkrc.default
|
||||
|
@ -1,3 +1,13 @@
|
||||
Sat Feb 2 16:43:31 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkmenu.c (gtk_menu_popup): To get around the fact
|
||||
that we may have a owner_events = FALSE grab in effect
|
||||
when we pop up a window, make a temporary grab on a
|
||||
different window, then grab on the real window. Fixes
|
||||
a problem where if a context menu popped up under the
|
||||
cursor, the first item would be stuck unselected.
|
||||
(#59812, reported by Arnaud Charlet.)
|
||||
|
||||
2002-02-02 Peter Williams <peterw@ximian.com>
|
||||
|
||||
* gtk/Makefile.am (install-data-local): Install gtkrc.default
|
||||
|
@ -1,3 +1,13 @@
|
||||
Sat Feb 2 16:43:31 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkmenu.c (gtk_menu_popup): To get around the fact
|
||||
that we may have a owner_events = FALSE grab in effect
|
||||
when we pop up a window, make a temporary grab on a
|
||||
different window, then grab on the real window. Fixes
|
||||
a problem where if a context menu popped up under the
|
||||
cursor, the first item would be stuck unselected.
|
||||
(#59812, reported by Arnaud Charlet.)
|
||||
|
||||
2002-02-02 Peter Williams <peterw@ximian.com>
|
||||
|
||||
* gtk/Makefile.am (install-data-local): Install gtkrc.default
|
||||
|
@ -1,3 +1,13 @@
|
||||
Sat Feb 2 16:43:31 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkmenu.c (gtk_menu_popup): To get around the fact
|
||||
that we may have a owner_events = FALSE grab in effect
|
||||
when we pop up a window, make a temporary grab on a
|
||||
different window, then grab on the real window. Fixes
|
||||
a problem where if a context menu popped up under the
|
||||
cursor, the first item would be stuck unselected.
|
||||
(#59812, reported by Arnaud Charlet.)
|
||||
|
||||
2002-02-02 Peter Williams <peterw@ximian.com>
|
||||
|
||||
* gtk/Makefile.am (install-data-local): Install gtkrc.default
|
||||
|
@ -1,3 +1,13 @@
|
||||
Sat Feb 2 16:43:31 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkmenu.c (gtk_menu_popup): To get around the fact
|
||||
that we may have a owner_events = FALSE grab in effect
|
||||
when we pop up a window, make a temporary grab on a
|
||||
different window, then grab on the real window. Fixes
|
||||
a problem where if a context menu popped up under the
|
||||
cursor, the first item would be stuck unselected.
|
||||
(#59812, reported by Arnaud Charlet.)
|
||||
|
||||
2002-02-02 Peter Williams <peterw@ximian.com>
|
||||
|
||||
* gtk/Makefile.am (install-data-local): Install gtkrc.default
|
||||
|
183
gtk/gtkmenu.c
183
gtk/gtkmenu.c
@ -136,6 +136,9 @@ static void gtk_menu_remove (GtkContainer *menu,
|
||||
|
||||
static void gtk_menu_update_title (GtkMenu *menu);
|
||||
|
||||
static void menu_grab_transfer_window_destroy (GtkMenu *menu);
|
||||
static GdkWindow *menu_grab_transfer_window_get (GtkMenu *menu);
|
||||
|
||||
static void _gtk_menu_refresh_accel_paths (GtkMenu *menu,
|
||||
gboolean group_changed);
|
||||
|
||||
@ -594,6 +597,29 @@ gtk_menu_tearoff_bg_copy (GtkMenu *menu)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
popup_grab_on_window (GdkWindow *window,
|
||||
guint32 activate_time)
|
||||
{
|
||||
if ((gdk_pointer_grab (window, TRUE,
|
||||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK,
|
||||
NULL, NULL, activate_time) == 0))
|
||||
{
|
||||
if (gdk_keyboard_grab (window, TRUE,
|
||||
activate_time) == 0)
|
||||
return TRUE;
|
||||
else
|
||||
{
|
||||
gdk_pointer_ungrab (activate_time);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_menu_popup (GtkMenu *menu,
|
||||
GtkWidget *parent_menu_shell,
|
||||
@ -615,6 +641,72 @@ gtk_menu_popup (GtkMenu *menu,
|
||||
menu_shell = GTK_MENU_SHELL (menu);
|
||||
|
||||
menu_shell->parent_menu_shell = parent_menu_shell;
|
||||
|
||||
/* Find the last viewable ancestor, and make an X grab on it
|
||||
*/
|
||||
parent = GTK_WIDGET (menu);
|
||||
xgrab_shell = NULL;
|
||||
while (parent)
|
||||
{
|
||||
gboolean viewable = TRUE;
|
||||
GtkWidget *tmp = parent;
|
||||
|
||||
while (tmp)
|
||||
{
|
||||
if (!GTK_WIDGET_MAPPED (tmp))
|
||||
{
|
||||
viewable = FALSE;
|
||||
break;
|
||||
}
|
||||
tmp = tmp->parent;
|
||||
}
|
||||
|
||||
if (viewable)
|
||||
xgrab_shell = parent;
|
||||
|
||||
parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
|
||||
}
|
||||
|
||||
/* We want to receive events generated when we map the menu; unfortunately,
|
||||
* since there is probably already an implicit grab in place from the
|
||||
* button that the user used to pop up the menu, we won't receive then --
|
||||
* in particular, the EnterNotify when the menu pops up under the pointer.
|
||||
*
|
||||
* If we are grabbing on a parent menu shell, no problem; just grab on
|
||||
* that menu shell first before popping up the window with owner_events = TRUE.
|
||||
*
|
||||
* When grabbing on the menu itself, things get more convuluted - we
|
||||
* we do an explicit grab on a specially created window with
|
||||
* owner_events = TRUE, which we override further down with a grab
|
||||
* on the menu. (We can't grab on the menu until it is mapped; we
|
||||
* probably could just leave the grab on the other window, with a
|
||||
* little reorganization of the code in gtkmenu*).
|
||||
*/
|
||||
if (xgrab_shell == widget)
|
||||
{
|
||||
if (popup_grab_on_window (xgrab_shell->window, activate_time))
|
||||
GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkWindow *transfer_window;
|
||||
|
||||
xgrab_shell = widget;
|
||||
transfer_window = menu_grab_transfer_window_get (menu);
|
||||
if (popup_grab_on_window (transfer_window, activate_time))
|
||||
GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
|
||||
}
|
||||
|
||||
if (!GTK_MENU_SHELL (xgrab_shell)->have_xgrab)
|
||||
{
|
||||
/* We failed to make our pointer/keyboard grab. Rather than leaving the user
|
||||
* with a stuck up window, we just abort here. Presumably the user will
|
||||
* try again.
|
||||
*/
|
||||
menu_shell->parent_menu_shell = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
menu_shell->active = TRUE;
|
||||
menu_shell->button = button;
|
||||
|
||||
@ -654,46 +746,8 @@ gtk_menu_popup (GtkMenu *menu,
|
||||
|
||||
gtk_menu_scroll_to (menu, menu->scroll_offset);
|
||||
|
||||
/* Find the last viewable ancestor, and make an X grab on it
|
||||
*/
|
||||
parent = GTK_WIDGET (menu);
|
||||
xgrab_shell = NULL;
|
||||
while (parent)
|
||||
{
|
||||
gboolean viewable = TRUE;
|
||||
GtkWidget *tmp = parent;
|
||||
|
||||
while (tmp)
|
||||
{
|
||||
if (!GTK_WIDGET_MAPPED (tmp))
|
||||
{
|
||||
viewable = FALSE;
|
||||
break;
|
||||
}
|
||||
tmp = tmp->parent;
|
||||
}
|
||||
|
||||
if (viewable)
|
||||
xgrab_shell = parent;
|
||||
|
||||
parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
|
||||
}
|
||||
|
||||
if (xgrab_shell && (!GTK_MENU_SHELL (xgrab_shell)->have_xgrab))
|
||||
{
|
||||
if ((gdk_pointer_grab (xgrab_shell->window, TRUE,
|
||||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK,
|
||||
NULL, NULL, activate_time) == 0))
|
||||
{
|
||||
if (gdk_keyboard_grab (xgrab_shell->window, TRUE,
|
||||
activate_time) == 0)
|
||||
GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
|
||||
else
|
||||
gdk_pointer_ungrab (activate_time);
|
||||
}
|
||||
}
|
||||
if (xgrab_shell == widget)
|
||||
popup_grab_on_window (widget->window, activate_time); /* Should always succeed */
|
||||
|
||||
gtk_grab_add (GTK_WIDGET (menu));
|
||||
}
|
||||
@ -766,6 +820,8 @@ gtk_menu_popdown (GtkMenu *menu)
|
||||
|
||||
menu_shell->have_xgrab = FALSE;
|
||||
gtk_grab_remove (GTK_WIDGET (menu));
|
||||
|
||||
menu_grab_transfer_window_destroy (menu);
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
@ -1241,6 +1297,51 @@ gtk_menu_realize (GtkWidget *widget)
|
||||
gdk_window_show (menu->view_window);
|
||||
}
|
||||
|
||||
/* See notes in gtk_menu_popup() for information about the "grab transfer window"
|
||||
*/
|
||||
static GdkWindow *
|
||||
menu_grab_transfer_window_get (GtkMenu *menu)
|
||||
{
|
||||
GdkWindow *window = g_object_get_data (G_OBJECT (menu), "gtk-menu-transfer-window");
|
||||
if (!window)
|
||||
{
|
||||
GdkWindowAttr attributes;
|
||||
gint attributes_mask;
|
||||
|
||||
attributes.x = -100;
|
||||
attributes.y = -100;
|
||||
attributes.width = 10;
|
||||
attributes.height = 10;
|
||||
attributes.window_type = GDK_WINDOW_TEMP;
|
||||
attributes.wclass = GDK_INPUT_ONLY;
|
||||
attributes.override_redirect = TRUE;
|
||||
attributes.event_mask = 0;
|
||||
|
||||
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
|
||||
|
||||
window = gdk_window_new (NULL, &attributes, attributes_mask);
|
||||
gdk_window_set_user_data (window, menu);
|
||||
|
||||
gdk_window_show (window);
|
||||
|
||||
g_object_set_data (G_OBJECT (menu), "gtk-menu-transfer-window", window);
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
static void
|
||||
menu_grab_transfer_window_destroy (GtkMenu *menu)
|
||||
{
|
||||
GdkWindow *window = g_object_get_data (G_OBJECT (menu), "gtk-menu-transfer-window");
|
||||
if (window)
|
||||
{
|
||||
gdk_window_set_user_data (window, NULL);
|
||||
gdk_window_destroy (window);
|
||||
g_object_set_data (G_OBJECT (menu), "gtk-menu-transfer-window", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_unrealize (GtkWidget *widget)
|
||||
{
|
||||
@ -1250,6 +1351,8 @@ gtk_menu_unrealize (GtkWidget *widget)
|
||||
|
||||
menu = GTK_MENU (widget);
|
||||
|
||||
menu_grab_transfer_window_destroy (menu);
|
||||
|
||||
gdk_window_set_user_data (menu->view_window, NULL);
|
||||
gdk_window_destroy (menu->view_window);
|
||||
menu->view_window = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user