mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-13 04:10:13 +00:00
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:
parent
e25fcf983a
commit
f57f48d61f
955
gdk/gdkwindow.c
955
gdk/gdkwindow.c
@ -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 ||
|
||||
|
Loading…
Reference in New Issue
Block a user