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)
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user