mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-28 06:21:14 +00:00
gdk: Drop generation of synthesized crossing events on grabs
GDK just needs to care about toplevels nowadays, which means these events are already delivered from the windowing. We don't need to generate intra-window crossing events ourselves.
This commit is contained in:
parent
a9988e18b0
commit
3e1f672170
117
gdk/gdkdisplay.c
117
gdk/gdkdisplay.c
@ -806,97 +806,6 @@ _gdk_display_end_touch_grab (GdkDisplay *display,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* _gdk_synthesize_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,
|
||||
GdkDevice *device,
|
||||
GdkDevice *source_device,
|
||||
GdkWindow *src_window,
|
||||
GdkWindow *dest_window,
|
||||
GdkCrossingMode crossing_mode,
|
||||
guint32 time,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindow *src_toplevel, *dest_toplevel;
|
||||
GdkModifierType state;
|
||||
double 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_window_get_device_position_double (dest_toplevel,
|
||||
device,
|
||||
&x, &y, &state);
|
||||
_gdk_synthesize_crossing_events (display,
|
||||
src_window,
|
||||
dest_window,
|
||||
device, source_device,
|
||||
crossing_mode,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL,
|
||||
serial, FALSE);
|
||||
}
|
||||
else if (dest_toplevel == NULL)
|
||||
{
|
||||
gdk_window_get_device_position_double (src_toplevel,
|
||||
device,
|
||||
&x, &y, &state);
|
||||
_gdk_synthesize_crossing_events (display,
|
||||
src_window,
|
||||
NULL,
|
||||
device, source_device,
|
||||
crossing_mode,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL,
|
||||
serial, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Different toplevels */
|
||||
gdk_window_get_device_position_double (src_toplevel,
|
||||
device,
|
||||
&x, &y, &state);
|
||||
_gdk_synthesize_crossing_events (display,
|
||||
src_window,
|
||||
NULL,
|
||||
device, source_device,
|
||||
crossing_mode,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL,
|
||||
serial, FALSE);
|
||||
gdk_window_get_device_position_double (dest_toplevel,
|
||||
device,
|
||||
&x, &y, &state);
|
||||
_gdk_synthesize_crossing_events (display,
|
||||
NULL,
|
||||
dest_window,
|
||||
device, source_device,
|
||||
crossing_mode,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL,
|
||||
serial, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static GdkWindow *
|
||||
get_current_toplevel (GdkDisplay *display,
|
||||
GdkDevice *device,
|
||||
@ -932,7 +841,7 @@ switch_to_pointer_grab (GdkDisplay *display,
|
||||
guint32 time,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindow *src_window, *pointer_window, *new_toplevel;
|
||||
GdkWindow *pointer_window, *new_toplevel;
|
||||
GdkPointerWindowInfo *info;
|
||||
GList *old_grabs;
|
||||
GdkModifierType state;
|
||||
@ -946,26 +855,8 @@ switch_to_pointer_grab (GdkDisplay *display,
|
||||
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 = info->window_under_pointer;
|
||||
|
||||
if (src_window != grab->window)
|
||||
synthesize_crossing_events (display, device, source_device,
|
||||
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 (!grab->owner_events && info->window_under_pointer != grab->window)
|
||||
@ -1029,12 +920,6 @@ switch_to_pointer_grab (GdkDisplay *display,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
if (!info->need_touch_press_enter &&
|
||||
pointer_window != last_grab->window)
|
||||
synthesize_crossing_events (display, device, source_device,
|
||||
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, device, pointer_window);
|
||||
}
|
||||
|
350
gdk/gdkwindow.c
350
gdk/gdkwindow.c
@ -5466,37 +5466,6 @@ point_in_input_window (GdkWindow *window,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
convert_toplevel_coords_to_window (GdkWindow *window,
|
||||
gdouble toplevel_x,
|
||||
gdouble toplevel_y,
|
||||
gdouble *window_x,
|
||||
gdouble *window_y)
|
||||
{
|
||||
GdkWindow *parent;
|
||||
gdouble x, y;
|
||||
GList *children, *l;
|
||||
|
||||
x = toplevel_x;
|
||||
y = toplevel_y;
|
||||
|
||||
children = NULL;
|
||||
while ((parent = window->parent) != NULL &&
|
||||
(parent->window_type != GDK_WINDOW_ROOT))
|
||||
{
|
||||
children = g_list_prepend (children, window);
|
||||
window = parent;
|
||||
}
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
gdk_window_coords_from_parent (l->data, x, y, &x, &y);
|
||||
|
||||
g_list_free (children);
|
||||
|
||||
*window_x = x;
|
||||
*window_y = y;
|
||||
}
|
||||
|
||||
GdkWindow *
|
||||
_gdk_window_find_child_at (GdkWindow *window,
|
||||
double x,
|
||||
@ -5670,43 +5639,6 @@ gdk_window_get_support_multidevice (GdkWindow *window)
|
||||
|
||||
/* send motion events if the right buttons are down */
|
||||
|
||||
static GdkWindow *
|
||||
find_common_ancestor (GdkWindow *win1,
|
||||
GdkWindow *win2)
|
||||
{
|
||||
GdkWindow *tmp;
|
||||
GList *path1 = NULL, *path2 = NULL;
|
||||
GList *list1, *list2;
|
||||
|
||||
tmp = win1;
|
||||
while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
|
||||
{
|
||||
path1 = g_list_prepend (path1, tmp);
|
||||
tmp = tmp->parent;
|
||||
}
|
||||
|
||||
tmp = win2;
|
||||
while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
|
||||
{
|
||||
path2 = g_list_prepend (path2, tmp);
|
||||
tmp = tmp->parent;
|
||||
}
|
||||
|
||||
list1 = path1;
|
||||
list2 = path2;
|
||||
tmp = NULL;
|
||||
while (list1 && list2 && (list1->data == list2->data))
|
||||
{
|
||||
tmp = list1->data;
|
||||
list1 = list1->next;
|
||||
list2 = list2->next;
|
||||
}
|
||||
g_list_free (path1);
|
||||
g_list_free (path2);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
GdkEvent *
|
||||
_gdk_make_event (GdkWindow *window,
|
||||
GdkEventType type,
|
||||
@ -5827,288 +5759,6 @@ _gdk_make_event (GdkWindow *window,
|
||||
return event;
|
||||
}
|
||||
|
||||
static void
|
||||
send_crossing_event (GdkDisplay *display,
|
||||
GdkWindow *toplevel,
|
||||
GdkWindow *window,
|
||||
GdkEventType type,
|
||||
GdkCrossingMode mode,
|
||||
GdkNotifyType notify_type,
|
||||
GdkWindow *subwindow,
|
||||
GdkDevice *device,
|
||||
GdkDevice *source_device,
|
||||
gdouble toplevel_x,
|
||||
gdouble toplevel_y,
|
||||
GdkModifierType mask,
|
||||
guint32 time_,
|
||||
GdkEvent *event_in_queue,
|
||||
gulong serial)
|
||||
{
|
||||
GdkEvent *event;
|
||||
guint32 window_event_mask, type_event_mask;
|
||||
GdkDeviceGrabInfo *grab;
|
||||
GdkTouchGrabInfo *touch_grab = NULL;
|
||||
GdkPointerWindowInfo *pointer_info;
|
||||
gboolean block_event = FALSE;
|
||||
GdkEventSequence *sequence;
|
||||
|
||||
grab = _gdk_display_has_device_grab (display, device, serial);
|
||||
pointer_info = _gdk_display_get_pointer_info (display, device);
|
||||
|
||||
sequence = gdk_event_get_event_sequence (event_in_queue);
|
||||
if (sequence)
|
||||
touch_grab = _gdk_display_has_touch_grab (display, device, sequence, serial);
|
||||
|
||||
if (touch_grab)
|
||||
{
|
||||
if (window != touch_grab->window)
|
||||
return;
|
||||
|
||||
window_event_mask = touch_grab->event_mask;
|
||||
}
|
||||
else if (grab != NULL &&
|
||||
!grab->owner_events)
|
||||
{
|
||||
/* !owner_event => only report events wrt grab window, ignore rest */
|
||||
if ((GdkWindow *)window != grab->window)
|
||||
return;
|
||||
window_event_mask = grab->event_mask;
|
||||
}
|
||||
else
|
||||
window_event_mask = window->event_mask;
|
||||
|
||||
if (type == GDK_ENTER_NOTIFY &&
|
||||
(pointer_info->need_touch_press_enter ||
|
||||
(source_device &&
|
||||
gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)) &&
|
||||
mode != GDK_CROSSING_TOUCH_BEGIN &&
|
||||
mode != GDK_CROSSING_TOUCH_END)
|
||||
{
|
||||
pointer_info->need_touch_press_enter = TRUE;
|
||||
block_event = TRUE;
|
||||
}
|
||||
else if (type == GDK_LEAVE_NOTIFY)
|
||||
{
|
||||
type_event_mask = GDK_LEAVE_NOTIFY_MASK;
|
||||
window->devices_inside = g_list_remove (window->devices_inside, device);
|
||||
|
||||
if (!window->support_multidevice && window->devices_inside)
|
||||
{
|
||||
/* Block leave events unless it's the last pointer */
|
||||
block_event = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type_event_mask = GDK_ENTER_NOTIFY_MASK;
|
||||
|
||||
if (!window->support_multidevice && window->devices_inside)
|
||||
{
|
||||
/* Only emit enter events for the first device */
|
||||
block_event = TRUE;
|
||||
}
|
||||
|
||||
if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER &&
|
||||
gdk_device_get_mode (device) != GDK_MODE_DISABLED &&
|
||||
!g_list_find (window->devices_inside, device))
|
||||
window->devices_inside = g_list_prepend (window->devices_inside, device);
|
||||
}
|
||||
|
||||
if (block_event)
|
||||
return;
|
||||
|
||||
if (window_event_mask & type_event_mask)
|
||||
{
|
||||
event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
|
||||
gdk_event_set_device (event, device);
|
||||
gdk_event_set_seat (event, gdk_device_get_seat (device));
|
||||
|
||||
if (source_device)
|
||||
gdk_event_set_source_device (event, source_device);
|
||||
|
||||
event->crossing.time = time_;
|
||||
event->crossing.subwindow = subwindow;
|
||||
if (subwindow)
|
||||
g_object_ref (subwindow);
|
||||
convert_toplevel_coords_to_window ((GdkWindow *)window,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->crossing.x, &event->crossing.y);
|
||||
event->crossing.x_root = toplevel_x + toplevel->x;
|
||||
event->crossing.y_root = toplevel_y + toplevel->y;
|
||||
event->crossing.mode = mode;
|
||||
event->crossing.detail = notify_type;
|
||||
event->crossing.focus = FALSE;
|
||||
event->crossing.state = mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The coordinates are in the toplevel window that src/dest are in.
|
||||
* src and dest are always (if != NULL) in the same toplevel, as
|
||||
* we get a leave-notify and set the window_under_pointer to null
|
||||
* before crossing to another toplevel.
|
||||
*/
|
||||
void
|
||||
_gdk_synthesize_crossing_events (GdkDisplay *display,
|
||||
GdkWindow *src,
|
||||
GdkWindow *dest,
|
||||
GdkDevice *device,
|
||||
GdkDevice *source_device,
|
||||
GdkCrossingMode mode,
|
||||
double toplevel_x,
|
||||
double toplevel_y,
|
||||
GdkModifierType mask,
|
||||
guint32 time_,
|
||||
GdkEvent *event_in_queue,
|
||||
gulong serial,
|
||||
gboolean non_linear)
|
||||
{
|
||||
GdkWindow *c;
|
||||
GdkWindow *win, *last, *next;
|
||||
GList *path, *list;
|
||||
GdkWindow *a;
|
||||
GdkWindow *b;
|
||||
GdkWindow *toplevel;
|
||||
GdkNotifyType notify_type;
|
||||
|
||||
/* TODO: Don't send events to toplevel, as we get those from the windowing system */
|
||||
|
||||
a = (src && GDK_IS_WINDOW (src)) ? src : NULL;
|
||||
b = (dest && GDK_IS_WINDOW (dest)) ? dest : NULL;
|
||||
|
||||
if (src == dest)
|
||||
return; /* No crossings generated between src and dest */
|
||||
|
||||
if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
|
||||
{
|
||||
if (a && gdk_window_get_device_events (src, device) == 0)
|
||||
a = NULL;
|
||||
|
||||
if (b && gdk_window_get_device_events (dest, device) == 0)
|
||||
b = NULL;
|
||||
}
|
||||
|
||||
if (!a && !b)
|
||||
return;
|
||||
|
||||
c = find_common_ancestor (a, b);
|
||||
|
||||
non_linear |= (c != a) && (c != b);
|
||||
|
||||
if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
|
||||
{
|
||||
toplevel = gdk_window_get_toplevel (a);
|
||||
|
||||
/* Traverse up from a to (excluding) c sending leave events */
|
||||
if (non_linear)
|
||||
notify_type = GDK_NOTIFY_NONLINEAR;
|
||||
else if (c == a)
|
||||
notify_type = GDK_NOTIFY_INFERIOR;
|
||||
else
|
||||
notify_type = GDK_NOTIFY_ANCESTOR;
|
||||
send_crossing_event (display, toplevel,
|
||||
a, GDK_LEAVE_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
NULL, device, source_device,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue,
|
||||
serial);
|
||||
|
||||
if (c != a)
|
||||
{
|
||||
if (non_linear)
|
||||
notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
|
||||
else
|
||||
notify_type = GDK_NOTIFY_VIRTUAL;
|
||||
|
||||
last = a;
|
||||
win = a->parent;
|
||||
while (win != c && win->window_type != GDK_WINDOW_ROOT)
|
||||
{
|
||||
send_crossing_event (display, toplevel,
|
||||
win, GDK_LEAVE_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
(GdkWindow *)last,
|
||||
device, source_device,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue,
|
||||
serial);
|
||||
|
||||
last = win;
|
||||
win = win->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (b) /* Might not be a dest, e.g. if we're moving out of the window */
|
||||
{
|
||||
toplevel = gdk_window_get_toplevel ((GdkWindow *)b);
|
||||
|
||||
/* Traverse down from c to b */
|
||||
if (c != b)
|
||||
{
|
||||
path = NULL;
|
||||
win = b->parent;
|
||||
while (win != c && win->window_type != GDK_WINDOW_ROOT)
|
||||
{
|
||||
path = g_list_prepend (path, win);
|
||||
win = win->parent;
|
||||
}
|
||||
|
||||
if (non_linear)
|
||||
notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
|
||||
else
|
||||
notify_type = GDK_NOTIFY_VIRTUAL;
|
||||
|
||||
list = path;
|
||||
while (list)
|
||||
{
|
||||
win = list->data;
|
||||
list = list->next;
|
||||
if (list)
|
||||
next = list->data;
|
||||
else
|
||||
next = b;
|
||||
|
||||
send_crossing_event (display, toplevel,
|
||||
win, GDK_ENTER_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
(GdkWindow *)next,
|
||||
device, source_device,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue,
|
||||
serial);
|
||||
}
|
||||
g_list_free (path);
|
||||
}
|
||||
|
||||
|
||||
if (non_linear)
|
||||
notify_type = GDK_NOTIFY_NONLINEAR;
|
||||
else if (c == a)
|
||||
notify_type = GDK_NOTIFY_ANCESTOR;
|
||||
else
|
||||
notify_type = GDK_NOTIFY_INFERIOR;
|
||||
|
||||
send_crossing_event (display, toplevel,
|
||||
b, GDK_ENTER_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
NULL,
|
||||
device, source_device,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue,
|
||||
serial);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_display_set_window_under_pointer (GdkDisplay *display,
|
||||
GdkDevice *device,
|
||||
|
Loading…
Reference in New Issue
Block a user