diff options
author | Owen Taylor <otaylor@redhat.com> | 2002-03-02 20:37:07 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2002-03-02 20:37:07 +0000 |
commit | b54e5f4ca17d56f4844caa9485989f65b18babda (patch) | |
tree | 951f60c1491f4e7c62c9ead4e18a76c72833f35a /gdk | |
parent | dfe5724765acc217ce43b4f96cc0d6dc2d73016c (diff) | |
download | gdk-pixbuf-b54e5f4ca17d56f4844caa9485989f65b18babda.tar.gz |
Robustify tracking of pointer grab window.
Fri Mar 1 18:39:44 2002 Owen Taylor <otaylor@redhat.com>
* gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h,
gdkwindow-x11.c}: Robustify tracking of pointer grab window.
* gdk/x11/gdkmain-x11.c: Keep track of current keyboard
grab window.
* gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only,
gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk
API for finding out current grab information.
* gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events
so that the effective behavior of owner_events = TRUE is changed
to "deliver events to same window group normally" instead
of "deliver events to same application normally. #69934
* gtk/gtkrange.c: Use an explicit gtk_grab_add() so that
it works within the GtkList combo, where there is a
owner_events = FALSE gdk_pointer_grab() already in effect.
(#65006, reported by Damon Chaplin)
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/x11/gdkevents-x11.c | 5 | ||||
-rw-r--r-- | gdk/x11/gdkmain-x11.c | 151 | ||||
-rw-r--r-- | gdk/x11/gdkprivate-x11.h | 8 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 15 |
4 files changed, 168 insertions, 11 deletions
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 2d1e14bd5..babd7e35c 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -1262,9 +1262,8 @@ gdk_event_translate (GdkEvent *event, gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_ICONIFIED); - - if (_gdk_xgrab_window == window_private) - _gdk_xgrab_window = NULL; + + _gdk_xgrab_check_unmap (window, xevent->xany.serial); break; diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index b6383a0dd..0b87d8c0c 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -92,6 +92,18 @@ static gboolean gdk_synchronize = FALSE; static GSList *gdk_error_traps = NULL; /* List of error traps */ static GSList *gdk_error_trap_free_list = NULL; /* Free list */ +/* Information about current pointer and keyboard grabs held by this + * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window + * window is NULL, then the other associated fields are ignored + */ +static GdkWindowObject *gdk_pointer_xgrab_window = NULL; +static gulong gdk_pointer_xgrab_serial; +static gboolean gdk_pointer_xgrab_owner_events; + +static GdkWindowObject *gdk_keyboard_xgrab_window = NULL; +static gulong gdk_keyboard_xgrab_serial; +static gboolean gdk_keyboard_xgrab_owner_events; + GdkArgDesc _gdk_windowing_args[] = { { "display", GDK_ARG_STRING, &_gdk_display_name, (GdkArgFunc)NULL }, { "sync", GDK_ARG_BOOL, &gdk_synchronize, (GdkArgFunc)NULL }, @@ -251,6 +263,7 @@ gdk_pointer_grab (GdkWindow * window, Window xwindow; Window xconfine_to; Cursor xcursor; + unsigned long serial; int i; g_return_val_if_fail (window != NULL, 0); @@ -260,6 +273,7 @@ gdk_pointer_grab (GdkWindow * window, cursor_private = (GdkCursorPrivate*) cursor; xwindow = GDK_WINDOW_XID (window); + serial = NextRequest (GDK_WINDOW_XDISPLAY (window)); if (!confine_to || GDK_WINDOW_DESTROYED (confine_to)) xconfine_to = None; @@ -308,7 +322,11 @@ gdk_pointer_grab (GdkWindow * window, } if (return_val == GrabSuccess) - _gdk_xgrab_window = (GdkWindowObject *)window; + { + gdk_pointer_xgrab_window = (GdkWindowObject *)window; + gdk_pointer_xgrab_serial = serial; + gdk_pointer_xgrab_owner_events = owner_events; + } return gdk_x11_convert_grab_status (return_val); } @@ -334,7 +352,7 @@ gdk_pointer_ungrab (guint32 time) _gdk_input_ungrab_pointer (time); XUngrabPointer (gdk_display, time); - _gdk_xgrab_window = NULL; + gdk_pointer_xgrab_window = NULL; } /* @@ -355,7 +373,36 @@ gdk_pointer_ungrab (guint32 time) gboolean gdk_pointer_is_grabbed (void) { - return _gdk_xgrab_window != NULL; + return gdk_pointer_xgrab_window != NULL; +} + +/** + * gdk_pointer_grab_info_libgtk_only: + * @grab_window: location to store current grab window + * @owner_events: location to store boolean indicating whether + * the @owner_events flag to gdk_pointer_grab() was %TRUE. + * + * Determines information about the current pointer grab. + * This is not public API and must not be used by applications. + * + * Return value: %TRUE if this application currently has the + * pointer grabbed. + **/ +gboolean +gdk_pointer_grab_info_libgtk_only (GdkWindow **grab_window, + gboolean *owner_events) +{ + if (gdk_pointer_xgrab_window) + { + if (grab_window) + *grab_window = (GdkWindow *)gdk_pointer_xgrab_window; + if (owner_events) + *owner_events = gdk_pointer_xgrab_owner_events; + + return TRUE; + } + else + return FALSE; } /* @@ -384,10 +431,13 @@ gdk_keyboard_grab (GdkWindow * window, guint32 time) { gint return_val; + unsigned long serial; g_return_val_if_fail (window != NULL, 0); g_return_val_if_fail (GDK_IS_WINDOW (window), 0); + serial = NextRequest (GDK_WINDOW_XDISPLAY (window)); + if (!GDK_WINDOW_DESTROYED (window)) { #ifdef G_ENABLE_DEBUG @@ -404,6 +454,13 @@ gdk_keyboard_grab (GdkWindow * window, else return_val = AlreadyGrabbed; + if (return_val == GrabSuccess) + { + gdk_keyboard_xgrab_window = (GdkWindowObject *)window; + gdk_keyboard_xgrab_serial = serial; + gdk_keyboard_xgrab_owner_events = owner_events; + } + return gdk_x11_convert_grab_status (return_val); } @@ -426,6 +483,94 @@ void gdk_keyboard_ungrab (guint32 time) { XUngrabKeyboard (gdk_display, time); + gdk_keyboard_xgrab_window = NULL; +} + +/** + * gdk_keyboard_grab_info_libgtk_only: + * @grab_window: location to store current grab window + * @owner_events: location to store boolean indicating whether + * the @owner_events flag to gdk_keyboard_grab() was %TRUE. + * + * Determines information about the current keyboard grab. + * This is not public API and must not be used by applications. + * + * Return value: %TRUE if this application currently has the + * keyboard grabbed. + **/ +gboolean +gdk_keyboard_grab_info_libgtk_only (GdkWindow **grab_window, + gboolean *owner_events) +{ + if (gdk_keyboard_xgrab_window) + { + if (grab_window) + *grab_window = (GdkWindow *)gdk_keyboard_xgrab_window; + if (owner_events) + *owner_events = gdk_keyboard_xgrab_owner_events; + + return TRUE; + } + else + return FALSE; +} + +/** + * _gdk_xgrab_check_unmap: + * @window: a #GdkWindow + * @serial: serial from Unmap event (or from NextRequest(display) + * if the unmap is being done by this client.) + * + * Checks to see if an unmap request or event causes the current + * grab window to become not viewable, and if so, clear the + * the pointer we keep to it. + **/ +void +_gdk_xgrab_check_unmap (GdkWindow *window, + gulong serial) +{ + if (gdk_pointer_xgrab_window && serial >= gdk_pointer_xgrab_serial) + { + GdkWindowObject *private = GDK_WINDOW_OBJECT (window); + GdkWindowObject *tmp = gdk_pointer_xgrab_window; + + + while (tmp && tmp != private) + tmp = tmp->parent; + + if (tmp) + gdk_pointer_xgrab_window = NULL; + } + + if (gdk_keyboard_xgrab_window && serial >= gdk_keyboard_xgrab_serial) + { + GdkWindowObject *private = GDK_WINDOW_OBJECT (window); + GdkWindowObject *tmp = gdk_keyboard_xgrab_window; + + + while (tmp && tmp != private) + tmp = tmp->parent; + + if (tmp) + gdk_keyboard_xgrab_window = NULL; + } +} + +/** + * _gdk_xgrab_check_destroy: + * @window: a #GdkWindow + * + * Checks to see if window is the current grab window, and if + * so, clear the current grab window. + **/ +void +_gdk_xgrab_check_destroy (GdkWindow *window) +{ + if ((GdkWindowObject *)window == gdk_pointer_xgrab_window) + gdk_pointer_xgrab_window = NULL; + + if ((GdkWindowObject *)window == gdk_keyboard_xgrab_window) + gdk_keyboard_xgrab_window = NULL; } /* diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index a495c5187..2035e2066 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -165,6 +165,10 @@ GC _gdk_x11_gc_flush (GdkGC *gc); void _gdk_x11_initialize_locale (void); +void _gdk_xgrab_check_unmap (GdkWindow *window, + gulong serial); +void _gdk_xgrab_check_destroy (GdkWindow *window); + extern GdkDrawableClass _gdk_x11_drawable_class; extern Window _gdk_root_window; extern gboolean _gdk_use_xshm; @@ -177,10 +181,6 @@ extern gchar *_gdk_display_name; extern Window _gdk_leader_window; -extern GdkWindowObject *_gdk_xgrab_window; /* Window that currently holds the - * x pointer grab - */ - /* Used to detect not-up-to-date keymap */ extern guint _gdk_keymap_serial; diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 53779c08c..4779cb382 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -169,6 +169,8 @@ gdk_window_impl_x11_finalize (GObject *object) wrapper = (GdkWindowObject*) draw_impl->wrapper; + _gdk_xgrab_check_destroy (GDK_WINDOW (wrapper)); + if (!GDK_WINDOW_DESTROYED (wrapper)) { gdk_xid_table_remove (draw_impl->xid); @@ -794,7 +796,9 @@ _gdk_windowing_window_destroy (GdkWindow *window, } } else if (!recursing && !foreign_destroy) - XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window)); + { + XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window)); + } } /* This function is called when the XWindow is really gone. @@ -819,6 +823,8 @@ gdk_window_destroy_notify (GdkWindow *window) gdk_xid_table_remove (GDK_WINDOW_XID (window)); if (window_impl->focus_window) gdk_xid_table_remove (window_impl->focus_window); + + _gdk_xgrab_check_destroy (window); gdk_drawable_unref (window); } @@ -991,6 +997,13 @@ gdk_window_hide (GdkWindow *window) private = (GdkWindowObject*) window; + /* We'll get the unmap notify eventually, and handle it then, + * but checking here makes things more consistent if we are + * just doing stuff ourself. + */ + _gdk_xgrab_check_unmap (window, + NextRequest (GDK_WINDOW_XDISPLAY (window))); + /* You can't simply unmap toplevel windows. */ switch (private->window_type) { |