aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremersion <contact@emersion.fr>2019-01-21 19:23:40 +0100
committeremersion <contact@emersion.fr>2019-01-21 19:23:40 +0100
commit06467d2e1233d8c2830500ca399bcce8dd37a91b (patch)
treec4b168bd7876879cb53bde307697561db0b139db
parentb619ab4d34b9bbcae7fbfdf87e84a9567acefa6b (diff)
primary-selection: add a serial argument
The serial needs to be bumped when X11 clients set the selection, otherwise some Wayland clients (e.g. GTK) will overwrite it when they gain focus.
-rw-r--r--include/wlr/types/wlr_data_device.h6
-rw-r--r--include/wlr/types/wlr_gtk_primary_selection.h1
-rw-r--r--include/wlr/types/wlr_primary_selection.h8
-rw-r--r--include/wlr/types/wlr_seat.h1
-rw-r--r--types/seat/wlr_seat.c3
-rw-r--r--types/wlr_gtk_primary_selection.c11
-rw-r--r--types/wlr_primary_selection.c12
-rw-r--r--xwayland/selection/incoming.c6
-rw-r--r--xwayland/selection/selection.c3
9 files changed, 32 insertions, 19 deletions
diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h
index 9c4ce995..209d917d 100644
--- a/include/wlr/types/wlr_data_device.h
+++ b/include/wlr/types/wlr_data_device.h
@@ -166,8 +166,10 @@ void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager);
void wlr_seat_client_send_selection(struct wlr_seat_client *seat_client);
/**
- * Sets the current selection for the seat. This removes the previous one if
- * there was any.
+ * Sets the current selection for the seat. NULL can be provided to clear it.
+ * This removes the previous one if there was any. In case the selection doesn't
+ * come from a client, wl_display_next_serial() can be used to generate a
+ * serial.
*/
void wlr_seat_set_selection(struct wlr_seat *seat,
struct wlr_data_source *source, uint32_t serial);
diff --git a/include/wlr/types/wlr_gtk_primary_selection.h b/include/wlr/types/wlr_gtk_primary_selection.h
index 436a50d2..7cf34201 100644
--- a/include/wlr/types/wlr_gtk_primary_selection.h
+++ b/include/wlr/types/wlr_gtk_primary_selection.h
@@ -36,7 +36,6 @@ struct wlr_gtk_primary_selection_device {
struct wl_list resources; // wl_resource_get_link
struct wl_list offers; // wl_resource_get_link
- uint32_t selection_serial;
struct wl_listener seat_destroy;
struct wl_listener seat_focus_change;
diff --git a/include/wlr/types/wlr_primary_selection.h b/include/wlr/types/wlr_primary_selection.h
index 9be61acc..a2b23574 100644
--- a/include/wlr/types/wlr_primary_selection.h
+++ b/include/wlr/types/wlr_primary_selection.h
@@ -48,7 +48,13 @@ void wlr_primary_selection_source_send(
struct wlr_primary_selection_source *source, const char *mime_type,
int fd);
+/**
+ * Sets the current primary selection for the seat. NULL can be provided to
+ * clear it. This removes the previous one if there was any. In case the
+ * selection doesn't come from a client, wl_display_next_serial() can be used to
+ * generate a serial.
+ */
void wlr_seat_set_primary_selection(struct wlr_seat *seat,
- struct wlr_primary_selection_source *source);
+ struct wlr_primary_selection_source *source, uint32_t serial);
#endif
diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h
index 942a3420..1ad5542e 100644
--- a/include/wlr/types/wlr_seat.h
+++ b/include/wlr/types/wlr_seat.h
@@ -200,6 +200,7 @@ struct wlr_seat {
uint32_t selection_serial;
struct wlr_primary_selection_source *primary_selection_source;
+ uint32_t primary_selection_serial;
// `drag` goes away before `drag_source`, when the implicit grab ends
struct wlr_drag *drag;
diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c
index 8b1d67fd..67ffd38a 100644
--- a/types/seat/wlr_seat.c
+++ b/types/seat/wlr_seat.c
@@ -163,7 +163,8 @@ void wlr_seat_destroy(struct wlr_seat *seat) {
seat->selection_source = NULL;
}
- wlr_seat_set_primary_selection(seat, NULL);
+ wlr_seat_set_primary_selection(seat, NULL,
+ wl_display_next_serial(seat->display));
struct wlr_seat_client *client, *tmp;
wl_list_for_each_safe(client, tmp, &seat->clients, link) {
diff --git a/types/wlr_gtk_primary_selection.c b/types/wlr_gtk_primary_selection.c
index 18bc624a..91b192cd 100644
--- a/types/wlr_gtk_primary_selection.c
+++ b/types/wlr_gtk_primary_selection.c
@@ -208,16 +208,7 @@ static void device_handle_set_selection(struct wl_client *client,
source = &client_source->source;
}
- // TODO: improve serial validation
- if (device->seat->primary_selection_source != NULL &&
- device->selection_serial - serial < UINT32_MAX / 2) {
- wlr_log(WLR_DEBUG, "Rejecting set_selection request, invalid serial "
- "(%"PRIu32" <= %"PRIu32")", serial, device->selection_serial);
- return;
- }
- device->selection_serial = serial;
-
- wlr_seat_set_primary_selection(device->seat, source);
+ wlr_seat_set_primary_selection(device->seat, source, serial);
}
static void device_handle_destroy(struct wl_client *client,
diff --git a/types/wlr_primary_selection.c b/types/wlr_primary_selection.c
index 921f44ee..be8b014d 100644
--- a/types/wlr_primary_selection.c
+++ b/types/wlr_primary_selection.c
@@ -1,6 +1,7 @@
#include <assert.h>
#include <stdlib.h>
#include <wlr/types/wlr_primary_selection.h>
+#include <wlr/util/log.h>
#include "util/signal.h"
void wlr_primary_selection_source_init(
@@ -50,7 +51,14 @@ static void seat_handle_primary_selection_source_destroy(
}
void wlr_seat_set_primary_selection(struct wlr_seat *seat,
- struct wlr_primary_selection_source *source) {
+ struct wlr_primary_selection_source *source, uint32_t serial) {
+ if (seat->primary_selection_source != NULL &&
+ seat->primary_selection_serial - serial < UINT32_MAX / 2) {
+ wlr_log(WLR_DEBUG, "Rejecting set_selection request, invalid serial "
+ "(%"PRIu32" <= %"PRIu32")", serial, seat->primary_selection_serial);
+ return;
+ }
+
if (seat->primary_selection_source != NULL) {
wl_list_remove(&seat->primary_selection_source_destroy.link);
wlr_primary_selection_source_destroy(seat->primary_selection_source);
@@ -58,6 +66,8 @@ void wlr_seat_set_primary_selection(struct wlr_seat *seat,
}
seat->primary_selection_source = source;
+ seat->primary_selection_serial = serial;
+
if (source != NULL) {
seat->primary_selection_source_destroy.notify =
seat_handle_primary_selection_source_destroy;
diff --git a/xwayland/selection/incoming.c b/xwayland/selection/incoming.c
index 3e97ca04..79197e60 100644
--- a/xwayland/selection/incoming.c
+++ b/xwayland/selection/incoming.c
@@ -370,7 +370,8 @@ static void xwm_selection_get_targets(struct wlr_xwm_selection *selection) {
bool ok = source_get_targets(selection, &source->base.mime_types,
&source->mime_types_atoms);
if (ok) {
- wlr_seat_set_primary_selection(xwm->seat, &source->base);
+ wlr_seat_set_primary_selection(xwm->seat, &source->base,
+ wl_display_next_serial(xwm->xwayland->wl_display));
} else {
wlr_primary_selection_source_destroy(&source->base);
}
@@ -427,7 +428,8 @@ int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
wlr_seat_set_selection(xwm->seat, NULL,
wl_display_next_serial(xwm->xwayland->wl_display));
} else if (selection == &xwm->primary_selection) {
- wlr_seat_set_primary_selection(xwm->seat, NULL);
+ wlr_seat_set_primary_selection(xwm->seat, NULL,
+ wl_display_next_serial(xwm->xwayland->wl_display));
} else if (selection == &xwm->dnd_selection) {
// TODO: DND
} else {
diff --git a/xwayland/selection/selection.c b/xwayland/selection/selection.c
index 4d7732cb..dee7f9c3 100644
--- a/xwayland/selection/selection.c
+++ b/xwayland/selection/selection.c
@@ -231,7 +231,8 @@ void xwm_selection_finish(struct wlr_xwm *xwm) {
if (xwm->seat->primary_selection_source &&
primary_selection_source_is_xwayland(
xwm->seat->primary_selection_source)) {
- wlr_seat_set_primary_selection(xwm->seat, NULL);
+ wlr_seat_set_primary_selection(xwm->seat, NULL,
+ wl_display_next_serial(xwm->xwayland->wl_display));
}
wlr_xwayland_set_seat(xwm->xwayland, NULL);
}