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.
This commit is contained in:
parent
b619ab4d34
commit
06467d2e12
|
@ -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…
Reference in New Issue