Skip to content

Commit

Permalink
data-device: fix dnd handling during popup interactions
Browse files Browse the repository at this point in the history
When a popup appears during dnd operations in wlroots-based
compositors, several issues occur:
1.Drag data is lost
2.Keyboard focus changes unexpectedly
3.Other windows cannot receive drag enter events
4.Event propagation is interrupted

Forwarding pointer/keyboard events from popup grab to drag grab when
drag is active, preventing data loss and maintaining proper event
propagation during popup interactions.
  • Loading branch information
Dami-star authored and justforlxz committed Dec 20, 2024
1 parent 41347e1 commit ddd7225
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 0 deletions.
148 changes: 148 additions & 0 deletions debian/patches/fix-dnd-handling-during-popup-interactions.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
Author: Lu YaNing <[email protected]>
Date: Fir Dec 20 10:05:24 2024 +0800
Subject: data-device: fix dnd handling during popup interactions

When a popup appears during dnd operations in wlroots-based
compositors, several issues occur:
1.Drag data is lost
2.Keyboard focus changes unexpectedly
3.Other windows cannot receive drag enter events
4.Event propagation is interrupted

Forwarding pointer/keyboard events from popup grab to drag grab when
drag is active, preventing data loss and maintaining proper event
propagation during popup interactions.
Upstream: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4943

--- wlroots-0.18.1.orig/types/seat/wlr_seat_pointer.c
+++ wlroots-0.18.1/types/seat/wlr_seat_pointer.c
@@ -4,6 +4,7 @@
#include <time.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_compositor.h>
+#include <wlr/types/wlr_data_device.h>
#include <wlr/util/log.h>
#include "types/wlr_seat.h"
#include "util/set.h"
@@ -417,6 +418,11 @@ void wlr_seat_pointer_start_grab(struct
grab->seat = wlr_seat;
wlr_seat->pointer_state.grab = grab;

+ // Preserve drag grab priority
+ if (wlr_seat->drag && grab != &wlr_seat->drag->pointer_grab) {
+ return;
+ }
+
wl_signal_emit_mutable(&wlr_seat->events.pointer_grab_begin, grab);
}

--- wlroots-0.18.1.orig/types/xdg_shell/wlr_xdg_popup.c
+++ wlroots-0.18.1/types/xdg_shell/wlr_xdg_popup.c
@@ -1,6 +1,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <wlr/types/wlr_data_device.h>
#include "types/wlr_xdg_shell.h"

void handle_xdg_popup_ack_configure(
@@ -52,6 +53,18 @@ static void xdg_popup_grab_end(struct wl
static void xdg_pointer_grab_enter(struct wlr_seat_pointer_grab *grab,
struct wlr_surface *surface, double sx, double sy) {
struct wlr_xdg_popup_grab *popup_grab = grab->data;
+ struct wlr_seat *seat = grab->seat;
+
+ // Forward to drag grab if active
+ if (seat->drag && seat->drag->pointer_grab.interface &&
+ seat->drag->pointer_grab.interface->enter) {
+ if (grab != &seat->drag->pointer_grab) {
+ seat->drag->pointer_grab.interface->enter(&seat->drag->pointer_grab,
+ surface, sx, sy);
+ }
+ return;
+ }
+
if (wl_resource_get_client(surface->resource) == popup_grab->client) {
wlr_seat_pointer_enter(grab->seat, surface, sx, sy);
} else {
@@ -65,13 +78,33 @@ static void xdg_pointer_grab_clear_focus

static void xdg_pointer_grab_motion(struct wlr_seat_pointer_grab *grab,
uint32_t time, double sx, double sy) {
+ struct wlr_seat *seat = grab->seat;
+
+ if (seat->drag && seat->drag->pointer_grab.interface &&
+ seat->drag->pointer_grab.interface->motion) {
+ if (grab != &seat->drag->pointer_grab) {
+ seat->drag->pointer_grab.interface->motion(&seat->drag->pointer_grab,
+ time, sx, sy);
+ }
+ return;
+ }
+
wlr_seat_pointer_send_motion(grab->seat, time, sx, sy);
}

static uint32_t xdg_pointer_grab_button(struct wlr_seat_pointer_grab *grab,
uint32_t time, uint32_t button, uint32_t state) {
- uint32_t serial =
- wlr_seat_pointer_send_button(grab->seat, time, button, state);
+ struct wlr_seat *seat = grab->seat;
+
+ if (seat->drag && seat->drag->pointer_grab.interface &&
+ seat->drag->pointer_grab.interface->button) {
+ if (grab != &seat->drag->pointer_grab) {
+ return seat->drag->pointer_grab.interface->button(&seat->drag->pointer_grab,
+ time, button, state);
+ }
+ }
+
+ uint32_t serial = wlr_seat_pointer_send_button(grab->seat, time, button, state);
if (serial) {
return serial;
} else {
@@ -84,11 +117,32 @@ static void xdg_pointer_grab_axis(struct
uint32_t time, enum wl_pointer_axis orientation, double value,
int32_t value_discrete, enum wl_pointer_axis_source source,
enum wl_pointer_axis_relative_direction relative_direction) {
+ struct wlr_seat *seat = grab->seat;
+
+ if (seat->drag && seat->drag->pointer_grab.interface &&
+ seat->drag->pointer_grab.interface->axis) {
+ if (grab != &seat->drag->pointer_grab) {
+ seat->drag->pointer_grab.interface->axis(&seat->drag->pointer_grab,
+ time, orientation, value, value_discrete, source, relative_direction);
+ }
+ return;
+ }
+
wlr_seat_pointer_send_axis(grab->seat, time, orientation, value,
value_discrete, source, relative_direction);
}

static void xdg_pointer_grab_frame(struct wlr_seat_pointer_grab *grab) {
+ struct wlr_seat *seat = grab->seat;
+
+ if (seat->drag && seat->drag->pointer_grab.interface &&
+ seat->drag->pointer_grab.interface->frame) {
+ if (grab != &seat->drag->pointer_grab) {
+ seat->drag->pointer_grab.interface->frame(&seat->drag->pointer_grab);
+ }
+ return;
+ }
+
wlr_seat_pointer_send_frame(grab->seat);
}

@@ -110,6 +164,11 @@ static void xdg_keyboard_grab_enter(stru
struct wlr_surface *surface, const uint32_t keycodes[], size_t num_keycodes,
const struct wlr_keyboard_modifiers *modifiers) {
// keyboard focus should remain on the popup
+ if (grab->seat->drag) {
+ return;
+ }
+
+ wlr_seat_keyboard_enter(grab->seat, surface, keycodes, num_keycodes, modifiers);
}

static void xdg_keyboard_grab_clear_focus(struct wlr_seat_keyboard_grab *grab) {
1 change: 1 addition & 0 deletions debian/patches/series
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Revert-layer-shell-error-on-0-dimension-without-anchors.patch
fix-dnd-handling-during-popup-interactions.patch

0 comments on commit ddd7225

Please sign in to comment.