mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 02:40:11 +00:00
New approach for grab tracking code
We try to track the exact grab state, i.e. whats valid on the client now and whats comming soon via the xserver roundtrip (and when).
This commit is contained in:
parent
526ff6dd68
commit
26cbf87d7d
481
gdk/gdkdisplay.c
481
gdk/gdkdisplay.c
@ -750,69 +750,150 @@ generate_grab_broken_event (GdkWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_display_set_has_pointer_grab (GdkDisplay *display,
|
||||
/* Get the pointer grab in effects for events we just sent */
|
||||
GdkPointerGrabInfo *
|
||||
_gdk_display_get_active_pointer_grab (GdkDisplay *display)
|
||||
{
|
||||
GdkPointerGrabInfo *info;
|
||||
|
||||
if (display->pointer_grabs == NULL)
|
||||
return NULL;
|
||||
|
||||
info = display->pointer_grabs->data;
|
||||
|
||||
if (info->activated)
|
||||
return info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
GdkPointerGrabInfo *
|
||||
_gdk_display_get_last_pointer_grab (GdkDisplay *display)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
l = display->pointer_grabs;
|
||||
|
||||
if (l == NULL)
|
||||
return NULL;
|
||||
|
||||
while (l->next != NULL)
|
||||
l = l->next;
|
||||
|
||||
return (GdkPointerGrabInfo *)l->data;
|
||||
}
|
||||
|
||||
|
||||
GdkPointerGrabInfo *
|
||||
_gdk_display_add_pointer_grab (GdkDisplay *display,
|
||||
GdkWindow *window,
|
||||
GdkWindow *native_window,
|
||||
gboolean owner_events,
|
||||
GdkEventMask event_mask,
|
||||
unsigned long serial,
|
||||
unsigned long serial_start,
|
||||
guint32 time,
|
||||
gboolean implicit)
|
||||
{
|
||||
GdkWindow *src_toplevel, *dest_toplevel, *src_window;
|
||||
GdkPointerGrabInfo *info, *other_info;
|
||||
GList *l;
|
||||
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
display->pointer_grab.window != window)
|
||||
info = g_new0 (GdkPointerGrabInfo, 1);
|
||||
|
||||
info->window = g_object_ref (window);
|
||||
info->native_window = g_object_ref (native_window);
|
||||
info->serial_start = serial_start;
|
||||
info->serial_end = G_MAXULONG;
|
||||
info->owner_events = owner_events;
|
||||
info->event_mask = event_mask;
|
||||
info->time = time;
|
||||
info->implicit = implicit;
|
||||
info->converted_implicit = FALSE;
|
||||
|
||||
/* Find the first grab that has a larger start time (if any) and insert
|
||||
* before that. I.E we insert after already existing grabs with same
|
||||
* start time */
|
||||
for (l = display->pointer_grabs; l != NULL; l = l->next)
|
||||
{
|
||||
generate_grab_broken_event (GDK_WINDOW (display->pointer_grab.window),
|
||||
FALSE, display->pointer_grab.implicit,
|
||||
window);
|
||||
other_info = l->data;
|
||||
|
||||
if (info->serial_start < other_info->serial_start)
|
||||
break;
|
||||
}
|
||||
display->pointer_grabs =
|
||||
g_list_insert_before (display->pointer_grabs, l, info);
|
||||
|
||||
/* Make sure the new grab end before next grab */
|
||||
if (l)
|
||||
{
|
||||
other_info = l->data;
|
||||
info->serial_end = other_info->serial_start;
|
||||
}
|
||||
|
||||
/* We need to generate crossing events for the grab.
|
||||
* However, there are never any crossing events for implicit grabs
|
||||
* TODO: ... Actually, this could happen if the pointer window doesn't have button mask so a parent gets the event...
|
||||
*/
|
||||
if (!implicit)
|
||||
/* Find any previous grab and update its end time */
|
||||
l = g_list_find (display->pointer_grabs, info);
|
||||
l = l->prev;
|
||||
if (l)
|
||||
{
|
||||
int x, y;
|
||||
other_info = l->data;
|
||||
other_info->serial_end = serial_start;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
free_pointer_grab (GdkPointerGrabInfo *info)
|
||||
{
|
||||
g_object_unref (info->window);
|
||||
g_object_unref (info->native_window);
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
/* _gdk_syntesize_crossing_events only works inside one toplevel.
|
||||
This function splits things into two calls if needed, converting the
|
||||
coordinates to the right toplevel */
|
||||
static void
|
||||
synthesize_crossing_events (GdkDisplay *display,
|
||||
GdkWindow *src_window,
|
||||
GdkWindow *dest_window,
|
||||
GdkCrossingMode crossing_mode,
|
||||
guint32 time,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindow *src_toplevel, *dest_toplevel;
|
||||
GdkModifierType state;
|
||||
int x, y;
|
||||
|
||||
/* We send GRAB crossing events from the window under the pointer to the
|
||||
grab window. Except if there is an old grab then we start from that */
|
||||
if (display->pointer_grab.window)
|
||||
src_window = display->pointer_grab.window;
|
||||
else
|
||||
src_window = display->pointer_info.window_under_pointer;
|
||||
|
||||
/* Unset any current grab to make sure we send the events */
|
||||
display->pointer_grab.window = NULL;
|
||||
|
||||
if (src_window != window)
|
||||
{
|
||||
/* _gdk_syntesize_crossing_events only works inside one toplevel, split into two calls if needed */
|
||||
if (src_window)
|
||||
src_toplevel = gdk_window_get_toplevel (src_window);
|
||||
else
|
||||
src_toplevel = NULL;
|
||||
dest_toplevel = gdk_window_get_toplevel (window);
|
||||
if (dest_window)
|
||||
dest_toplevel = gdk_window_get_toplevel (dest_window);
|
||||
else
|
||||
dest_toplevel = NULL;
|
||||
|
||||
if (src_toplevel == NULL && dest_toplevel == NULL)
|
||||
return;
|
||||
|
||||
if (src_toplevel == NULL ||
|
||||
src_toplevel == dest_toplevel)
|
||||
{
|
||||
/* Same toplevels */
|
||||
_gdk_windowing_window_get_pointer (display,
|
||||
dest_toplevel,
|
||||
&x, &y, &state);
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
src_window,
|
||||
window,
|
||||
GDK_CROSSING_GRAB,
|
||||
dest_window,
|
||||
crossing_mode,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL);
|
||||
NULL,
|
||||
serial);
|
||||
}
|
||||
else
|
||||
else if (dest_toplevel == NULL)
|
||||
{
|
||||
_gdk_windowing_window_get_pointer (display,
|
||||
src_toplevel,
|
||||
@ -820,66 +901,94 @@ _gdk_display_set_has_pointer_grab (GdkDisplay *display,
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
src_window,
|
||||
NULL,
|
||||
GDK_CROSSING_GRAB,
|
||||
crossing_mode,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL);
|
||||
NULL,
|
||||
serial);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Different toplevels */
|
||||
_gdk_windowing_window_get_pointer (display,
|
||||
src_toplevel,
|
||||
&x, &y, &state);
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
src_window,
|
||||
NULL,
|
||||
crossing_mode,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL,
|
||||
serial);
|
||||
_gdk_windowing_window_get_pointer (display,
|
||||
dest_toplevel,
|
||||
&x, &y, &state);
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
NULL,
|
||||
window,
|
||||
GDK_CROSSING_GRAB,
|
||||
dest_window,
|
||||
crossing_mode,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL);
|
||||
NULL,
|
||||
serial);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
switch_to_pointer_grab (GdkDisplay *display,
|
||||
GdkPointerGrabInfo *grab,
|
||||
GdkPointerGrabInfo *last_grab,
|
||||
guint32 time,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindow *src_window, *pointer_window;
|
||||
GdkWindowObject *w;
|
||||
GList *old_grabs;
|
||||
GdkModifierType state;
|
||||
int x, y;
|
||||
|
||||
/* Temporarily unset pointer to make sure we send the crossing events below */
|
||||
old_grabs = display->pointer_grabs;
|
||||
display->pointer_grabs = NULL;
|
||||
|
||||
if (grab)
|
||||
{
|
||||
/* New grab is in effect */
|
||||
|
||||
/* We need to generate crossing events for the grab.
|
||||
* However, there are never any crossing events for implicit grabs
|
||||
* TODO: ... Actually, this could happen if the pointer window
|
||||
* doesn't have button mask so a parent gets the event...
|
||||
*/
|
||||
if (!grab->implicit)
|
||||
{
|
||||
/* We send GRAB crossing events from the window under the pointer to the
|
||||
grab window. Except if there is an old grab then we start from that */
|
||||
if (last_grab)
|
||||
src_window = last_grab->window;
|
||||
else
|
||||
src_window = display->pointer_info.window_under_pointer;
|
||||
|
||||
if (src_window != grab->window)
|
||||
{
|
||||
synthesize_crossing_events (display,
|
||||
src_window, grab->window,
|
||||
GDK_CROSSING_GRAB, time, serial);
|
||||
}
|
||||
|
||||
/* !owner_event Grabbing a window that we're not inside, current status is
|
||||
now NULL (i.e. outside grabbed window) */
|
||||
if (!owner_events && display->pointer_info.window_under_pointer != window)
|
||||
if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window)
|
||||
_gdk_display_set_window_under_pointer (display, NULL);
|
||||
}
|
||||
|
||||
display->pointer_grab.window = window;
|
||||
display->pointer_grab.native_window = native_window;
|
||||
display->pointer_grab.serial = serial;
|
||||
display->pointer_grab.owner_events = owner_events;
|
||||
display->pointer_grab.event_mask = event_mask;
|
||||
display->pointer_grab.time = time;
|
||||
display->pointer_grab.implicit = implicit;
|
||||
display->pointer_grab.converted_implicit = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_display_unset_has_pointer_grab (GdkDisplay *display,
|
||||
gboolean implicit,
|
||||
gboolean do_grab_one_pointer_release_event,
|
||||
guint32 time)
|
||||
{
|
||||
GdkWindow *pointer_window, *src_toplevel, *dest_toplevel;
|
||||
GdkWindow *old_grab_window;
|
||||
GdkWindow *old_native_grab_window;
|
||||
int x, y;
|
||||
GdkModifierType state;
|
||||
GdkWindowObject *w;
|
||||
|
||||
old_grab_window = display->pointer_grab.window;
|
||||
old_native_grab_window = display->pointer_grab.native_window;
|
||||
|
||||
if (old_grab_window == NULL)
|
||||
return; /* This happens in the gdk_window_hide case */
|
||||
|
||||
if (do_grab_one_pointer_release_event)
|
||||
display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
|
||||
|
||||
/* Set first so crossing events get sent */
|
||||
display->pointer_grab.window = NULL;
|
||||
|
||||
grab->activated = TRUE;
|
||||
}
|
||||
else if (last_grab)
|
||||
{
|
||||
pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state);
|
||||
|
||||
if (pointer_window != NULL &&
|
||||
(GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
|
||||
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
|
||||
@ -905,73 +1014,170 @@ _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
|
||||
}
|
||||
|
||||
/* w is now toplevel and x,y in toplevel coords */
|
||||
|
||||
display->pointer_info.toplevel_under_pointer = g_object_ref (w);
|
||||
|
||||
/* Find child window */
|
||||
/* Find (possibly virtual) child window */
|
||||
pointer_window =
|
||||
_gdk_window_find_descendant_at ((GdkWindow *)w,
|
||||
x, y,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (pointer_window == NULL)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
old_grab_window,
|
||||
NULL,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pointer_window != old_grab_window)
|
||||
{
|
||||
/* _gdk_syntesize_crossing_events only works inside one toplevel, split into two calls if needed */
|
||||
src_toplevel = gdk_window_get_toplevel (old_grab_window);
|
||||
dest_toplevel = gdk_window_get_toplevel (pointer_window);
|
||||
|
||||
if (src_toplevel == dest_toplevel)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
pointer_window,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: We're reporting the wrong coords here. They are in pointer_window toplevel coords */
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
NULL,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL);
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
NULL,
|
||||
pointer_window,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pointer_window != last_grab->window)
|
||||
synthesize_crossing_events (display,
|
||||
last_grab->window, pointer_window,
|
||||
GDK_CROSSING_UNGRAB, time, serial);
|
||||
|
||||
/* We're now ungrabbed, update the window_under_pointer */
|
||||
_gdk_display_set_window_under_pointer (display, pointer_window);
|
||||
|
||||
if (implicit)
|
||||
generate_grab_broken_event (old_grab_window,
|
||||
FALSE, implicit,
|
||||
if (last_grab->implicit_ungrab)
|
||||
generate_grab_broken_event (last_grab->window,
|
||||
FALSE, TRUE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
display->pointer_grabs = old_grabs;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_display_pointer_grab_update (GdkDisplay *display,
|
||||
gulong current_serial)
|
||||
{
|
||||
GdkPointerGrabInfo *current_grab, *next_grab;
|
||||
guint32 time;
|
||||
|
||||
time = display->last_event_time;
|
||||
|
||||
while (display->pointer_grabs != NULL)
|
||||
{
|
||||
current_grab = display->pointer_grabs->data;
|
||||
|
||||
if (current_grab->serial_start > current_serial)
|
||||
return; /* Hasn't started yet */
|
||||
|
||||
if (current_grab->serial_end > current_serial ||
|
||||
(current_grab->serial_end == current_serial &&
|
||||
current_grab->grab_one_pointer_release_event))
|
||||
{
|
||||
/* This one hasn't ended yet.
|
||||
its the currently active one or scheduled to be active */
|
||||
|
||||
if (!current_grab->activated)
|
||||
switch_to_pointer_grab (display, current_grab, NULL, time, current_serial);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
next_grab = NULL;
|
||||
if (display->pointer_grabs->next)
|
||||
{
|
||||
/* This is the next active grab */
|
||||
next_grab = display->pointer_grabs->next->data;
|
||||
|
||||
if (next_grab->serial_start > current_serial)
|
||||
next_grab = NULL; /* Actually its not yet active */
|
||||
}
|
||||
|
||||
if (next_grab == NULL ||
|
||||
current_grab->window != next_grab->window)
|
||||
generate_grab_broken_event (GDK_WINDOW (current_grab->window),
|
||||
FALSE, current_grab->implicit,
|
||||
next_grab? next_grab->window : NULL);
|
||||
|
||||
|
||||
/* Remove old grab */
|
||||
display->pointer_grabs =
|
||||
g_list_delete_link (display->pointer_grabs,
|
||||
display->pointer_grabs);
|
||||
|
||||
switch_to_pointer_grab (display,
|
||||
next_grab, current_grab,
|
||||
time, current_serial);
|
||||
|
||||
free_pointer_grab (current_grab);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_parent_of (GdkWindow *parent,
|
||||
GdkWindow *child)
|
||||
{
|
||||
GdkWindow *w;
|
||||
|
||||
w = child;
|
||||
while (w != NULL)
|
||||
{
|
||||
if (w == parent)
|
||||
return TRUE;
|
||||
|
||||
w = gdk_window_get_parent (w);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GList *
|
||||
find_pointer_grab (GdkDisplay *display,
|
||||
gulong serial)
|
||||
{
|
||||
GdkPointerGrabInfo *grab;
|
||||
GList *l;
|
||||
|
||||
for (l = display->pointer_grabs; l != NULL; l = l->next)
|
||||
{
|
||||
grab = l->data;
|
||||
|
||||
if (serial >= grab->serial_start && serial < grab->serial_end)
|
||||
return l;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GdkPointerGrabInfo *
|
||||
_gdk_display_has_pointer_grab (GdkDisplay *display,
|
||||
gulong serial)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
l = find_pointer_grab (display, serial);
|
||||
if (l)
|
||||
return l->data;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns true if last grab was ended */
|
||||
gboolean
|
||||
_gdk_display_end_pointer_grab (GdkDisplay *display,
|
||||
gulong serial,
|
||||
GdkWindow *if_child,
|
||||
gboolean implicit)
|
||||
{
|
||||
GdkPointerGrabInfo *grab;
|
||||
GList *l;
|
||||
|
||||
l = find_pointer_grab (display, serial);
|
||||
|
||||
if (l == NULL)
|
||||
return FALSE;
|
||||
|
||||
grab = l->data;
|
||||
if (grab &&
|
||||
(if_child == NULL ||
|
||||
is_parent_of (grab->window, if_child)))
|
||||
{
|
||||
grab->serial_end = serial;
|
||||
grab->implicit_ungrab = implicit;
|
||||
return l->next == NULL;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1055,14 +1261,18 @@ gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
|
||||
GdkWindow **grab_window,
|
||||
gboolean *owner_events)
|
||||
{
|
||||
GdkPointerGrabInfo *info;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
if (display->pointer_grab.window)
|
||||
info = _gdk_display_get_active_pointer_grab (display);
|
||||
|
||||
if (info)
|
||||
{
|
||||
if (grab_window)
|
||||
*grab_window = (GdkWindow *)display->pointer_grab.window;
|
||||
*grab_window = info->window;
|
||||
if (owner_events)
|
||||
*owner_events = display->pointer_grab.owner_events;
|
||||
*owner_events = info->owner_events;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1084,10 +1294,13 @@ gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
|
||||
gboolean
|
||||
gdk_display_pointer_is_grabbed (GdkDisplay *display)
|
||||
{
|
||||
GdkPointerGrabInfo *info;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
|
||||
|
||||
return (display->pointer_grab.window != NULL &&
|
||||
!display->pointer_grab.implicit);
|
||||
info = _gdk_display_get_active_pointer_grab (display);
|
||||
|
||||
return (info && !info->implicit);
|
||||
}
|
||||
|
||||
#define __GDK_DISPLAY_C__
|
||||
|
@ -43,21 +43,6 @@ typedef struct _GdkDisplayPointerHooks GdkDisplayPointerHooks;
|
||||
#define GDK_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY))
|
||||
#define GDK_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY, GdkDisplayClass))
|
||||
|
||||
/* Tracks information about the pointer grab on this display */
|
||||
typedef struct
|
||||
{
|
||||
GdkWindow *window;
|
||||
GdkWindow *native_window;
|
||||
gulong serial;
|
||||
gboolean owner_events;
|
||||
guint event_mask;
|
||||
gboolean implicit;
|
||||
gboolean converted_implicit;
|
||||
guint32 time;
|
||||
|
||||
GdkWindow *grab_one_pointer_release_event;
|
||||
} GdkPointerGrabInfo;
|
||||
|
||||
/* Tracks information about the keyboard grab on this display */
|
||||
typedef struct
|
||||
{
|
||||
@ -68,7 +53,6 @@ typedef struct
|
||||
guint32 time;
|
||||
} GdkKeyboardGrabInfo;
|
||||
|
||||
|
||||
/* Tracks information about which window and position the pointer last was in.
|
||||
* This is useful when we need to synthesize events later.
|
||||
* Note that we track toplevel_under_pointer using enter/leave events,
|
||||
@ -112,9 +96,12 @@ struct _GdkDisplay
|
||||
gint button_x[2]; /* The last 2 button click positions. */
|
||||
gint button_y[2];
|
||||
|
||||
GdkPointerGrabInfo pointer_grab;
|
||||
GList *pointer_grabs;
|
||||
GdkKeyboardGrabInfo keyboard_grab;
|
||||
GdkPointerWindowInfo pointer_info;
|
||||
|
||||
/* Last reported event time from server */
|
||||
guint32 last_event_time;
|
||||
};
|
||||
|
||||
struct _GdkDisplayClass
|
||||
|
@ -170,6 +170,24 @@ struct _GdkEventPrivate
|
||||
gpointer windowing_data;
|
||||
};
|
||||
|
||||
/* Tracks information about the pointer grab on this display */
|
||||
typedef struct
|
||||
{
|
||||
GdkWindow *window;
|
||||
GdkWindow *native_window;
|
||||
gulong serial_start;
|
||||
gulong serial_end; /* exclusive, i.e. not active on serial_end */
|
||||
gboolean owner_events;
|
||||
guint event_mask;
|
||||
gboolean implicit;
|
||||
gboolean converted_implicit;
|
||||
guint32 time;
|
||||
|
||||
gboolean activated;
|
||||
gboolean implicit_ungrab;
|
||||
gboolean grab_one_pointer_release_event;
|
||||
} GdkPointerGrabInfo;
|
||||
|
||||
extern GdkEventFunc _gdk_event_func; /* Callback for events */
|
||||
extern gpointer _gdk_event_data;
|
||||
extern GDestroyNotify _gdk_event_notify;
|
||||
@ -464,18 +482,24 @@ char *_gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
|
||||
void _gdk_windowing_launch_failed (GAppLaunchContext *context,
|
||||
const char *startup_notify_id);
|
||||
|
||||
void _gdk_display_set_has_pointer_grab (GdkDisplay *display,
|
||||
GdkPointerGrabInfo *_gdk_display_get_active_pointer_grab (GdkDisplay *display);
|
||||
void _gdk_display_pointer_grab_update (GdkDisplay *display,
|
||||
gulong current_serial);
|
||||
GdkPointerGrabInfo *_gdk_display_get_last_pointer_grab (GdkDisplay *display);
|
||||
GdkPointerGrabInfo *_gdk_display_add_pointer_grab (GdkDisplay *display,
|
||||
GdkWindow *window,
|
||||
GdkWindow *native_window,
|
||||
gboolean owner_events,
|
||||
GdkEventMask event_mask,
|
||||
unsigned long serial,
|
||||
unsigned long serial_start,
|
||||
guint32 time,
|
||||
gboolean implicit);
|
||||
void _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
|
||||
gboolean implicit,
|
||||
gboolean do_grab_one_pointer_release_event,
|
||||
guint32 time);
|
||||
GdkPointerGrabInfo * _gdk_display_has_pointer_grab (GdkDisplay *display,
|
||||
gulong serial);
|
||||
gboolean _gdk_display_end_pointer_grab (GdkDisplay *display,
|
||||
gulong serial,
|
||||
GdkWindow *if_child,
|
||||
gboolean implicit);
|
||||
void _gdk_display_set_has_keyboard_grab (GdkDisplay *display,
|
||||
GdkWindow *window,
|
||||
GdkWindow *native_window,
|
||||
@ -518,7 +542,8 @@ void _gdk_syntesize_crossing_events (GdkDisplay *display,
|
||||
gint toplevel_y,
|
||||
GdkModifierType mask,
|
||||
guint32 time_,
|
||||
GdkEvent *event_in_queue);
|
||||
GdkEvent *event_in_queue,
|
||||
gulong serial);
|
||||
void _gdk_display_set_window_under_pointer (GdkDisplay *display,
|
||||
GdkWindow *window);
|
||||
|
||||
|
@ -852,6 +852,8 @@ gdk_offscreen_window_hide (GdkWindow *window)
|
||||
/* May need to break grabs on children */
|
||||
display = gdk_drawable_get_display (window);
|
||||
|
||||
/* TODO: This needs updating to the new grab world */
|
||||
#if 0
|
||||
if (display->pointer_grab.window != NULL)
|
||||
{
|
||||
if (is_parent_of (window, display->pointer_grab.window))
|
||||
@ -866,6 +868,7 @@ gdk_offscreen_window_hide (GdkWindow *window)
|
||||
gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
191
gdk/gdkwindow.c
191
gdk/gdkwindow.c
@ -5725,20 +5725,11 @@ gdk_window_hide (GdkWindow *window)
|
||||
/* May need to break grabs on children */
|
||||
display = gdk_drawable_get_display (window);
|
||||
|
||||
if (display->pointer_grab.window != NULL)
|
||||
{
|
||||
if (is_parent_of (window, display->pointer_grab.window))
|
||||
{
|
||||
/* Call this ourselves, even though gdk_display_pointer_ungrab
|
||||
does so too, since we want to pass implicit == TRUE so the
|
||||
broken grab event is generated */
|
||||
_gdk_display_unset_has_pointer_grab (display,
|
||||
TRUE,
|
||||
FALSE,
|
||||
GDK_CURRENT_TIME);
|
||||
if (_gdk_display_end_pointer_grab (display,
|
||||
_gdk_windowing_window_get_next_serial (display),
|
||||
window,
|
||||
TRUE))
|
||||
gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
if (display->keyboard_grab.window != NULL)
|
||||
{
|
||||
@ -6561,6 +6552,7 @@ static void
|
||||
update_cursor (GdkDisplay *display)
|
||||
{
|
||||
GdkWindowObject *pointer_window, *cursor_window;
|
||||
GdkPointerGrabInfo *grab;
|
||||
|
||||
pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
|
||||
|
||||
@ -6570,13 +6562,17 @@ update_cursor (GdkDisplay *display)
|
||||
cursor_window->parent->window_type != GDK_WINDOW_ROOT)
|
||||
cursor_window = cursor_window->parent;
|
||||
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
!is_parent_of (display->pointer_grab.window, (GdkWindow *)cursor_window))
|
||||
cursor_window = (GdkWindowObject *)display->pointer_grab.window;
|
||||
/* We ignore the serials here and just pick the last grab
|
||||
we've sent, as that would shortly be used anyway. */
|
||||
grab = _gdk_display_get_last_pointer_grab (display);
|
||||
if (grab != NULL &&
|
||||
!is_parent_of (grab->window, (GdkWindow *)cursor_window))
|
||||
cursor_window = (GdkWindowObject *)grab->window;
|
||||
|
||||
/* Set all cursors on toplevel, otherwise its tricky to keep track of
|
||||
* which native window has what cursor set. */
|
||||
GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor (gdk_window_get_toplevel ((GdkWindow *)pointer_window),
|
||||
GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor
|
||||
(gdk_window_get_toplevel ((GdkWindow *)pointer_window),
|
||||
cursor_window->cursor);
|
||||
}
|
||||
|
||||
@ -7869,14 +7865,18 @@ send_crossing_event (GdkDisplay *display,
|
||||
gint toplevel_y,
|
||||
GdkModifierType mask,
|
||||
guint32 time_,
|
||||
GdkEvent *event_in_queue)
|
||||
GdkEvent *event_in_queue,
|
||||
gulong serial)
|
||||
{
|
||||
GdkEvent *event;
|
||||
guint32 event_mask;
|
||||
GdkPointerGrabInfo *grab;
|
||||
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
!display->pointer_grab.owner_events &&
|
||||
(GdkWindow *)window != display->pointer_grab.window)
|
||||
grab = _gdk_display_has_pointer_grab (display, serial);
|
||||
|
||||
if (grab != NULL &&
|
||||
!grab->owner_events &&
|
||||
(GdkWindow *)window != grab->window)
|
||||
return;
|
||||
|
||||
if (type == GDK_LEAVE_NOTIFY)
|
||||
@ -7918,7 +7918,8 @@ _gdk_syntesize_crossing_events (GdkDisplay *display,
|
||||
gint toplevel_y,
|
||||
GdkModifierType mask,
|
||||
guint32 time_,
|
||||
GdkEvent *event_in_queue)
|
||||
GdkEvent *event_in_queue,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindowObject *c;
|
||||
GdkWindowObject *win, *last, *next;
|
||||
@ -7958,7 +7959,8 @@ _gdk_syntesize_crossing_events (GdkDisplay *display,
|
||||
NULL,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue);
|
||||
event_in_queue,
|
||||
serial);
|
||||
|
||||
if (c != a)
|
||||
{
|
||||
@ -7978,7 +7980,8 @@ _gdk_syntesize_crossing_events (GdkDisplay *display,
|
||||
(GdkWindow *)last,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue);
|
||||
event_in_queue,
|
||||
serial);
|
||||
|
||||
last = win;
|
||||
win = win->parent;
|
||||
@ -8023,7 +8026,8 @@ _gdk_syntesize_crossing_events (GdkDisplay *display,
|
||||
(GdkWindow *)next,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue);
|
||||
event_in_queue,
|
||||
serial);
|
||||
}
|
||||
g_list_free (path);
|
||||
}
|
||||
@ -8043,7 +8047,8 @@ _gdk_syntesize_crossing_events (GdkDisplay *display,
|
||||
NULL,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue);
|
||||
event_in_queue,
|
||||
serial);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8067,9 +8072,11 @@ static GdkWindow *
|
||||
get_pointer_window (GdkDisplay *display,
|
||||
GdkWindow *event_window,
|
||||
gdouble toplevel_x,
|
||||
gdouble toplevel_y)
|
||||
gdouble toplevel_y,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindow *pointer_window;
|
||||
GdkPointerGrabInfo *grab;
|
||||
|
||||
if (event_window == display->pointer_info.toplevel_under_pointer)
|
||||
pointer_window =
|
||||
@ -8079,9 +8086,10 @@ get_pointer_window (GdkDisplay *display,
|
||||
else
|
||||
pointer_window = NULL;
|
||||
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
!display->pointer_grab.owner_events &&
|
||||
pointer_window != display->pointer_grab.window)
|
||||
grab = _gdk_display_has_pointer_grab (display, serial);
|
||||
if (grab != NULL &&
|
||||
!grab->owner_events &&
|
||||
pointer_window != grab->window)
|
||||
pointer_window = NULL;
|
||||
|
||||
return pointer_window;
|
||||
@ -8113,16 +8121,20 @@ _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
|
||||
GdkDisplay *display;
|
||||
GdkWindow *changed_toplevel;
|
||||
GdkWindow *new_window_under_pointer;
|
||||
|
||||
changed_toplevel = get_toplevel (changed_window);
|
||||
gulong serial;
|
||||
|
||||
display = gdk_drawable_get_display (changed_window);
|
||||
|
||||
serial = _gdk_windowing_window_get_next_serial (display);
|
||||
changed_toplevel = get_toplevel (changed_window);
|
||||
|
||||
if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
|
||||
{
|
||||
new_window_under_pointer =
|
||||
get_pointer_window (display, changed_toplevel,
|
||||
display->pointer_info.toplevel_x,
|
||||
display->pointer_info.toplevel_y);
|
||||
display->pointer_info.toplevel_y,
|
||||
serial);
|
||||
if (new_window_under_pointer !=
|
||||
display->pointer_info.window_under_pointer)
|
||||
{
|
||||
@ -8134,7 +8146,8 @@ _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
|
||||
display->pointer_info.toplevel_y,
|
||||
display->pointer_info.state,
|
||||
GDK_CURRENT_TIME,
|
||||
NULL);
|
||||
NULL,
|
||||
serial);
|
||||
_gdk_display_set_window_under_pointer (display, new_window_under_pointer);
|
||||
}
|
||||
}
|
||||
@ -8146,27 +8159,22 @@ get_event_window (GdkDisplay *display,
|
||||
GdkWindow *pointer_window,
|
||||
GdkEventType type,
|
||||
GdkModifierType mask,
|
||||
guint *evmask_out)
|
||||
guint *evmask_out,
|
||||
gulong serial)
|
||||
{
|
||||
guint evmask;
|
||||
GdkWindow *grab_window;
|
||||
GdkWindowObject *w;
|
||||
GdkPointerGrabInfo *grab;
|
||||
|
||||
if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
|
||||
(type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
|
||||
grab = _gdk_display_has_pointer_grab (display, serial);
|
||||
|
||||
if (grab != NULL && !grab->owner_events)
|
||||
{
|
||||
evmask = display->pointer_grab.event_mask;
|
||||
evmask = grab->event_mask;
|
||||
evmask = update_evmask_for_button_motion (evmask, mask);
|
||||
|
||||
if (type == GDK_BUTTON_RELEASE &&
|
||||
display->pointer_grab.grab_one_pointer_release_event)
|
||||
{
|
||||
grab_window = display->pointer_grab.grab_one_pointer_release_event;
|
||||
display->pointer_grab.grab_one_pointer_release_event = NULL;
|
||||
}
|
||||
else
|
||||
grab_window = display->pointer_grab.window;
|
||||
|
||||
grab_window = grab->window;
|
||||
|
||||
if (evmask & type_masks[type])
|
||||
{
|
||||
@ -8194,17 +8202,17 @@ get_event_window (GdkDisplay *display,
|
||||
w = w->parent;
|
||||
}
|
||||
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
display->pointer_grab.owner_events)
|
||||
if (grab != NULL &&
|
||||
grab->owner_events)
|
||||
{
|
||||
evmask = display->pointer_grab.event_mask;
|
||||
evmask = grab->event_mask;
|
||||
evmask = update_evmask_for_button_motion (evmask, mask);
|
||||
|
||||
if (evmask & type_masks[type])
|
||||
{
|
||||
if (evmask_out)
|
||||
*evmask_out = evmask;
|
||||
return display->pointer_grab.window;
|
||||
return grab->window;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
@ -8220,7 +8228,6 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
{
|
||||
GdkWindow *toplevel_window;
|
||||
GdkWindow *pointer_window;
|
||||
GdkWindow *cursor_window;
|
||||
GdkEvent *event;
|
||||
guint state;
|
||||
gdouble toplevel_x, toplevel_y;
|
||||
@ -8231,7 +8238,7 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
gdk_event_get_state (source_event, &state);
|
||||
time_ = gdk_event_get_time (source_event);
|
||||
|
||||
pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
|
||||
pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y, serial);
|
||||
if (display->pointer_info.window_under_pointer != pointer_window)
|
||||
{
|
||||
/* Either a toplevel crossing notify that ended up inside a child window,
|
||||
@ -8244,7 +8251,8 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
GDK_CROSSING_NORMAL,
|
||||
toplevel_x, toplevel_y,
|
||||
state, time_,
|
||||
source_event);
|
||||
source_event,
|
||||
serial);
|
||||
|
||||
_gdk_display_set_window_under_pointer (display, pointer_window);
|
||||
}
|
||||
@ -8258,7 +8266,8 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
pointer_window,
|
||||
source_event->type,
|
||||
state,
|
||||
&evmask);
|
||||
&evmask,
|
||||
serial);
|
||||
|
||||
is_hint = FALSE;
|
||||
|
||||
@ -8291,22 +8300,14 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: set cursor from cursor_window, or grab cursor */
|
||||
cursor_window = pointer_window;
|
||||
if (display->pointer_grab.window &&
|
||||
(pointer_window == NULL ||
|
||||
!is_parent_of (display->pointer_grab.window, pointer_window)))
|
||||
cursor_window = display->pointer_grab.window;
|
||||
/* Actually, this should probably happen in synthesize crossing so it works with geometry changes */
|
||||
|
||||
|
||||
/* unlink all move events from queue.
|
||||
We handle our own, including our emulated masks. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
proxy_button_event (GdkEvent *source_event)
|
||||
proxy_button_event (GdkEvent *source_event,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindow *toplevel_window;
|
||||
GdkWindow *event_win;
|
||||
@ -8318,6 +8319,7 @@ proxy_button_event (GdkEvent *source_event)
|
||||
gdouble toplevel_x, toplevel_y;
|
||||
GdkDisplay *display;
|
||||
GdkWindowObject *w;
|
||||
GdkPointerGrabInfo *grab;
|
||||
|
||||
type = source_event->any.type;
|
||||
toplevel_window = source_event->any.window;
|
||||
@ -8326,10 +8328,11 @@ proxy_button_event (GdkEvent *source_event)
|
||||
time_ = gdk_event_get_time (source_event);
|
||||
display = gdk_drawable_get_display (source_event->any.window);
|
||||
|
||||
grab = _gdk_display_get_active_pointer_grab (display);
|
||||
|
||||
if ((type == GDK_BUTTON_PRESS || type == GDK_SCROLL) &&
|
||||
display->pointer_grab.window == source_event->any.window &&
|
||||
display->pointer_grab.implicit &&
|
||||
!display->pointer_grab.converted_implicit)
|
||||
grab && grab->window == toplevel_window &&
|
||||
grab->implicit && !grab->converted_implicit)
|
||||
{
|
||||
pointer_window =
|
||||
_gdk_window_find_descendant_at (toplevel_window,
|
||||
@ -8347,25 +8350,25 @@ proxy_button_event (GdkEvent *source_event)
|
||||
pointer_window = (GdkWindow *)w;
|
||||
|
||||
if (pointer_window != NULL &&
|
||||
pointer_window != source_event->any.window)
|
||||
_gdk_display_set_has_pointer_grab (display,
|
||||
pointer_window,
|
||||
display->pointer_grab.native_window,
|
||||
display->pointer_grab.owner_events,
|
||||
gdk_window_get_events (pointer_window),
|
||||
display->pointer_grab.serial,
|
||||
display->pointer_grab.time,
|
||||
display->pointer_grab.implicit);
|
||||
display->pointer_grab.converted_implicit = TRUE;
|
||||
pointer_window != toplevel_window)
|
||||
{
|
||||
g_object_ref (pointer_window);
|
||||
g_object_unref (grab->window);
|
||||
grab->window = pointer_window;
|
||||
grab->event_mask = gdk_window_get_events (pointer_window);
|
||||
}
|
||||
|
||||
pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
|
||||
grab->converted_implicit = TRUE;
|
||||
}
|
||||
|
||||
pointer_window = get_pointer_window (display, toplevel_window,
|
||||
toplevel_x, toplevel_y,
|
||||
serial);
|
||||
|
||||
event_win = get_event_window (display,
|
||||
pointer_window,
|
||||
type,
|
||||
state,
|
||||
NULL);
|
||||
type, state,
|
||||
NULL, serial);
|
||||
|
||||
if (event_win == NULL)
|
||||
return TRUE;
|
||||
@ -8478,6 +8481,13 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
gdouble x, y;
|
||||
gboolean unlink_event;
|
||||
guint old_state, old_button;
|
||||
GdkPointerGrabInfo *button_release_grab;
|
||||
|
||||
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
|
||||
display->last_event_time = gdk_event_get_time (event);
|
||||
|
||||
_gdk_display_pointer_grab_update (display,
|
||||
serial);
|
||||
|
||||
event_window = event->any.window;
|
||||
if (!event_window)
|
||||
@ -8559,7 +8569,22 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
event,
|
||||
serial);
|
||||
else if (is_button_type (event->type))
|
||||
unlink_event = proxy_button_event (event);
|
||||
unlink_event = proxy_button_event (event,
|
||||
serial);
|
||||
|
||||
if (event->type == GDK_BUTTON_RELEASE)
|
||||
{
|
||||
button_release_grab =
|
||||
_gdk_display_has_pointer_grab (display, serial);
|
||||
if (button_release_grab &&
|
||||
button_release_grab->grab_one_pointer_release_event)
|
||||
{
|
||||
button_release_grab->grab_one_pointer_release_event = FALSE;
|
||||
button_release_grab->serial_end = serial;
|
||||
button_release_grab->implicit_ungrab = TRUE;
|
||||
_gdk_display_pointer_grab_update (display, serial);
|
||||
}
|
||||
}
|
||||
|
||||
if (unlink_event)
|
||||
{
|
||||
|
@ -118,6 +118,7 @@ struct _RoundtripState
|
||||
Display *dpy;
|
||||
_XAsyncHandler async;
|
||||
gulong get_input_focus_req;
|
||||
GdkDisplay *display;
|
||||
GdkRoundTripCallback callback;
|
||||
gpointer data;
|
||||
};
|
||||
@ -758,7 +759,7 @@ roundtrip_callback_idle (gpointer data)
|
||||
{
|
||||
RoundtripState *state = (RoundtripState *)data;
|
||||
|
||||
state->callback (state->data);
|
||||
state->callback (state->display, state->data, state->get_input_focus_req);
|
||||
|
||||
g_free (state);
|
||||
|
||||
@ -790,6 +791,7 @@ roundtrip_handler (Display *dpy,
|
||||
True);
|
||||
}
|
||||
|
||||
|
||||
if (state->callback)
|
||||
gdk_threads_add_idle (roundtrip_callback_idle, state);
|
||||
|
||||
@ -813,6 +815,7 @@ _gdk_x11_roundtrip_async (GdkDisplay *display,
|
||||
|
||||
state = g_new (RoundtripState, 1);
|
||||
|
||||
state->display = display;
|
||||
state->dpy = dpy;
|
||||
state->callback = callback;
|
||||
state->data = data;
|
||||
|
@ -31,8 +31,9 @@ typedef struct _GdkChildInfoX11 GdkChildInfoX11;
|
||||
typedef void (*GdkSendXEventCallback) (Window window,
|
||||
gboolean success,
|
||||
gpointer data);
|
||||
typedef void (*GdkRoundTripCallback) (gpointer data);
|
||||
|
||||
typedef void (*GdkRoundTripCallback) (GdkDisplay *display,
|
||||
gpointer data,
|
||||
gulong serial);
|
||||
|
||||
struct _GdkChildInfoX11
|
||||
{
|
||||
|
@ -598,16 +598,11 @@ struct XPointerUngrabInfo {
|
||||
};
|
||||
|
||||
static void
|
||||
pointer_ungrab_callback (gpointer _data)
|
||||
pointer_ungrab_callback (GdkDisplay *display,
|
||||
gpointer data,
|
||||
gulong serial)
|
||||
{
|
||||
struct XPointerUngrabInfo *data = _data;
|
||||
|
||||
_gdk_display_unset_has_pointer_grab (data->display,
|
||||
FALSE,
|
||||
FALSE,
|
||||
data->time);
|
||||
|
||||
g_free (data);
|
||||
_gdk_display_pointer_grab_update (display, serial);
|
||||
}
|
||||
|
||||
|
||||
@ -631,30 +626,30 @@ gdk_display_pointer_ungrab (GdkDisplay *display,
|
||||
{
|
||||
Display *xdisplay;
|
||||
GdkDisplayX11 *display_x11;
|
||||
GdkPointerGrabInfo *grab;
|
||||
unsigned long serial;
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
display_x11 = GDK_DISPLAY_X11 (display);
|
||||
xdisplay = GDK_DISPLAY_XDISPLAY (display);
|
||||
|
||||
serial = NextRequest (xdisplay);
|
||||
|
||||
_gdk_input_ungrab_pointer (display, time_);
|
||||
XUngrabPointer (xdisplay, time_);
|
||||
XFlush (xdisplay);
|
||||
|
||||
if (time_ == GDK_CURRENT_TIME ||
|
||||
display->pointer_grab.time == GDK_CURRENT_TIME ||
|
||||
!XSERVER_TIME_IS_LATER (display->pointer_grab.time, time_))
|
||||
grab = _gdk_display_get_last_pointer_grab (display);
|
||||
if (grab &&
|
||||
(time_ == GDK_CURRENT_TIME ||
|
||||
grab->time == GDK_CURRENT_TIME ||
|
||||
!XSERVER_TIME_IS_LATER (grab->time, time_)))
|
||||
{
|
||||
struct XPointerUngrabInfo *data;
|
||||
|
||||
data = g_new (struct XPointerUngrabInfo, 1);
|
||||
|
||||
data->display = GDK_DISPLAY_OBJECT (display_x11);
|
||||
data->time = time_;
|
||||
|
||||
_gdk_x11_roundtrip_async (data->display,
|
||||
grab->serial_end = serial;
|
||||
_gdk_x11_roundtrip_async (display,
|
||||
pointer_ungrab_callback,
|
||||
data);
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,22 +149,11 @@ struct XPointerGrabInfo {
|
||||
};
|
||||
|
||||
static void
|
||||
has_pointer_grab_callback (gpointer _data)
|
||||
has_pointer_grab_callback (GdkDisplay *display,
|
||||
gpointer data,
|
||||
gulong serial)
|
||||
{
|
||||
struct XPointerGrabInfo *data = _data;
|
||||
|
||||
_gdk_display_set_has_pointer_grab (data->display,
|
||||
data->window,
|
||||
data->native_window,
|
||||
data->owner_events,
|
||||
data->event_mask,
|
||||
data->serial,
|
||||
data->time,
|
||||
FALSE);
|
||||
|
||||
g_object_unref (data->window);
|
||||
g_object_unref (data->native_window);
|
||||
g_free (data);
|
||||
_gdk_display_pointer_grab_update (display, serial);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -215,10 +204,18 @@ gdk_pointer_grab (GdkWindow * window,
|
||||
|
||||
native = gdk_window_get_toplevel (window);
|
||||
|
||||
/* We need a native window for confine to to work, ensure we have one */
|
||||
if (confine_to)
|
||||
gdk_window_set_has_native (confine_to, TRUE);
|
||||
|
||||
/* TODO: What do we do for offscreens and their children? We need to proxy the grab somehow */
|
||||
if (!GDK_IS_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (native)->impl))
|
||||
return GDK_GRAB_SUCCESS;
|
||||
|
||||
if (!_gdk_window_has_impl (window) &&
|
||||
!gdk_window_is_viewable (window))
|
||||
return GDK_GRAB_NOT_VIEWABLE;
|
||||
|
||||
if (confine_to)
|
||||
confine_to = _gdk_window_get_impl_window (confine_to);
|
||||
|
||||
@ -285,21 +282,18 @@ gdk_pointer_grab (GdkWindow * window,
|
||||
|
||||
if (return_val == GrabSuccess)
|
||||
{
|
||||
struct XPointerGrabInfo *data;
|
||||
_gdk_display_add_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
|
||||
window,
|
||||
native,
|
||||
owner_events,
|
||||
event_mask,
|
||||
serial,
|
||||
time,
|
||||
FALSE);
|
||||
|
||||
data = g_new (struct XPointerGrabInfo, 1);
|
||||
|
||||
data->display = GDK_DISPLAY_OBJECT (display_x11);
|
||||
data->window = g_object_ref (window);
|
||||
data->native_window = g_object_ref (native);
|
||||
data->owner_events = owner_events;
|
||||
data->event_mask = event_mask;
|
||||
data->serial = serial;
|
||||
data->time = time;
|
||||
|
||||
_gdk_x11_roundtrip_async (data->display,
|
||||
_gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11),
|
||||
has_pointer_grab_callback,
|
||||
data);
|
||||
NULL);
|
||||
}
|
||||
|
||||
return gdk_x11_convert_grab_status (return_val);
|
||||
@ -395,18 +389,7 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
|
||||
{
|
||||
GdkDisplay *display = gdk_drawable_get_display (window);
|
||||
|
||||
if (display->pointer_grab.window &&
|
||||
serial >= display->pointer_grab.serial)
|
||||
{
|
||||
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
|
||||
GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->pointer_grab.native_window);
|
||||
|
||||
while (tmp && tmp != private)
|
||||
tmp = tmp->parent;
|
||||
|
||||
if (tmp)
|
||||
_gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
|
||||
}
|
||||
_gdk_display_end_pointer_grab (display, serial, window, TRUE);
|
||||
|
||||
if (display->keyboard_grab.window &&
|
||||
serial >= display->keyboard_grab.serial)
|
||||
@ -433,10 +416,20 @@ void
|
||||
_gdk_xgrab_check_destroy (GdkWindow *window)
|
||||
{
|
||||
GdkDisplay *display = gdk_drawable_get_display (window);
|
||||
GdkPointerGrabInfo *grab;
|
||||
|
||||
if (window == display->pointer_grab.native_window &&
|
||||
display->pointer_grab.window != NULL)
|
||||
_gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
|
||||
/* Make sure there is no lasting grab in this native
|
||||
window */
|
||||
grab = _gdk_display_get_last_pointer_grab (display);
|
||||
if (grab && grab->native_window == window)
|
||||
{
|
||||
/* We don't know the actual serial to end, but it
|
||||
doesn't really matter as this only happens
|
||||
after we get told of the destroy from the
|
||||
server so we know its ended in the server,
|
||||
just make sure its ended. */
|
||||
grab->serial_end = grab->serial_start;
|
||||
}
|
||||
|
||||
if (window == display->keyboard_grab.native_window &&
|
||||
display->keyboard_grab.window != NULL)
|
||||
@ -461,31 +454,31 @@ _gdk_xgrab_check_button_event (GdkWindow *window,
|
||||
XEvent *xevent)
|
||||
{
|
||||
GdkDisplay *display = gdk_drawable_get_display (window);
|
||||
gulong serial = xevent->xany.serial;
|
||||
GdkPointerGrabInfo *grab;
|
||||
|
||||
/* track implicit grabs for button presses */
|
||||
switch (xevent->type)
|
||||
{
|
||||
case ButtonPress:
|
||||
if (!display->pointer_grab.window)
|
||||
if (!_gdk_display_has_pointer_grab (display, serial))
|
||||
{
|
||||
_gdk_display_set_has_pointer_grab (display,
|
||||
_gdk_display_add_pointer_grab (display,
|
||||
window,
|
||||
window,
|
||||
FALSE,
|
||||
gdk_window_get_events (window),
|
||||
xevent->xany.serial,
|
||||
serial,
|
||||
xevent->xbutton.time,
|
||||
TRUE);
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (display->pointer_grab.window &&
|
||||
display->pointer_grab.implicit &&
|
||||
serial = serial;
|
||||
grab = _gdk_display_has_pointer_grab (display, serial);
|
||||
if (grab && grab->implicit &&
|
||||
(xevent->xbutton.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
|
||||
{
|
||||
_gdk_display_unset_has_pointer_grab (display, TRUE, TRUE,
|
||||
xevent->xbutton.time);
|
||||
}
|
||||
grab->grab_one_pointer_release_event = TRUE;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
|
Loading…
Reference in New Issue
Block a user