}
}
-void
-_gdk_display_set_has_pointer_grab (GdkDisplay *display,
- GdkWindow *window,
- GdkWindow *native_window,
- gboolean owner_events,
- GdkEventMask event_mask,
- unsigned long serial,
- guint32 time,
- gboolean implicit)
+/* Get the pointer grab in effects for events we just sent */
+GdkPointerGrabInfo *
+_gdk_display_get_active_pointer_grab (GdkDisplay *display)
{
- GdkWindow *src_toplevel, *dest_toplevel, *src_window;
+ GdkPointerGrabInfo *info;
+
+ if (display->pointer_grabs == NULL)
+ return NULL;
+
+ info = display->pointer_grabs->data;
+
+ if (info->activated)
+ return info;
- if (display->pointer_grab.window != NULL &&
- display->pointer_grab.window != window)
+ 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_start,
+ guint32 time,
+ gboolean implicit)
+{
+ GdkPointerGrabInfo *info, *other_info;
+ GList *l;
+
+ 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;
- GdkModifierType state;
+ 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;
+
+ if (src_window)
+ src_toplevel = gdk_window_get_toplevel (src_window);
+ else
+ src_toplevel = NULL;
+ 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,
+ dest_window,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial);
+ }
+ else if (dest_toplevel == NULL)
+ {
+ _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);
+ }
+ 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,
+ dest_window,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial);
+ }
+}
- /* 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;
+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 */
- if (src_window != window)
+ /* 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)
{
- /* _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);
+ /* 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_toplevel = NULL;
- dest_toplevel = gdk_window_get_toplevel (window);
+ src_window = display->pointer_info.window_under_pointer;
- if (src_toplevel == NULL ||
- src_toplevel == dest_toplevel)
+ if (src_window != grab->window)
{
- _gdk_windowing_window_get_pointer (display,
- dest_toplevel,
- &x, &y, &state);
- _gdk_syntesize_crossing_events (display,
- src_window,
- window,
- GDK_CROSSING_GRAB,
- x, y, state,
- time,
- NULL);
+ synthesize_crossing_events (display,
+ src_window, grab->window,
+ GDK_CROSSING_GRAB, time, serial);
}
- else
+
+ /* !owner_event Grabbing a window that we're not inside, current status is
+ now NULL (i.e. outside grabbed window) */
+ if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window)
+ _gdk_display_set_window_under_pointer (display, 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))
+ pointer_window = NULL;
+
+ /* We force checked what window we're in, so we need to
+ * update the toplevel_under_pointer info, as that won't get told of
+ * this change.
+ */
+ if (display->pointer_info.toplevel_under_pointer)
+ g_object_unref (display->pointer_info.toplevel_under_pointer);
+ display->pointer_info.toplevel_under_pointer = NULL;
+
+ if (pointer_window)
+ {
+ /* Convert to toplevel */
+ w = (GdkWindowObject *)pointer_window;
+ while (w->parent->window_type != GDK_WINDOW_ROOT)
{
- _gdk_windowing_window_get_pointer (display,
- src_toplevel,
- &x, &y, &state);
- _gdk_syntesize_crossing_events (display,
- src_window,
- NULL,
- GDK_CROSSING_GRAB,
- x, y, state,
- time,
- NULL);
- _gdk_windowing_window_get_pointer (display,
- dest_toplevel,
- &x, &y, &state);
- _gdk_syntesize_crossing_events (display,
- NULL,
- window,
- GDK_CROSSING_GRAB,
- x, y, state,
- time,
- NULL);
+ x += w->x;
+ y += w->y;
+ w = w->parent;
}
+
+ /* w is now toplevel and x,y in toplevel coords */
+ display->pointer_info.toplevel_under_pointer = g_object_ref (w);
+
+ /* Find (possibly virtual) child window */
+ pointer_window =
+ _gdk_window_find_descendant_at ((GdkWindow *)w,
+ x, y,
+ NULL, NULL);
}
- /* !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)
- _gdk_display_set_window_under_pointer (display, 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 (last_grab->implicit_ungrab)
+ generate_grab_broken_event (last_grab->window,
+ FALSE, TRUE,
+ NULL);
}
+
+ display->pointer_grabs = old_grabs;
- 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)
+_gdk_display_pointer_grab_update (GdkDisplay *display,
+ gulong current_serial)
{
- 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;
+ GdkPointerGrabInfo *current_grab, *next_grab;
+ guint32 time;
+
+ time = display->last_event_time;
- if (old_grab_window == NULL)
- return; /* This happens in the gdk_window_hide case */
+ while (display->pointer_grabs != NULL)
+ {
+ current_grab = display->pointer_grabs->data;
- if (do_grab_one_pointer_release_event)
- display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
+ 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 */
- /* Set first so crossing events get sent */
- display->pointer_grab.window = NULL;
-
- pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state);
+ if (!current_grab->activated)
+ switch_to_pointer_grab (display, current_grab, NULL, time, current_serial);
- if (pointer_window != NULL &&
- (GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
- GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
- pointer_window = NULL;
-
- /* We force checked what window we're in, so we need to
- * update the toplevel_under_pointer info, as that won't get told of
- * this change.
- */
- if (display->pointer_info.toplevel_under_pointer)
- g_object_unref (display->pointer_info.toplevel_under_pointer);
- display->pointer_info.toplevel_under_pointer = NULL;
-
- if (pointer_window)
- {
- /* Convert to toplevel */
- w = (GdkWindowObject *)pointer_window;
- while (w->parent->window_type != GDK_WINDOW_ROOT)
+ break;
+ }
+
+
+ next_grab = NULL;
+ if (display->pointer_grabs->next)
{
- x += w->x;
- y += w->y;
- w = w->parent;
+ /* 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 */
}
- /* w is now toplevel and x,y in toplevel coords */
+ 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);
- display->pointer_info.toplevel_under_pointer = g_object_ref (w);
+
+ /* 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);
- /* Find child window */
- pointer_window =
- _gdk_window_find_descendant_at ((GdkWindow *)w,
- x, y,
- NULL, NULL);
+ free_pointer_grab (current_grab);
}
-
-
- if (pointer_window == NULL)
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+ GdkWindow *child)
+{
+ GdkWindow *w;
+
+ w = child;
+ while (w != NULL)
{
- _gdk_syntesize_crossing_events (display,
- old_grab_window,
- NULL,
- GDK_CROSSING_UNGRAB,
- x, y, state,
- time,
- NULL);
+ if (w == parent)
+ return TRUE;
+
+ w = gdk_window_get_parent (w);
}
- else
+
+ 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)
{
- 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);
+ grab = l->data;
- 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 (serial >= grab->serial_start && serial < grab->serial_end)
+ return l;
}
+
+ return NULL;
+}
+
- /* We're now ungrabbed, update the window_under_pointer */
- _gdk_display_set_window_under_pointer (display, pointer_window);
+
+GdkPointerGrabInfo *
+_gdk_display_has_pointer_grab (GdkDisplay *display,
+ gulong serial)
+{
+ GList *l;
+
+ l = find_pointer_grab (display, serial);
+ if (l)
+ return l->data;
- if (implicit)
- generate_grab_broken_event (old_grab_window,
- FALSE, implicit,
- NULL);
+ 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
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;
}
gboolean
gdk_display_pointer_is_grabbed (GdkDisplay *display)
{
+ GdkPointerGrabInfo *info;
+
g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
+
+ info = _gdk_display_get_active_pointer_grab (display);
- return (display->pointer_grab.window != NULL &&
- !display->pointer_grab.implicit);
+ return (info && !info->implicit);
}
#define __GDK_DISPLAY_C__
#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
{
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,
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
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;
void _gdk_windowing_launch_failed (GAppLaunchContext *context,
const char *startup_notify_id);
-void _gdk_display_set_has_pointer_grab (GdkDisplay *display,
- GdkWindow *window,
- GdkWindow *native_window,
- gboolean owner_events,
- GdkEventMask event_mask,
- unsigned long serial,
- guint32 time,
+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_start,
+ guint32 time,
+ gboolean implicit);
+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_unset_has_pointer_grab (GdkDisplay *display,
- gboolean implicit,
- gboolean do_grab_one_pointer_release_event,
- guint32 time);
void _gdk_display_set_has_keyboard_grab (GdkDisplay *display,
GdkWindow *window,
GdkWindow *native_window,
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);
/* 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))
gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
}
}
+#endif
}
static void
/* 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);
- gdk_display_pointer_ungrab (display, 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)
{
update_cursor (GdkDisplay *display)
{
GdkWindowObject *pointer_window, *cursor_window;
+ GdkPointerGrabInfo *grab;
pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
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),
- cursor_window->cursor);
+ GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor
+ (gdk_window_get_toplevel ((GdkWindow *)pointer_window),
+ cursor_window->cursor);
}
/**
gint toplevel_y,
GdkModifierType mask,
guint32 time_,
- GdkEvent *event_in_queue)
+ GdkEvent *event_in_queue,
+ gulong serial)
{
GdkEvent *event;
guint32 event_mask;
-
- if (display->pointer_grab.window != NULL &&
- !display->pointer_grab.owner_events &&
- (GdkWindow *)window != display->pointer_grab.window)
+ GdkPointerGrabInfo *grab;
+
+ grab = _gdk_display_has_pointer_grab (display, serial);
+
+ if (grab != NULL &&
+ !grab->owner_events &&
+ (GdkWindow *)window != grab->window)
return;
if (type == GDK_LEAVE_NOTIFY)
gint toplevel_y,
GdkModifierType mask,
guint32 time_,
- GdkEvent *event_in_queue)
+ GdkEvent *event_in_queue,
+ gulong serial)
{
GdkWindowObject *c;
GdkWindowObject *win, *last, *next;
NULL,
toplevel_x, toplevel_y,
mask, time_,
- event_in_queue);
+ event_in_queue,
+ serial);
if (c != a)
{
(GdkWindow *)last,
toplevel_x, toplevel_y,
mask, time_,
- event_in_queue);
+ event_in_queue,
+ serial);
last = win;
win = win->parent;
(GdkWindow *)next,
toplevel_x, toplevel_y,
mask, time_,
- event_in_queue);
+ event_in_queue,
+ serial);
}
g_list_free (path);
}
NULL,
toplevel_x, toplevel_y,
mask, time_,
- event_in_queue);
+ event_in_queue,
+ serial);
}
}
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 =
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;
GdkDisplay *display;
GdkWindow *changed_toplevel;
GdkWindow *new_window_under_pointer;
+ gulong serial;
+ display = gdk_drawable_get_display (changed_window);
+
+ serial = _gdk_windowing_window_get_next_serial (display);
changed_toplevel = get_toplevel (changed_window);
- display = gdk_drawable_get_display (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)
{
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);
}
}
GdkWindow *pointer_window,
GdkEventType type,
GdkModifierType mask,
- guint *evmask_out)
+ guint *evmask_out,
+ gulong serial)
{
guint evmask;
GdkWindow *grab_window;
GdkWindowObject *w;
+ GdkPointerGrabInfo *grab;
+
+ grab = _gdk_display_has_pointer_grab (display, serial);
- if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
- (type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
+ 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])
{
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;
{
GdkWindow *toplevel_window;
GdkWindow *pointer_window;
- GdkWindow *cursor_window;
GdkEvent *event;
guint state;
gdouble toplevel_x, toplevel_y;
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,
GDK_CROSSING_NORMAL,
toplevel_x, toplevel_y,
state, time_,
- source_event);
+ source_event,
+ serial);
_gdk_display_set_window_under_pointer (display, pointer_window);
}
pointer_window,
source_event->type,
state,
- &evmask);
+ &evmask,
+ serial);
is_hint = FALSE;
}
}
- /* 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;
gdouble toplevel_x, toplevel_y;
GdkDisplay *display;
GdkWindowObject *w;
+ GdkPointerGrabInfo *grab;
type = source_event->any.type;
toplevel_window = source_event->any.window;
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,
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);
+ }
+
+ grab->converted_implicit = TRUE;
}
- 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);
event_win = get_event_window (display,
pointer_window,
- type,
- state,
- NULL);
+ type, state,
+ NULL, serial);
if (event_win == NULL)
return TRUE;
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)
return;
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)
{
Display *dpy;
_XAsyncHandler async;
gulong get_input_focus_req;
+ GdkDisplay *display;
GdkRoundTripCallback callback;
gpointer data;
};
{
RoundtripState *state = (RoundtripState *)data;
- state->callback (state->data);
+ state->callback (state->display, state->data, state->get_input_focus_req);
g_free (state);
True);
}
+
if (state->callback)
gdk_threads_add_idle (roundtrip_callback_idle, state);
state = g_new (RoundtripState, 1);
+ state->display = display;
state->dpy = dpy;
state->callback = callback;
state->data = data;
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
{
};
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);
}
{
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);
}
}
if (window)
g_object_unref (window);
-
+
return return_val;
}
};
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);
}
/*
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);
if (return_val == GrabSuccess)
{
- struct XPointerGrabInfo *data;
-
- 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_display_add_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
+ window,
+ native,
+ owner_events,
+ event_mask,
+ serial,
+ time,
+ FALSE);
- _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);
gulong serial)
{
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)
_gdk_xgrab_check_destroy (GdkWindow *window)
{
GdkDisplay *display = gdk_drawable_get_display (window);
-
- if (window == display->pointer_grab.native_window &&
- display->pointer_grab.window != NULL)
- _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
+ GdkPointerGrabInfo *grab;
+ /* 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)
_gdk_display_unset_has_keyboard_grab (display, TRUE);
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,
- window,
- window,
- FALSE,
- gdk_window_get_events (window),
- xevent->xany.serial,
- xevent->xbutton.time,
- TRUE);
+ _gdk_display_add_pointer_grab (display,
+ window,
+ window,
+ FALSE,
+ gdk_window_get_events (window),
+ 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 ();