Wayland: ignore touch/tablet events on destroyed surfaces
When destroying a wl_surface (e.g. when a window or menu is closed), the surface may continue to exist in the compositor slightly longer than on the client side. In that case, the surface can still receive input events, which need to be ignored gracefully. In particular, this prevents segfaulting on wl_surface_get_user_data() in that situation. Reported in https://gitlab.gnome.org/GNOME/gtk/-/issues/3296 The same issue for pointers/keyboards was reported in https://bugzilla.gnome.org/show_bug.cgi?id=693338 and fixed with inbfd7137ffb3625f17857a8fc099a72
This commit is contained in:
@ -2460,6 +2460,9 @@ touch_handle_down (void *data,
|
|||||||
|
|
||||||
_gdk_wayland_display_update_serial (display, serial);
|
_gdk_wayland_display_update_serial (display, serial);
|
||||||
|
|
||||||
|
if (!wl_surface)
|
||||||
|
return;
|
||||||
|
|
||||||
touch = gdk_wayland_seat_add_touch (seat, id, wl_surface);
|
touch = gdk_wayland_seat_add_touch (seat, id, wl_surface);
|
||||||
touch->x = wl_fixed_to_double (x);
|
touch->x = wl_fixed_to_double (x);
|
||||||
touch->y = wl_fixed_to_double (y);
|
touch->y = wl_fixed_to_double (y);
|
||||||
@ -2495,6 +2498,9 @@ touch_handle_up (void *data,
|
|||||||
_gdk_wayland_display_update_serial (display, serial);
|
_gdk_wayland_display_update_serial (display, serial);
|
||||||
|
|
||||||
touch = gdk_wayland_seat_get_touch (seat, id);
|
touch = gdk_wayland_seat_get_touch (seat, id);
|
||||||
|
if (!touch)
|
||||||
|
return;
|
||||||
|
|
||||||
event = _create_touch_event (seat, touch, GDK_TOUCH_END, time);
|
event = _create_touch_event (seat, touch, GDK_TOUCH_END, time);
|
||||||
|
|
||||||
GDK_NOTE (EVENTS,
|
GDK_NOTE (EVENTS,
|
||||||
@ -2521,6 +2527,9 @@ touch_handle_motion (void *data,
|
|||||||
GdkEvent *event;
|
GdkEvent *event;
|
||||||
|
|
||||||
touch = gdk_wayland_seat_get_touch (seat, id);
|
touch = gdk_wayland_seat_get_touch (seat, id);
|
||||||
|
if (!touch)
|
||||||
|
return;
|
||||||
|
|
||||||
touch->x = wl_fixed_to_double (x);
|
touch->x = wl_fixed_to_double (x);
|
||||||
touch->y = wl_fixed_to_double (y);
|
touch->y = wl_fixed_to_double (y);
|
||||||
|
|
||||||
@ -3634,19 +3643,21 @@ tablet_tool_handle_proximity_in (void *data,
|
|||||||
struct zwp_tablet_tool_v2 *wp_tablet_tool,
|
struct zwp_tablet_tool_v2 *wp_tablet_tool,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
struct zwp_tablet_v2 *wp_tablet,
|
struct zwp_tablet_v2 *wp_tablet,
|
||||||
struct wl_surface *surface)
|
struct wl_surface *wl_surface)
|
||||||
{
|
{
|
||||||
GdkWaylandTabletToolData *tool = data;
|
GdkWaylandTabletToolData *tool = data;
|
||||||
GdkWaylandTabletData *tablet = zwp_tablet_v2_get_user_data (wp_tablet);
|
GdkWaylandTabletData *tablet = zwp_tablet_v2_get_user_data (wp_tablet);
|
||||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat);
|
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat);
|
||||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
|
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
|
||||||
GdkWindow *window = wl_surface_get_user_data (surface);
|
GdkWindow *window;
|
||||||
GdkEvent *event;
|
GdkEvent *event;
|
||||||
|
|
||||||
if (!surface)
|
if (!wl_surface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
window = wl_surface_get_user_data (wl_surface);
|
||||||
if (!GDK_IS_WINDOW (window))
|
if (!GDK_IS_WINDOW (window))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tool->current_tablet = tablet;
|
tool->current_tablet = tablet;
|
||||||
tablet->current_tool = tool;
|
tablet->current_tool = tool;
|
||||||
@ -3685,6 +3696,9 @@ tablet_tool_handle_proximity_out (void *data,
|
|||||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tool->seat);
|
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tool->seat);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
GDK_NOTE (EVENTS,
|
GDK_NOTE (EVENTS,
|
||||||
g_message ("proximity out, seat %p, tool %d", seat,
|
g_message ("proximity out, seat %p, tool %d", seat,
|
||||||
gdk_device_tool_get_tool_type (tool->tool)));
|
gdk_device_tool_get_tool_type (tool->tool)));
|
||||||
@ -3741,7 +3755,7 @@ tablet_tool_handle_down (void *data,
|
|||||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tool->seat);
|
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tool->seat);
|
||||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
|
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
|
||||||
|
|
||||||
if (!tablet->pointer_info.focus)
|
if (!tablet || !tablet->pointer_info.focus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_gdk_wayland_display_update_serial (display_wayland, serial);
|
_gdk_wayland_display_update_serial (display_wayland, serial);
|
||||||
@ -3758,7 +3772,7 @@ tablet_tool_handle_up (void *data,
|
|||||||
GdkWaylandTabletToolData *tool = data;
|
GdkWaylandTabletToolData *tool = data;
|
||||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||||
|
|
||||||
if (!tablet->pointer_info.focus)
|
if (!tablet || !tablet->pointer_info.focus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tablet_create_button_event_frame (tablet, GDK_BUTTON_RELEASE, GDK_BUTTON_PRIMARY);
|
tablet_create_button_event_frame (tablet, GDK_BUTTON_RELEASE, GDK_BUTTON_PRIMARY);
|
||||||
@ -3777,6 +3791,9 @@ tablet_tool_handle_motion (void *data,
|
|||||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display);
|
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display);
|
||||||
GdkEvent *event;
|
GdkEvent *event;
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
tablet->pointer_info.surface_x = wl_fixed_to_double (sx);
|
tablet->pointer_info.surface_x = wl_fixed_to_double (sx);
|
||||||
tablet->pointer_info.surface_y = wl_fixed_to_double (sy);
|
tablet->pointer_info.surface_y = wl_fixed_to_double (sy);
|
||||||
|
|
||||||
@ -3809,7 +3826,12 @@ tablet_tool_handle_pressure (void *data,
|
|||||||
{
|
{
|
||||||
GdkWaylandTabletToolData *tool = data;
|
GdkWaylandTabletToolData *tool = data;
|
||||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||||
gint axis_index = tablet->axis_indices[GDK_AXIS_PRESSURE];
|
gint axis_index;
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
axis_index = tablet->axis_indices[GDK_AXIS_PRESSURE];
|
||||||
|
|
||||||
_gdk_device_translate_axis (tablet->current_device, axis_index,
|
_gdk_device_translate_axis (tablet->current_device, axis_index,
|
||||||
pressure, &tablet->axes[axis_index]);
|
pressure, &tablet->axes[axis_index]);
|
||||||
@ -3826,7 +3848,12 @@ tablet_tool_handle_distance (void *data,
|
|||||||
{
|
{
|
||||||
GdkWaylandTabletToolData *tool = data;
|
GdkWaylandTabletToolData *tool = data;
|
||||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||||
gint axis_index = tablet->axis_indices[GDK_AXIS_DISTANCE];
|
gint axis_index;
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
axis_index = tablet->axis_indices[GDK_AXIS_DISTANCE];
|
||||||
|
|
||||||
_gdk_device_translate_axis (tablet->current_device, axis_index,
|
_gdk_device_translate_axis (tablet->current_device, axis_index,
|
||||||
distance, &tablet->axes[axis_index]);
|
distance, &tablet->axes[axis_index]);
|
||||||
@ -3844,8 +3871,14 @@ tablet_tool_handle_tilt (void *data,
|
|||||||
{
|
{
|
||||||
GdkWaylandTabletToolData *tool = data;
|
GdkWaylandTabletToolData *tool = data;
|
||||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||||
gint xtilt_axis_index = tablet->axis_indices[GDK_AXIS_XTILT];
|
gint xtilt_axis_index;
|
||||||
gint ytilt_axis_index = tablet->axis_indices[GDK_AXIS_YTILT];
|
gint ytilt_axis_index;
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
xtilt_axis_index = tablet->axis_indices[GDK_AXIS_XTILT];
|
||||||
|
ytilt_axis_index = tablet->axis_indices[GDK_AXIS_YTILT];
|
||||||
|
|
||||||
_gdk_device_translate_axis (tablet->current_device, xtilt_axis_index,
|
_gdk_device_translate_axis (tablet->current_device, xtilt_axis_index,
|
||||||
wl_fixed_to_double (xtilt),
|
wl_fixed_to_double (xtilt),
|
||||||
@ -3872,7 +3905,7 @@ tablet_tool_handle_button (void *data,
|
|||||||
GdkEventType evtype;
|
GdkEventType evtype;
|
||||||
guint n_button;
|
guint n_button;
|
||||||
|
|
||||||
if (!tablet->pointer_info.focus)
|
if (!tablet || !tablet->pointer_info.focus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tablet->pointer_info.press_serial = serial;
|
tablet->pointer_info.press_serial = serial;
|
||||||
@ -3903,7 +3936,12 @@ tablet_tool_handle_rotation (void *data,
|
|||||||
{
|
{
|
||||||
GdkWaylandTabletToolData *tool = data;
|
GdkWaylandTabletToolData *tool = data;
|
||||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||||
gint axis_index = tablet->axis_indices[GDK_AXIS_ROTATION];
|
gint axis_index;
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
axis_index = tablet->axis_indices[GDK_AXIS_ROTATION];
|
||||||
|
|
||||||
_gdk_device_translate_axis (tablet->current_device, axis_index,
|
_gdk_device_translate_axis (tablet->current_device, axis_index,
|
||||||
wl_fixed_to_double (degrees),
|
wl_fixed_to_double (degrees),
|
||||||
@ -3922,7 +3960,12 @@ tablet_tool_handle_slider (void *data,
|
|||||||
{
|
{
|
||||||
GdkWaylandTabletToolData *tool = data;
|
GdkWaylandTabletToolData *tool = data;
|
||||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||||
gint axis_index = tablet->axis_indices[GDK_AXIS_SLIDER];
|
gint axis_index;
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
axis_index = tablet->axis_indices[GDK_AXIS_SLIDER];
|
||||||
|
|
||||||
_gdk_device_translate_axis (tablet->current_device, axis_index,
|
_gdk_device_translate_axis (tablet->current_device, axis_index,
|
||||||
position, &tablet->axes[axis_index]);
|
position, &tablet->axes[axis_index]);
|
||||||
@ -3940,9 +3983,12 @@ tablet_tool_handle_wheel (void *data,
|
|||||||
{
|
{
|
||||||
GdkWaylandTabletToolData *tool = data;
|
GdkWaylandTabletToolData *tool = data;
|
||||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat);
|
GdkWaylandSeat *seat;
|
||||||
GdkEvent *event;
|
GdkEvent *event;
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
GDK_NOTE (EVENTS,
|
GDK_NOTE (EVENTS,
|
||||||
g_message ("tablet tool %d wheel %d/%d",
|
g_message ("tablet tool %d wheel %d/%d",
|
||||||
gdk_device_tool_get_tool_type (tool->tool), degrees, clicks));
|
gdk_device_tool_get_tool_type (tool->tool), degrees, clicks));
|
||||||
@ -3950,6 +3996,8 @@ tablet_tool_handle_wheel (void *data,
|
|||||||
if (clicks == 0)
|
if (clicks == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
seat = GDK_WAYLAND_SEAT (tablet->seat);
|
||||||
|
|
||||||
/* Send smooth event */
|
/* Send smooth event */
|
||||||
event = create_scroll_event (seat, &tablet->pointer_info,
|
event = create_scroll_event (seat, &tablet->pointer_info,
|
||||||
tablet->master, tablet->current_device, FALSE);
|
tablet->master, tablet->current_device, FALSE);
|
||||||
@ -3975,6 +4023,9 @@ tablet_tool_handle_frame (void *data,
|
|||||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||||
GdkEvent *frame_event;
|
GdkEvent *frame_event;
|
||||||
|
|
||||||
|
if (!tablet)
|
||||||
|
return;
|
||||||
|
|
||||||
GDK_NOTE (EVENTS,
|
GDK_NOTE (EVENTS,
|
||||||
g_message ("tablet frame, time %d", time));
|
g_message ("tablet frame, time %d", time));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user