gdkwindow: Drop csw-side event translation

Now that gtk_main_do_event() is able to handle pointing events in toplevel
coordinates, forward all of these as is. Just minimal handling is still done
on the gdk side for GDK grab accounting, and toplevel tracking for each
pointer.
This commit is contained in:
Carlos Garnacho 2017-03-31 17:46:35 +02:00
parent e25fcf983a
commit f57f48d61f

View File

@ -5518,31 +5518,6 @@ point_in_input_window (GdkWindow *window,
return FALSE;
}
static GdkWindow *
convert_native_coords_to_toplevel (GdkWindow *window,
gdouble child_x,
gdouble child_y,
gdouble *toplevel_x,
gdouble *toplevel_y)
{
gdouble x, y;
x = child_x;
y = child_y;
while (!gdk_window_is_toplevel (window))
{
x += window->x;
y += window->y;
window = window->parent;
}
*toplevel_x = x;
*toplevel_y = y;
return window;
}
static void
convert_toplevel_coords_to_window (GdkWindow *window,
gdouble toplevel_x,
@ -5798,63 +5773,6 @@ static const guint type_masks[] = {
G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
/* send motion events if the right buttons are down */
static guint
update_evmask_for_button_motion (guint evmask,
GdkModifierType mask)
{
if (evmask & GDK_BUTTON_MOTION_MASK &&
mask & (GDK_BUTTON1_MASK |
GDK_BUTTON2_MASK |
GDK_BUTTON3_MASK |
GDK_BUTTON4_MASK |
GDK_BUTTON5_MASK))
evmask |= GDK_POINTER_MOTION_MASK;
if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
(evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
(evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
evmask |= GDK_POINTER_MOTION_MASK;
return evmask;
}
static gboolean
is_button_type (GdkEventType type)
{
return type == GDK_BUTTON_PRESS ||
type == GDK_2BUTTON_PRESS ||
type == GDK_3BUTTON_PRESS ||
type == GDK_BUTTON_RELEASE ||
type == GDK_TOUCH_BEGIN ||
type == GDK_TOUCH_END ||
type == GDK_TOUCH_CANCEL ||
type == GDK_SCROLL;
}
static gboolean
is_gesture_type (GdkEventType type)
{
return (type == GDK_TOUCHPAD_SWIPE ||
type == GDK_TOUCHPAD_PINCH);
}
static gboolean
is_motion_type (GdkEventType type)
{
return type == GDK_MOTION_NOTIFY ||
type == GDK_TOUCH_UPDATE ||
type == GDK_ENTER_NOTIFY ||
type == GDK_LEAVE_NOTIFY;
}
static gboolean
is_touch_type (GdkEventType type)
{
return type == GDK_TOUCH_BEGIN ||
type == GDK_TOUCH_UPDATE ||
type == GDK_TOUCH_END ||
type == GDK_TOUCH_CANCEL;
}
static GdkWindow *
find_common_ancestor (GdkWindow *win1,
@ -6580,776 +6498,12 @@ _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
}
}
/* Don't use for crossing events */
static GdkWindow *
get_event_window (GdkDisplay *display,
GdkDevice *device,
GdkEventSequence *sequence,
GdkWindow *pointer_window,
GdkEventType type,
GdkModifierType mask,
guint *evmask_out,
gboolean pointer_emulated,
gulong serial)
{
guint evmask, emulated_mask = 0;
GdkWindow *grab_window;
GdkDeviceGrabInfo *grab;
GdkTouchGrabInfo *touch_grab;
touch_grab = _gdk_display_has_touch_grab (display, device, sequence, serial);
grab = _gdk_display_get_last_device_grab (display, device);
/* Default value. */
if (evmask_out)
*evmask_out = 0;
if (is_touch_type (type) && pointer_emulated)
{
switch (type)
{
case GDK_TOUCH_BEGIN:
emulated_mask |= GDK_BUTTON_PRESS_MASK;
break;
case GDK_TOUCH_UPDATE:
emulated_mask |= GDK_POINTER_MOTION_MASK;
break;
case GDK_TOUCH_END:
emulated_mask |= GDK_BUTTON_RELEASE_MASK;
default:
break;
}
}
if (touch_grab != NULL &&
(!grab || grab->implicit || touch_grab->serial >= grab->serial_start))
{
evmask = touch_grab->event_mask;
evmask = update_evmask_for_button_motion (evmask, mask);
if (evmask & (type_masks[type] | emulated_mask))
{
if (evmask_out)
*evmask_out = evmask;
return touch_grab->window;
}
else
return NULL;
}
if (grab != NULL && !grab->owner_events)
{
evmask = grab->event_mask;
evmask = update_evmask_for_button_motion (evmask, mask);
grab_window = grab->window;
if (evmask & (type_masks[type] | emulated_mask))
{
if (evmask_out)
*evmask_out = evmask;
return grab_window;
}
else
return NULL;
}
while (pointer_window != NULL)
{
evmask = pointer_window->event_mask;
evmask = update_evmask_for_button_motion (evmask, mask);
if (evmask & (type_masks[type] | emulated_mask))
{
if (evmask_out)
*evmask_out = evmask;
return pointer_window;
}
pointer_window = pointer_window->parent;
}
if (grab != NULL &&
grab->owner_events)
{
evmask = grab->event_mask;
evmask = update_evmask_for_button_motion (evmask, mask);
if (evmask & (type_masks[type] | emulated_mask))
{
if (evmask_out)
*evmask_out = evmask;
return grab->window;
}
else
return NULL;
}
return NULL;
}
static gboolean
proxy_pointer_event (GdkDisplay *display,
GdkEvent *source_event,
gulong serial)
{
GdkWindow *toplevel_window, *event_window;
GdkWindow *pointer_window;
GdkPointerWindowInfo *pointer_info;
GdkDevice *device, *source_device;
GdkEvent *event;
guint state;
gdouble toplevel_x, toplevel_y;
guint32 time_;
gboolean non_linear, need_synthetic_enter = FALSE;
gint event_type;
event_type = source_event->type;
event_window = source_event->any.window;
gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
gdk_event_get_state (source_event, &state);
time_ = gdk_event_get_time (source_event);
device = gdk_event_get_device (source_event);
source_device = gdk_event_get_source_device (source_event);
pointer_info = _gdk_display_get_pointer_info (display, device);
toplevel_window = convert_native_coords_to_toplevel (event_window,
toplevel_x, toplevel_y,
&toplevel_x, &toplevel_y);
non_linear = FALSE;
if ((source_event->type == GDK_LEAVE_NOTIFY ||
source_event->type == GDK_ENTER_NOTIFY) &&
(source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
non_linear = TRUE;
if (pointer_info->need_touch_press_enter &&
gdk_device_get_source (pointer_info->last_slave) != GDK_SOURCE_TOUCHSCREEN &&
(source_event->type != GDK_TOUCH_UPDATE ||
gdk_event_get_pointer_emulated (source_event)))
{
pointer_info->need_touch_press_enter = FALSE;
need_synthetic_enter = TRUE;
}
/* If we get crossing events with subwindow unexpectedly being NULL
that means there is a native subwindow that gdk doesn't know about.
We track these and forward them, with the correct virtual window
events inbetween.
This is important to get right, as metacity uses gdk for the frame
windows, but gdk doesn't know about the client windows reparented
into the frame. */
if (((source_event->type == GDK_LEAVE_NOTIFY &&
source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
(source_event->type == GDK_ENTER_NOTIFY &&
(source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
source_event->crossing.subwindow == NULL)
{
/* Left for an unknown (to gdk) subwindow */
/* Send leave events from window under pointer to event window
that will get the subwindow == NULL window */
_gdk_synthesize_crossing_events (display,
pointer_info->window_under_pointer,
event_window,
device, source_device,
source_event->crossing.mode,
toplevel_x, toplevel_y,
state, time_,
source_event,
serial,
non_linear);
/* Send subwindow == NULL event */
send_crossing_event (display,
toplevel_window,
event_window,
source_event->type,
source_event->crossing.mode,
source_event->crossing.detail,
NULL,
device, source_device,
toplevel_x, toplevel_y,
state, time_,
source_event,
serial);
_gdk_display_set_window_under_pointer (display, device, NULL);
return TRUE;
}
pointer_window = get_pointer_window (display, toplevel_window, device,
toplevel_x, toplevel_y, serial);
if (((source_event->type == GDK_ENTER_NOTIFY &&
source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
(source_event->type == GDK_LEAVE_NOTIFY &&
(source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
source_event->crossing.subwindow == NULL)
{
/* Entered from an unknown (to gdk) subwindow */
/* Send subwindow == NULL event */
send_crossing_event (display,
toplevel_window,
event_window,
source_event->type,
source_event->crossing.mode,
source_event->crossing.detail,
NULL,
device, source_device,
toplevel_x, toplevel_y,
state, time_,
source_event,
serial);
/* Send enter events from event window to pointer_window */
_gdk_synthesize_crossing_events (display,
event_window,
pointer_window,
device, source_device,
source_event->crossing.mode,
toplevel_x, toplevel_y,
state, time_,
source_event,
serial, non_linear);
_gdk_display_set_window_under_pointer (display, device, pointer_window);
return TRUE;
}
if ((source_event->type != GDK_TOUCH_UPDATE ||
gdk_event_get_pointer_emulated (source_event)) &&
pointer_info->window_under_pointer != pointer_window)
{
/* Either a toplevel crossing notify that ended up inside a child window,
or a motion notify that got into another child window */
/* Different than last time, send crossing events */
_gdk_synthesize_crossing_events (display,
pointer_info->window_under_pointer,
pointer_window,
device, source_device,
GDK_CROSSING_NORMAL,
toplevel_x, toplevel_y,
state, time_,
source_event,
serial, non_linear);
_gdk_display_set_window_under_pointer (display, device, pointer_window);
}
else if (source_event->type == GDK_MOTION_NOTIFY ||
source_event->type == GDK_TOUCH_UPDATE)
{
GdkWindow *event_win;
guint evmask;
gboolean is_hint;
GdkEventSequence *sequence;
sequence = gdk_event_get_event_sequence (source_event);
event_win = get_event_window (display,
device,
sequence,
pointer_window,
source_event->type,
state,
&evmask,
gdk_event_get_pointer_emulated (source_event),
serial);
if (event_type == GDK_TOUCH_UPDATE)
{
if (gdk_event_get_pointer_emulated (source_event))
{
/* Touch events emulating pointer events are transformed back
* to pointer events if:
* 1 - The event window doesn't select for touch events
* 2 - There's no touch grab for this sequence, which means
* it was started as a pointer sequence, but a device
* grab added touch events afterwards, the sequence must
* not mutate in this case.
*/
if ((evmask & GDK_TOUCH_MASK) == 0 ||
!_gdk_display_has_touch_grab (display, device, sequence, serial))
event_type = GDK_MOTION_NOTIFY;
}
else if ((evmask & GDK_TOUCH_MASK) == 0)
return TRUE;
}
if (is_touch_type (source_event->type) && !is_touch_type (event_type))
state |= GDK_BUTTON1_MASK;
if (event_win &&
gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
gdk_window_get_device_events (event_win, device) == 0)
return TRUE;
/* The last device to interact with the window was a touch device,
* which synthesized a leave notify event, so synthesize another enter
* notify to tell the pointer is on the window.
*/
if (need_synthetic_enter)
_gdk_synthesize_crossing_events (display,
NULL, pointer_window,
device, source_device,
GDK_CROSSING_DEVICE_SWITCH,
toplevel_x, toplevel_y,
state, time_, NULL,
serial, FALSE);
is_hint = FALSE;
if (event_win &&
event_type == GDK_MOTION_NOTIFY &&
(evmask & GDK_POINTER_MOTION_HINT_MASK))
{
gulong *device_serial;
device_serial = g_hash_table_lookup (display->motion_hint_info, device);
if (!device_serial ||
(*device_serial != 0 &&
serial < *device_serial))
event_win = NULL; /* Ignore event */
else
{
is_hint = TRUE;
*device_serial = G_MAXULONG;
}
}
if (!event_win)
return TRUE;
event = gdk_event_new (event_type);
event->any.window = g_object_ref (event_win);
event->any.send_event = source_event->any.send_event;
gdk_event_set_device (event, gdk_event_get_device (source_event));
gdk_event_set_source_device (event, source_device);
gdk_event_set_seat (event, gdk_device_get_seat (device));
gdk_event_set_device_tool (event, gdk_event_get_device_tool (source_event));
if (event_type == GDK_TOUCH_UPDATE)
{
event->touch.time = time_;
event->touch.state = state | GDK_BUTTON1_MASK;
event->touch.sequence = source_event->touch.sequence;
event->touch.emulating_pointer = source_event->touch.emulating_pointer;
convert_toplevel_coords_to_window (event_win,
toplevel_x, toplevel_y,
&event->touch.x, &event->touch.y);
gdk_event_get_root_coords (source_event,
&event->touch.x_root,
&event->touch.y_root);
event->touch.axes = g_memdup (source_event->touch.axes,
sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
}
else
{
event->motion.time = time_;
event->motion.state = state;
event->motion.is_hint = is_hint;
convert_toplevel_coords_to_window (event_win,
toplevel_x, toplevel_y,
&event->motion.x, &event->motion.y);
gdk_event_get_root_coords (source_event,
&event->motion.x_root,
&event->motion.y_root);
if (is_touch_type (source_event->type))
event->motion.axes = g_memdup (source_event->touch.axes,
sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
else
event->motion.axes = g_memdup (source_event->motion.axes,
sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
}
/* Just insert the event */
_gdk_event_queue_insert_after (gdk_window_get_display (event_win),
source_event, event);
}
/* unlink all move events from queue.
We handle our own, including our emulated masks. */
return TRUE;
}
#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
GDK_BUTTON2_MASK | \
GDK_BUTTON3_MASK | \
GDK_BUTTON4_MASK | \
GDK_BUTTON5_MASK)
static gboolean
proxy_button_event (GdkEvent *source_event,
gulong serial)
{
GdkWindow *toplevel_window, *event_window;
GdkWindow *event_win;
GdkWindow *pointer_window;
GdkWindow *parent;
GdkEvent *event;
GdkPointerWindowInfo *pointer_info;
GdkDeviceGrabInfo *pointer_grab;
guint state;
guint32 time_;
GdkEventType type;
gdouble toplevel_x, toplevel_y;
GdkDisplay *display;
GdkWindow *w;
GdkDevice *device, *source_device;
GdkEventMask evmask;
GdkEventSequence *sequence;
type = source_event->any.type;
event_window = source_event->any.window;
gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
gdk_event_get_state (source_event, &state);
time_ = gdk_event_get_time (source_event);
device = gdk_event_get_device (source_event);
source_device = gdk_event_get_source_device (source_event);
display = gdk_window_get_display (source_event->any.window);
toplevel_window = convert_native_coords_to_toplevel (event_window,
toplevel_x, toplevel_y,
&toplevel_x, &toplevel_y);
sequence = gdk_event_get_event_sequence (source_event);
pointer_info = _gdk_display_get_pointer_info (display, device);
pointer_grab = _gdk_display_has_device_grab (display, device, serial);
if ((type == GDK_BUTTON_PRESS ||
type == GDK_TOUCH_BEGIN) &&
!source_event->any.send_event &&
(!pointer_grab ||
(type == GDK_TOUCH_BEGIN && pointer_grab->implicit &&
!gdk_event_get_pointer_emulated (source_event))))
{
pointer_window =
_gdk_window_find_descendant_at (toplevel_window,
toplevel_x, toplevel_y,
NULL, NULL);
/* Find the event window, that gets the grab */
w = pointer_window;
while (w != NULL &&
(parent = w->parent) != NULL &&
parent->window_type != GDK_WINDOW_ROOT)
{
if (w->event_mask & GDK_BUTTON_PRESS_MASK &&
(type == GDK_BUTTON_PRESS ||
gdk_event_get_pointer_emulated (source_event)))
break;
if (type == GDK_TOUCH_BEGIN &&
w->event_mask & GDK_TOUCH_MASK)
break;
w = parent;
}
pointer_window = w;
if (pointer_window)
{
if (type == GDK_TOUCH_BEGIN &&
pointer_window->event_mask & GDK_TOUCH_MASK)
{
_gdk_display_add_touch_grab (display, device, sequence,
pointer_window, event_window,
gdk_window_get_events (pointer_window),
serial, time_);
}
else if (type == GDK_BUTTON_PRESS ||
gdk_event_get_pointer_emulated (source_event))
{
_gdk_display_add_device_grab (display,
device,
pointer_window,
event_window,
GDK_OWNERSHIP_NONE,
FALSE,
gdk_window_get_events (pointer_window),
serial,
time_,
TRUE);
_gdk_display_device_grab_update (display, device,
source_device, serial);
}
}
}
pointer_window = get_pointer_window (display, toplevel_window, device,
toplevel_x, toplevel_y,
serial);
event_win = get_event_window (display,
device,
sequence,
pointer_window,
type, state,
&evmask,
gdk_event_get_pointer_emulated (source_event),
serial);
if (type == GDK_TOUCH_BEGIN || type == GDK_TOUCH_END)
{
if (gdk_event_get_pointer_emulated (source_event))
{
if ((evmask & GDK_TOUCH_MASK) == 0 ||
!_gdk_display_has_touch_grab (display, device, sequence, serial))
{
if (type == GDK_TOUCH_BEGIN)
type = GDK_BUTTON_PRESS;
else if (type == GDK_TOUCH_END)
type = GDK_BUTTON_RELEASE;
}
}
else if ((evmask & GDK_TOUCH_MASK) == 0)
return TRUE;
}
if (source_event->type == GDK_TOUCH_END && !is_touch_type (type))
state |= GDK_BUTTON1_MASK;
if (event_win == NULL)
return TRUE;
if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
gdk_window_get_device_events (event_win, device) == 0)
return TRUE;
if ((type == GDK_BUTTON_PRESS ||
(type == GDK_TOUCH_BEGIN &&
gdk_event_get_pointer_emulated (source_event))) &&
pointer_info->need_touch_press_enter)
{
GdkCrossingMode mode;
/* The last device to interact with the window was a touch device,
* which synthesized a leave notify event, so synthesize another enter
* notify to tell the pointer is on the window.
*/
if (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
mode = GDK_CROSSING_TOUCH_BEGIN;
else
mode = GDK_CROSSING_DEVICE_SWITCH;
pointer_info->need_touch_press_enter = FALSE;
_gdk_synthesize_crossing_events (display,
NULL,
pointer_info->window_under_pointer,
device, source_device, mode,
toplevel_x, toplevel_y,
state, time_, source_event,
serial, FALSE);
}
else if (type == GDK_SCROLL &&
(((evmask & GDK_SMOOTH_SCROLL_MASK) == 0 &&
source_event->scroll.direction == GDK_SCROLL_SMOOTH) ||
((evmask & GDK_SMOOTH_SCROLL_MASK) != 0 &&
source_event->scroll.direction != GDK_SCROLL_SMOOTH &&
gdk_event_get_pointer_emulated (source_event))))
return FALSE;
event = _gdk_make_event (event_win, type, source_event, FALSE);
switch (type)
{
case GDK_BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
event->button.button = source_event->button.button;
convert_toplevel_coords_to_window (event_win,
toplevel_x, toplevel_y,
&event->button.x, &event->button.y);
gdk_event_get_root_coords (source_event,
&event->button.x_root,
&event->button.y_root);
gdk_event_set_device (event, gdk_event_get_device (source_event));
gdk_event_set_source_device (event, source_device);
gdk_event_set_seat (event, gdk_device_get_seat (device));
gdk_event_set_device_tool (event, gdk_event_get_device_tool (source_event));
if (is_touch_type (source_event->type))
{
if (type == GDK_BUTTON_RELEASE)
event->button.state |= GDK_BUTTON1_MASK;
event->button.button = 1;
event->button.axes = g_memdup (source_event->touch.axes,
sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
}
else
{
event->button.button = source_event->button.button;
event->button.axes = g_memdup (source_event->button.axes,
sizeof (gdouble) * gdk_device_get_n_axes (source_event->button.device));
}
if (type == GDK_BUTTON_PRESS)
_gdk_event_button_generate (display, event);
else if ((type == GDK_BUTTON_RELEASE ||
(type == GDK_TOUCH_END &&
gdk_event_get_pointer_emulated (source_event))) &&
pointer_window == pointer_info->window_under_pointer &&
gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
{
/* Synthesize a leave notify event
* whenever a touch device is released
*/
pointer_info->need_touch_press_enter = TRUE;
_gdk_synthesize_crossing_events (display,
pointer_window, NULL,
device, source_device,
GDK_CROSSING_TOUCH_END,
toplevel_x, toplevel_y,
state, time_, NULL,
serial, FALSE);
}
return TRUE;
case GDK_TOUCH_BEGIN:
case GDK_TOUCH_END:
case GDK_TOUCH_CANCEL:
convert_toplevel_coords_to_window (event_win,
toplevel_x, toplevel_y,
&event->button.x, &event->button.y);
gdk_event_get_root_coords (source_event,
&event->touch.x_root,
&event->touch.y_root);
event->touch.state = state;
event->touch.device = source_event->touch.device;
event->touch.axes = g_memdup (source_event->touch.axes,
sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
event->touch.sequence = source_event->touch.sequence;
event->touch.emulating_pointer = source_event->touch.emulating_pointer;
gdk_event_set_source_device (event, source_device);
if (((type == GDK_TOUCH_END || type == GDK_TOUCH_CANCEL) &&
gdk_event_get_pointer_emulated (source_event)) &&
pointer_window == pointer_info->window_under_pointer &&
gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
{
/* Synthesize a leave notify event
* whenever a touch device is released
*/
pointer_info->need_touch_press_enter = TRUE;
_gdk_synthesize_crossing_events (display,
pointer_window, NULL,
device, source_device,
GDK_CROSSING_TOUCH_END,
toplevel_x, toplevel_y,
state, time_, NULL,
serial, FALSE);
}
return TRUE;
case GDK_SCROLL:
event->scroll.direction = source_event->scroll.direction;
convert_toplevel_coords_to_window (event_win,
toplevel_x, toplevel_y,
&event->scroll.x, &event->scroll.y);
event->scroll.x_root = source_event->scroll.x_root;
event->scroll.y_root = source_event->scroll.y_root;
event->scroll.state = state;
event->scroll.device = source_event->scroll.device;
event->scroll.delta_x = source_event->scroll.delta_x;
event->scroll.delta_y = source_event->scroll.delta_y;
event->scroll.is_stop = source_event->scroll.is_stop;
gdk_event_set_source_device (event, source_device);
return TRUE;
default:
return FALSE;
}
return TRUE; /* Always unlink original, we want to obey the emulated event mask */
}
static gboolean
proxy_gesture_event (GdkEvent *source_event,
gulong serial)
{
GdkWindow *toplevel_window, *pointer_window, *event_win;
GdkDevice *device, *source_device;
gdouble toplevel_x, toplevel_y;
GdkDisplay *display;
GdkEventMask evmask;
GdkEventType evtype;
GdkEvent *event;
guint state;
evtype = source_event->any.type;
gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
gdk_event_get_state (source_event, &state);
device = gdk_event_get_device (source_event);
source_device = gdk_event_get_source_device (source_event);
display = gdk_window_get_display (source_event->any.window);
toplevel_window = convert_native_coords_to_toplevel (source_event->any.window,
toplevel_x, toplevel_y,
&toplevel_x, &toplevel_y);
pointer_window = get_pointer_window (display, toplevel_window, device,
toplevel_x, toplevel_y,
serial);
event_win = get_event_window (display, device, NULL,
pointer_window, evtype, state,
&evmask, FALSE, serial);
if (!event_win)
return TRUE;
if ((evmask & GDK_TOUCHPAD_GESTURE_MASK) == 0)
return TRUE;
event = _gdk_make_event (event_win, evtype, source_event, FALSE);
gdk_event_set_device (event, device);
gdk_event_set_source_device (event, source_device);
gdk_event_set_seat (event, gdk_device_get_seat (device));
switch (evtype)
{
case GDK_TOUCHPAD_SWIPE:
convert_toplevel_coords_to_window (event_win,
toplevel_x, toplevel_y,
&event->touchpad_swipe.x,
&event->touchpad_swipe.y);
gdk_event_get_root_coords (source_event,
&event->touchpad_swipe.x_root,
&event->touchpad_swipe.y_root);
event->touchpad_swipe.dx = source_event->touchpad_swipe.dx;
event->touchpad_swipe.dy = source_event->touchpad_swipe.dy;
event->touchpad_swipe.n_fingers = source_event->touchpad_swipe.n_fingers;
event->touchpad_swipe.phase = source_event->touchpad_swipe.phase;
break;
case GDK_TOUCHPAD_PINCH:
convert_toplevel_coords_to_window (event_win,
toplevel_x, toplevel_y,
&event->touchpad_pinch.x,
&event->touchpad_pinch.y);
gdk_event_get_root_coords (source_event,
&event->touchpad_pinch.x_root,
&event->touchpad_pinch.y_root);
event->touchpad_pinch.dx = source_event->touchpad_pinch.dx;
event->touchpad_pinch.dy = source_event->touchpad_pinch.dy;
event->touchpad_pinch.scale = source_event->touchpad_pinch.scale;
event->touchpad_pinch.angle_delta = source_event->touchpad_pinch.angle_delta;
event->touchpad_pinch.n_fingers = source_event->touchpad_pinch.n_fingers;
event->touchpad_pinch.phase = source_event->touchpad_pinch.phase;
break;
default:
break;
}
return TRUE;
}
#ifdef DEBUG_WINDOW_PRINTING
#ifdef GDK_WINDOWING_X11
@ -7435,12 +6589,10 @@ _gdk_windowing_got_event (GdkDisplay *display,
gulong serial)
{
GdkWindow *event_window;
gdouble x, y;
gboolean unlink_event = FALSE;
GdkDeviceGrabInfo *button_release_grab;
GdkPointerWindowInfo *pointer_info = NULL;
GdkDevice *device, *source_device;
gboolean is_toplevel;
_gdk_display_update_last_event (display, event);
@ -7494,110 +6646,13 @@ _gdk_windowing_got_event (GdkDisplay *display,
goto out;
}
if (!(event->type == GDK_TOUCH_CANCEL ||
is_button_type (event->type) ||
is_motion_type (event->type) ||
is_gesture_type (event->type)) ||
event_window->window_type == GDK_WINDOW_ROOT)
if (event_window->window_type == GDK_WINDOW_ROOT)
goto out;
is_toplevel = gdk_window_is_toplevel (event_window);
if ((event->type == GDK_ENTER_NOTIFY ||
event->type == GDK_LEAVE_NOTIFY) &&
(event->crossing.mode == GDK_CROSSING_GRAB ||
event->crossing.mode == GDK_CROSSING_UNGRAB) &&
(_gdk_display_has_device_grab (display, device, serial) ||
event->crossing.detail == GDK_NOTIFY_INFERIOR))
{
/* We synthesize all crossing events due to grabs ourselves,
* so we ignore the native ones caused by our native pointer_grab
* calls. Otherwise we would proxy these crossing event and cause
* multiple copies of crossing events for grabs.
*
* We do want to handle grabs from other clients though, as for
* instance alt-tab in metacity causes grabs like these and
* we want to handle those. Thus the has_pointer_grab check.
*
* Implicit grabs on child windows create some grabbing events
* that are sent before the button press. This means we can't
* detect these with the has_pointer_grab check (as the implicit
* grab is only noticed when we get button press event), so we
* detect these events by checking for INFERIOR enter or leave
* events. These should never be a problem to filter out.
*/
/* We ended up in this window after some (perhaps other clients)
* grab, so update the toplevel_under_window state
*/
if (pointer_info && is_toplevel &&
event->type == GDK_ENTER_NOTIFY &&
event->crossing.mode == GDK_CROSSING_UNGRAB)
{
if (pointer_info->toplevel_under_pointer)
g_object_unref (pointer_info->toplevel_under_pointer);
pointer_info->toplevel_under_pointer = g_object_ref (event_window);
}
unlink_event = TRUE;
goto out;
}
/* Track toplevel_under_pointer */
if (pointer_info && is_toplevel)
{
if (event->type == GDK_ENTER_NOTIFY &&
event->crossing.detail != GDK_NOTIFY_INFERIOR)
{
if (pointer_info->toplevel_under_pointer)
g_object_unref (pointer_info->toplevel_under_pointer);
pointer_info->toplevel_under_pointer = g_object_ref (event_window);
}
else if (event->type == GDK_LEAVE_NOTIFY &&
event->crossing.detail != GDK_NOTIFY_INFERIOR &&
pointer_info->toplevel_under_pointer == event_window)
{
if (pointer_info->toplevel_under_pointer)
g_object_unref (pointer_info->toplevel_under_pointer);
pointer_info->toplevel_under_pointer = NULL;
}
}
if (pointer_info &&
(!is_touch_type (event->type) ||
gdk_event_get_pointer_emulated (event)))
{
guint old_state, old_button;
/* Store last pointer window and position/state */
old_state = pointer_info->state;
old_button = pointer_info->button;
gdk_event_get_coords (event, &x, &y);
convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
pointer_info->toplevel_x = x;
pointer_info->toplevel_y = y;
gdk_event_get_state (event, &pointer_info->state);
if (event->type == GDK_BUTTON_PRESS ||
event->type == GDK_BUTTON_RELEASE)
pointer_info->button = event->button.button;
else if (event->type == GDK_TOUCH_BEGIN ||
event->type == GDK_TOUCH_END)
pointer_info->button = 1;
if (device &&
(pointer_info->state != old_state ||
pointer_info->button != old_button))
_gdk_display_enable_motion_hints (display, device);
}
if (is_motion_type (event->type))
unlink_event = proxy_pointer_event (display, event, serial);
else if (is_button_type (event->type))
unlink_event = proxy_button_event (event, serial);
else if (is_gesture_type (event->type))
unlink_event = proxy_gesture_event (event, serial);
if (event->type == GDK_ENTER_NOTIFY)
_gdk_display_set_window_under_pointer (display, device, event_window);
else if (event->type == GDK_LEAVE_NOTIFY)
_gdk_display_set_window_under_pointer (display, device, NULL);
if ((event->type == GDK_BUTTON_RELEASE ||
event->type == GDK_TOUCH_CANCEL ||