From 0c19ef6c2caa0686d924ab9e8377da4a787fccd5 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 24 Nov 2023 23:30:36 +0100 Subject: [PATCH 1/3] gdk/wayland: Improve recent serial lookup This function takes an event, so the place(s) that do not have one readily available can only pass NULL, so the serial lookup will only work for the pointer. Pass a device (plus optional sequence) to this function, as these places do at least have the corresponding GdkDevice at hand. Fixes serial lookups for DnD, for other devices than pointers (e.g. tablets, or touch). --- gdk/wayland/gdkdrag-wayland.c | 2 +- gdk/wayland/gdkprivate-wayland.h | 5 ++-- gdk/wayland/gdkseat-wayland.c | 50 +++++++++++++++++-------------- gdk/wayland/gdktoplevel-wayland.c | 4 ++- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/gdk/wayland/gdkdrag-wayland.c b/gdk/wayland/gdkdrag-wayland.c index d323ba6e38..a637b3abe5 100644 --- a/gdk/wayland/gdkdrag-wayland.c +++ b/gdk/wayland/gdkdrag-wayland.c @@ -397,7 +397,7 @@ _gdk_wayland_surface_drag_begin (GdkSurface *surface, drag_wayland->data_source, gdk_wayland_surface_get_wl_surface (surface), gdk_wayland_surface_get_wl_surface (drag_wayland->dnd_surface), - _gdk_wayland_seat_get_implicit_grab_serial (seat, NULL)); + _gdk_wayland_seat_get_implicit_grab_serial (seat, device, NULL)); cursor = gdk_drag_get_cursor (drag, gdk_drag_get_selected_action (drag)); gdk_drag_set_cursor (drag, cursor); diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 0860f118b4..d1da4dbf71 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -164,8 +164,9 @@ void _gdk_wayland_display_remove_seat (GdkWaylandDisplay *displa guint32 id); GdkKeymap *_gdk_wayland_device_get_keymap (GdkDevice *device); -uint32_t _gdk_wayland_seat_get_implicit_grab_serial(GdkSeat *seat, - GdkEvent *event); +uint32_t _gdk_wayland_seat_get_implicit_grab_serial (GdkSeat *seat, + GdkDevice *event, + GdkEventSequence *sequence); uint32_t _gdk_wayland_seat_get_last_implicit_grab_serial (GdkWaylandSeat *seat, GdkEventSequence **sequence); GdkSurface * gdk_wayland_device_get_focus (GdkDevice *device); diff --git a/gdk/wayland/gdkseat-wayland.c b/gdk/wayland/gdkseat-wayland.c index b284388f62..f44258a05b 100644 --- a/gdk/wayland/gdkseat-wayland.c +++ b/gdk/wayland/gdkseat-wayland.c @@ -4344,35 +4344,39 @@ _gdk_wayland_display_remove_seat (GdkWaylandDisplay *display_wayland, } uint32_t -_gdk_wayland_seat_get_implicit_grab_serial (GdkSeat *seat, - GdkEvent *event) +_gdk_wayland_seat_get_implicit_grab_serial (GdkSeat *seat, + GdkDevice *device, + GdkEventSequence *sequence) { - GdkEventSequence *sequence = NULL; - GdkWaylandTouchData *touch = NULL; - - if (event) - sequence = gdk_event_get_event_sequence (event); + GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); + GList *l; if (sequence) - touch = gdk_wayland_seat_get_touch (GDK_WAYLAND_SEAT (seat), - GDK_EVENT_SEQUENCE_TO_SLOT (sequence)); - - if (touch) - return touch->touch_down_serial; - - if (event) { - GdkDevice *source = gdk_event_get_device (event); - GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); - GList *l; + GdkWaylandTouchData *touch = NULL; - for (l = wayland_seat->tablets; l; l = l->next) - { - GdkWaylandTabletData *tablet = l->data; + touch = gdk_wayland_seat_get_touch (GDK_WAYLAND_SEAT (seat), + GDK_EVENT_SEQUENCE_TO_SLOT (sequence)); + if (touch) + return touch->touch_down_serial; + } + else if (device == wayland_seat->logical_touch) + { + GdkWaylandTouchData *touch; + GHashTableIter iter; - if (tablet->stylus_device == source) - return tablet->pointer_info.press_serial; - } + /* Pick the first sequence */ + g_hash_table_iter_init (&iter, wayland_seat->touches); + g_hash_table_iter_next (&iter, NULL, (gpointer *) &touch); + return touch->touch_down_serial; + } + + for (l = wayland_seat->tablets; l; l = l->next) + { + GdkWaylandTabletData *tablet = l->data; + + if (tablet->logical_device == device) + return tablet->pointer_info.press_serial; } return GDK_WAYLAND_SEAT (seat)->pointer_info.press_serial; diff --git a/gdk/wayland/gdktoplevel-wayland.c b/gdk/wayland/gdktoplevel-wayland.c index abbd01ece8..c3a0749d55 100644 --- a/gdk/wayland/gdktoplevel-wayland.c +++ b/gdk/wayland/gdktoplevel-wayland.c @@ -1904,7 +1904,9 @@ gdk_wayland_toplevel_show_window_menu (GdkToplevel *toplevel, wl_seat = gdk_wayland_seat_get_wl_seat (seat); gdk_event_get_position (event, &x, &y); - serial = _gdk_wayland_seat_get_implicit_grab_serial (seat, event); + serial = _gdk_wayland_seat_get_implicit_grab_serial (seat, + gdk_event_get_device (event), + gdk_event_get_event_sequence (event)); switch (display_wayland->shell_variant) { From 988b9de210a92f4326f4c9c4a8d010050b4fc003 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 24 Nov 2023 23:35:45 +0100 Subject: [PATCH 2/3] gdk/wayland: Pass surface-relative coordinates in DnD events Make this event behave like the other regular events, and emit coordinates based on native surfaces. Fixes DnD over popovers finding the correct coordinates. --- gdk/wayland/gdkseat-wayland.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/gdk/wayland/gdkseat-wayland.c b/gdk/wayland/gdkseat-wayland.c index f44258a05b..bad02169d6 100644 --- a/gdk/wayland/gdkseat-wayland.c +++ b/gdk/wayland/gdkseat-wayland.c @@ -345,7 +345,6 @@ data_device_enter (void *data, GdkWaylandSeat *seat = data; GdkSurface *dest_surface; GdkContentFormats *formats; - int origin_x, origin_y; GdkDevice *device; dest_surface = wl_surface_get_user_data (surface); @@ -392,12 +391,10 @@ data_device_enter (void *data, gdk_wayland_seat_discard_pending_offer (seat); - gdk_surface_get_origin (gdk_drop_get_surface (seat->drop), &origin_x, &origin_y); - gdk_drop_emit_enter_event (seat->drop, FALSE, - origin_x + seat->pointer_info.surface_x, - origin_y + seat->pointer_info.surface_y, + seat->pointer_info.surface_x, + seat->pointer_info.surface_y, GDK_CURRENT_TIME); } @@ -431,7 +428,6 @@ data_device_motion (void *data, wl_fixed_t y) { GdkWaylandSeat *seat = data; - int origin_x, origin_y; GDK_SEAT_DEBUG (seat, EVENTS, "data device motion, data_device = %p, time = %d, x = %f, y = %f", @@ -444,12 +440,10 @@ data_device_motion (void *data, seat->pointer_info.surface_x = wl_fixed_to_double (x); seat->pointer_info.surface_y = wl_fixed_to_double (y); - gdk_surface_get_origin (gdk_drop_get_surface (seat->drop), &origin_x, &origin_y); - gdk_drop_emit_motion_event (seat->drop, FALSE, - origin_x + seat->pointer_info.surface_x, - origin_y + seat->pointer_info.surface_y, + seat->pointer_info.surface_x, + seat->pointer_info.surface_y, time); } @@ -458,17 +452,14 @@ data_device_drop (void *data, struct wl_data_device *data_device) { GdkWaylandSeat *seat = data; - int origin_x, origin_y; GDK_SEAT_DEBUG (seat, EVENTS, "data device drop, data device %p", data_device); - gdk_surface_get_origin (gdk_drop_get_surface (seat->drop), &origin_x, &origin_y); - gdk_drop_emit_drop_event (seat->drop, FALSE, - origin_x + seat->pointer_info.surface_x, - origin_y + seat->pointer_info.surface_y, + seat->pointer_info.surface_x, + seat->pointer_info.surface_y, GDK_CURRENT_TIME); } From d78475372fa15bda4f5b18d9b3c91c6b81078986 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 24 Nov 2023 23:37:20 +0100 Subject: [PATCH 3/3] gtk: Obey GTK grabs on DnD events Make DnD events get directed to the right places (and most importantly, not to the wrong places) when happening over modal parts of the UI. Fixes DnD started from popovers being able to drop on their modal toplevel. --- gtk/gtkmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 1c5f27189b..ec252b7aa6 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1696,7 +1696,7 @@ gtk_main_do_event (GdkEvent *event) { GdkDrop *drop = gdk_dnd_event_get_drop (event); gtk_drop_begin_event (drop, gdk_event_get_event_type (event)); - gtk_propagate_event (target_widget, event); + gtk_propagate_event (grab_widget, event); gtk_drop_end_event (drop); } break;