mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-07-31 04:28:56 +00:00
wayland: Clear references to the clipboard when setting new data
Ensure that references to the clipboard being held by other seats are cleared when new data is being set, or some seats may hold references to invalid data and callbacks.
This commit is contained in:
@@ -39,9 +39,26 @@ bool Wayland_SetClipboardData(SDL_VideoDevice *_this)
|
||||
seat = wl_container_of(video_data->seat_list.next, seat, link);
|
||||
}
|
||||
|
||||
video_data->last_incoming_data_offer_seat = seat;
|
||||
video_data->current_data_offer_seat = seat;
|
||||
|
||||
if (seat && seat->data_device) {
|
||||
/* Clear references to the clipboard held by other seats, as they are about to become invalid.
|
||||
* For the target seat, the new source data is set before clearing the old source, as some
|
||||
* clipboard managers prefer this behavior.
|
||||
*/
|
||||
SDL_WaylandSeat *s;
|
||||
wl_list_for_each (s, &video_data->seat_list, link) {
|
||||
if (s->data_device) {
|
||||
if (s != seat) {
|
||||
Wayland_DataSourceDestroy(s->data_device->selection_source);
|
||||
s->data_device->selection_source = NULL;
|
||||
}
|
||||
|
||||
Wayland_DataOfferDestroy(s->data_device->selection_offer);
|
||||
s->data_device->selection_offer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_WaylandDataDevice *data_device = seat->data_device;
|
||||
|
||||
if (_this->clipboard_callback && _this->clipboard_mime_types) {
|
||||
@@ -65,7 +82,7 @@ bool Wayland_SetClipboardData(SDL_VideoDevice *_this)
|
||||
void *Wayland_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *length)
|
||||
{
|
||||
SDL_VideoData *video_data = _this->internal;
|
||||
SDL_WaylandSeat *seat = video_data->last_incoming_data_offer_seat;
|
||||
SDL_WaylandSeat *seat = video_data->current_data_offer_seat;
|
||||
void *buffer = NULL;
|
||||
|
||||
if (seat && seat->data_device) {
|
||||
@@ -83,7 +100,7 @@ void *Wayland_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, si
|
||||
bool Wayland_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type)
|
||||
{
|
||||
SDL_VideoData *video_data = _this->internal;
|
||||
SDL_WaylandSeat *seat = video_data->last_incoming_data_offer_seat;
|
||||
SDL_WaylandSeat *seat = video_data->current_data_offer_seat;
|
||||
bool result = false;
|
||||
|
||||
if (seat && seat->data_device) {
|
||||
@@ -122,7 +139,7 @@ bool Wayland_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text)
|
||||
seat = wl_container_of(video_data->seat_list.next, seat, link);
|
||||
}
|
||||
|
||||
video_data->last_incoming_primary_selection_seat = seat;
|
||||
video_data->current_primary_selection_seat = seat;
|
||||
|
||||
if (seat && seat->primary_selection_device) {
|
||||
SDL_WaylandPrimarySelectionDevice *primary_selection_device = seat->primary_selection_device;
|
||||
@@ -148,7 +165,7 @@ bool Wayland_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text)
|
||||
char *Wayland_GetPrimarySelectionText(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *video_data = _this->internal;
|
||||
SDL_WaylandSeat *seat = video_data->last_incoming_primary_selection_seat;
|
||||
SDL_WaylandSeat *seat = video_data->current_primary_selection_seat;
|
||||
char *text = NULL;
|
||||
size_t length = 0;
|
||||
|
||||
@@ -176,7 +193,7 @@ char *Wayland_GetPrimarySelectionText(SDL_VideoDevice *_this)
|
||||
bool Wayland_HasPrimarySelectionText(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *video_data = _this->internal;
|
||||
SDL_WaylandSeat *seat = video_data->last_incoming_primary_selection_seat;
|
||||
SDL_WaylandSeat *seat = video_data->current_primary_selection_seat;
|
||||
bool result = false;
|
||||
|
||||
if (seat && seat->primary_selection_device) {
|
||||
|
||||
@@ -446,6 +446,29 @@ static void DataOfferCheckSource(SDL_WaylandDataOffer *offer, const char *mime_t
|
||||
}
|
||||
}
|
||||
|
||||
static void SetCurrentClipboardOffer(SDL_WaylandDataOffer *offer)
|
||||
{
|
||||
SDL_WaylandSeat *offer_seat = offer->data_device->seat;
|
||||
SDL_VideoData *video_data = offer_seat->display;
|
||||
|
||||
// Clear any existing references to the existing clipboard data before replacing the current offer.
|
||||
SDL_WaylandSeat *s;
|
||||
wl_list_for_each (s, &video_data->seat_list, link) {
|
||||
if (s->data_device) {
|
||||
Wayland_DataSourceDestroy(s->data_device->selection_source);
|
||||
s->data_device->selection_source = NULL;
|
||||
|
||||
// Don't clear the offer that is about to be set.
|
||||
if (s != offer_seat) {
|
||||
Wayland_DataOfferDestroy(s->data_device->selection_offer);
|
||||
s->data_device->selection_offer = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
video_data->current_data_offer_seat = offer_seat;
|
||||
}
|
||||
|
||||
void Wayland_DataOfferNotifyFromMIMEs(SDL_WaylandDataOffer *offer, bool check_origin)
|
||||
{
|
||||
int nformats = 0;
|
||||
@@ -494,6 +517,7 @@ void Wayland_DataOfferNotifyFromMIMEs(SDL_WaylandDataOffer *offer, bool check_or
|
||||
new_mime_types[nformats] = NULL;
|
||||
}
|
||||
|
||||
SetCurrentClipboardOffer(offer);
|
||||
SDL_SendClipboardUpdate(false, new_mime_types, nformats);
|
||||
}
|
||||
|
||||
@@ -697,26 +721,26 @@ bool Wayland_PrimarySelectionDeviceSetSelection(SDL_WaylandPrimarySelectionDevic
|
||||
void Wayland_DataDeviceSetSerial(SDL_WaylandDataDevice *data_device, uint32_t serial)
|
||||
{
|
||||
if (data_device) {
|
||||
data_device->selection_serial = serial;
|
||||
|
||||
// If there was no serial and there is a pending selection set it now.
|
||||
// If there was no serial and there is a pending selection, set it now.
|
||||
if (data_device->selection_serial == 0 && data_device->selection_source) {
|
||||
wl_data_device_set_selection(data_device->data_device, data_device->selection_source->source, data_device->selection_serial);
|
||||
wl_data_device_set_selection(data_device->data_device, data_device->selection_source->source, serial);
|
||||
}
|
||||
|
||||
data_device->selection_serial = serial;
|
||||
}
|
||||
}
|
||||
|
||||
void Wayland_PrimarySelectionDeviceSetSerial(SDL_WaylandPrimarySelectionDevice *primary_selection_device, uint32_t serial)
|
||||
{
|
||||
if (primary_selection_device) {
|
||||
primary_selection_device->selection_serial = serial;
|
||||
|
||||
// If there was no serial and there is a pending selection set it now.
|
||||
// If there was no serial and there is a pending selection, set it now.
|
||||
if (primary_selection_device->selection_serial == 0 && primary_selection_device->selection_source) {
|
||||
zwp_primary_selection_device_v1_set_selection(primary_selection_device->primary_selection_device,
|
||||
primary_selection_device->selection_source->source,
|
||||
primary_selection_device->selection_serial);
|
||||
serial);
|
||||
}
|
||||
|
||||
primary_selection_device->selection_serial = serial;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2749,7 +2749,6 @@ static void data_device_handle_data_offer(void *data, struct wl_data_device *wl_
|
||||
SDL_WaylandDataOffer *data_offer = SDL_calloc(1, sizeof(*data_offer));
|
||||
if (data_offer) {
|
||||
SDL_WaylandDataDevice *data_device = (SDL_WaylandDataDevice *)data;
|
||||
data_device->seat->display->last_incoming_data_offer_seat = data_device->seat;
|
||||
data_offer->offer = id;
|
||||
data_offer->data_device = data_device;
|
||||
data_offer->read_fd = -1;
|
||||
@@ -3054,7 +3053,7 @@ static void primary_selection_device_handle_offer(void *data, struct zwp_primary
|
||||
SDL_WaylandPrimarySelectionOffer *primary_selection_offer = SDL_calloc(1, sizeof(*primary_selection_offer));
|
||||
if (primary_selection_offer) {
|
||||
SDL_WaylandPrimarySelectionDevice *primary_selection_device = (SDL_WaylandPrimarySelectionDevice *)data;
|
||||
primary_selection_device->seat->display->last_incoming_primary_selection_seat = primary_selection_device->seat;
|
||||
primary_selection_device->seat->display->current_primary_selection_seat = primary_selection_device->seat;
|
||||
primary_selection_offer->offer = id;
|
||||
primary_selection_offer->primary_selection_device = primary_selection_device;
|
||||
WAYLAND_wl_list_init(&(primary_selection_offer->mimes));
|
||||
|
||||
@@ -96,8 +96,8 @@ struct SDL_VideoData
|
||||
|
||||
struct wl_list seat_list;
|
||||
struct SDL_WaylandSeat *last_implicit_grab_seat;
|
||||
struct SDL_WaylandSeat *last_incoming_data_offer_seat;
|
||||
struct SDL_WaylandSeat *last_incoming_primary_selection_seat;
|
||||
struct SDL_WaylandSeat *current_data_offer_seat;
|
||||
struct SDL_WaylandSeat *current_primary_selection_seat;
|
||||
Wayland_EventThreadContext *event_thread_context;
|
||||
|
||||
SDL_DisplayData **output_list;
|
||||
|
||||
Reference in New Issue
Block a user