summaryrefslogtreecommitdiff
path: root/xwayland
diff options
context:
space:
mode:
authorDerek Foreman <derek.foreman@collabora.com>2022-08-12 10:55:01 -0500
committerMarius Vlad <marius.vlad@collabora.com>2022-12-07 10:03:37 +0200
commita04fd9921276e435487436f1f535fbdc8b5b9c82 (patch)
treecb6a93c347965554a44b807c208a1f6f9288f5e0 /xwayland
parent73449705525788dee80363e9812168bbb7232452 (diff)
downloadweston-a04fd9921276e435487436f1f535fbdc8b5b9c82.tar.gz
xwm: Fix selection if no seat present at startup
It's possible that there are no seats present at startup (especially with the RDP backend, which creates and removes seats for connections), and previously we'd just fail to set up XWayland cut and paste properly. We should set up a listener and find a seat when one becomes available - but we also need to switch seats if ours is removed. Signed-off-by: Derek Foreman <derek.foreman@collabora.com> Co-authored-by: Hideyuki Nagase <hideyukn@microsoft.com>
Diffstat (limited to 'xwayland')
-rw-r--r--xwayland/selection.c71
-rw-r--r--xwayland/window-manager.c2
-rw-r--r--xwayland/xwayland.h2
3 files changed, 68 insertions, 7 deletions
diff --git a/xwayland/selection.c b/xwayland/selection.c
index 0e4120ac..463a738c 100644
--- a/xwayland/selection.c
+++ b/xwayland/selection.c
@@ -716,13 +716,61 @@ weston_wm_set_selection(struct wl_listener *listener, void *data)
XCB_TIME_CURRENT_TIME);
}
+static void
+maybe_reassign_selection_seat(struct weston_wm *wm)
+{
+ struct weston_seat *seat;
+
+ /* If we already have a seat, keep it */
+ if (!wl_list_empty(&wm->selection_listener.link))
+ return;
+
+ seat = weston_wm_pick_seat(wm);
+ if (!seat)
+ return;
+
+ wl_list_remove(&wm->selection_listener.link);
+ wl_list_remove(&wm->seat_destroy_listener.link);
+
+ wl_signal_add(&seat->selection_signal, &wm->selection_listener);
+ wl_signal_add(&seat->destroy_signal, &wm->seat_destroy_listener);
+
+ weston_wm_set_selection(&wm->selection_listener, seat);
+}
+
+static void
+weston_wm_seat_created(struct wl_listener *listener, void *data)
+{
+ struct weston_wm *wm =
+ container_of(listener, struct weston_wm, seat_create_listener);
+
+ maybe_reassign_selection_seat(wm);
+}
+
+static void
+weston_wm_seat_destroyed(struct wl_listener *listener, void *data)
+{
+ struct weston_wm *wm =
+ container_of(listener, struct weston_wm, seat_destroy_listener);
+
+ wl_list_remove(&wm->selection_listener.link);
+ wl_list_init(&wm->selection_listener.link);
+
+ wl_list_remove(&wm->seat_destroy_listener.link);
+ wl_list_init(&wm->seat_destroy_listener.link);
+
+ /* Try to pick another available seat to fall back to */
+ maybe_reassign_selection_seat(wm);
+}
+
void
weston_wm_selection_init(struct weston_wm *wm)
{
- struct weston_seat *seat;
uint32_t values[1], mask;
wl_list_init(&wm->selection_listener.link);
+ wl_list_init(&wm->seat_create_listener.link);
+ wl_list_init(&wm->seat_destroy_listener.link);
wm->selection_request.requestor = XCB_NONE;
@@ -751,11 +799,20 @@ weston_wm_selection_init(struct weston_wm *wm)
xcb_xfixes_select_selection_input(wm->conn, wm->selection_window,
wm->atom.clipboard, mask);
- seat = weston_wm_pick_seat(wm);
- if (seat == NULL)
- return;
+ /* Try to set up a selection listener for any existing seat - we
+ * have a clipboard manager that can copy a subset of available
+ * selections so they don't disappear when the client owning
+ * them quits, but to make this work we need to have a seat
+ * to hang the selection off.
+ *
+ * If we have no seat or lose our seat we need to make sure we
+ * eventually assign a new one, so we listen for seat creation
+ * and destruction.
+ */
wm->selection_listener.notify = weston_wm_set_selection;
- wl_signal_add(&seat->selection_signal, &wm->selection_listener);
-
- weston_wm_set_selection(&wm->selection_listener, seat);
+ wm->seat_destroy_listener.notify = weston_wm_seat_destroyed;
+ wm->seat_create_listener.notify = weston_wm_seat_created;
+ wl_signal_add(&wm->server->compositor->seat_created_signal,
+ &wm->seat_create_listener);
+ maybe_reassign_selection_seat(wm);
}
diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
index 9dc30e1c..d90e84b7 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -2728,6 +2728,8 @@ weston_wm_destroy(struct weston_wm *wm)
theme_destroy(wm->theme);
xcb_disconnect(wm->conn);
wl_event_source_remove(wm->source);
+ wl_list_remove(&wm->seat_create_listener.link);
+ wl_list_remove(&wm->seat_destroy_listener.link);
wl_list_remove(&wm->selection_listener.link);
wl_list_remove(&wm->activate_listener.link);
wl_list_remove(&wm->kill_listener.link);
diff --git a/xwayland/xwayland.h b/xwayland/xwayland.h
index df9cab83..5b75ff8e 100644
--- a/xwayland/xwayland.h
+++ b/xwayland/xwayland.h
@@ -88,6 +88,8 @@ struct weston_wm {
int selection_property_set;
int flush_property_on_delete;
struct wl_listener selection_listener;
+ struct wl_listener seat_create_listener;
+ struct wl_listener seat_destroy_listener;
xcb_window_t dnd_window;
xcb_window_t dnd_owner;