summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2002-03-02 20:37:07 +0000
committerOwen Taylor <otaylor@src.gnome.org>2002-03-02 20:37:07 +0000
commitb54e5f4ca17d56f4844caa9485989f65b18babda (patch)
tree951f60c1491f4e7c62c9ead4e18a76c72833f35a /gdk
parentdfe5724765acc217ce43b4f96cc0d6dc2d73016c (diff)
downloadgdk-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.c5
-rw-r--r--gdk/x11/gdkmain-x11.c151
-rw-r--r--gdk/x11/gdkprivate-x11.h8
-rw-r--r--gdk/x11/gdkwindow-x11.c15
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)
{