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.
master
emersion 6 years ago
parent b619ab4d34
commit 06467d2e12
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48

@ -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); 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 * Sets the current selection for the seat. NULL can be provided to clear it.
* there was any. * 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, void wlr_seat_set_selection(struct wlr_seat *seat,
struct wlr_data_source *source, uint32_t serial); struct wlr_data_source *source, uint32_t serial);

@ -36,7 +36,6 @@ struct wlr_gtk_primary_selection_device {
struct wl_list resources; // wl_resource_get_link struct wl_list resources; // wl_resource_get_link
struct wl_list offers; // 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_destroy;
struct wl_listener seat_focus_change; struct wl_listener seat_focus_change;

@ -48,7 +48,13 @@ void wlr_primary_selection_source_send(
struct wlr_primary_selection_source *source, const char *mime_type, struct wlr_primary_selection_source *source, const char *mime_type,
int fd); 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, 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 #endif

@ -200,6 +200,7 @@ struct wlr_seat {
uint32_t selection_serial; uint32_t selection_serial;
struct wlr_primary_selection_source *primary_selection_source; struct wlr_primary_selection_source *primary_selection_source;
uint32_t primary_selection_serial;
// `drag` goes away before `drag_source`, when the implicit grab ends // `drag` goes away before `drag_source`, when the implicit grab ends
struct wlr_drag *drag; struct wlr_drag *drag;

@ -163,7 +163,8 @@ void wlr_seat_destroy(struct wlr_seat *seat) {
seat->selection_source = NULL; 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; struct wlr_seat_client *client, *tmp;
wl_list_for_each_safe(client, tmp, &seat->clients, link) { wl_list_for_each_safe(client, tmp, &seat->clients, link) {

@ -208,16 +208,7 @@ static void device_handle_set_selection(struct wl_client *client,
source = &client_source->source; source = &client_source->source;
} }
// TODO: improve serial validation wlr_seat_set_primary_selection(device->seat, source, serial);
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);
} }
static void device_handle_destroy(struct wl_client *client, static void device_handle_destroy(struct wl_client *client,

@ -1,6 +1,7 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_primary_selection.h>
#include <wlr/util/log.h>
#include "util/signal.h" #include "util/signal.h"
void wlr_primary_selection_source_init( 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, 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) { if (seat->primary_selection_source != NULL) {
wl_list_remove(&seat->primary_selection_source_destroy.link); wl_list_remove(&seat->primary_selection_source_destroy.link);
wlr_primary_selection_source_destroy(seat->primary_selection_source); 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_source = source;
seat->primary_selection_serial = serial;
if (source != NULL) { if (source != NULL) {
seat->primary_selection_source_destroy.notify = seat->primary_selection_source_destroy.notify =
seat_handle_primary_selection_source_destroy; seat_handle_primary_selection_source_destroy;

@ -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, bool ok = source_get_targets(selection, &source->base.mime_types,
&source->mime_types_atoms); &source->mime_types_atoms);
if (ok) { 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 { } else {
wlr_primary_selection_source_destroy(&source->base); 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, wlr_seat_set_selection(xwm->seat, NULL,
wl_display_next_serial(xwm->xwayland->wl_display)); wl_display_next_serial(xwm->xwayland->wl_display));
} else if (selection == &xwm->primary_selection) { } 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) { } else if (selection == &xwm->dnd_selection) {
// TODO: DND // TODO: DND
} else { } else {

@ -231,7 +231,8 @@ void xwm_selection_finish(struct wlr_xwm *xwm) {
if (xwm->seat->primary_selection_source && if (xwm->seat->primary_selection_source &&
primary_selection_source_is_xwayland( primary_selection_source_is_xwayland(
xwm->seat->primary_selection_source)) { 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); wlr_xwayland_set_seat(xwm->xwayland, NULL);
} }

Loading…
Cancel
Save