data-device, primary-selection: add request_set_selection
This makes compositors able to block and/or customize set_selection requests coming from clients. For instance, it's possible for a compositor to disable rich selection content (by removing all MIME types except text/plain). This commit implements the design proposed in [1]. Two new events are added to wlr_seat: request_set_selection and request_set_primary_selection. Compositors need to listen to these events and either destroy the source or effectively set the selection. Fixes https://github.com/swaywm/wlroots/issues/1138 [1]: https://github.com/swaywm/wlroots/issues/1367#issuecomment-442403454
This commit is contained in:
parent
c41d01306d
commit
4cb0697e57
|
@ -38,6 +38,8 @@ struct roots_seat {
|
||||||
struct wl_list tablets;
|
struct wl_list tablets;
|
||||||
struct wl_list tablet_pads;
|
struct wl_list tablet_pads;
|
||||||
|
|
||||||
|
struct wl_listener request_set_selection;
|
||||||
|
struct wl_listener request_set_primary_selection;
|
||||||
struct wl_listener new_drag_icon;
|
struct wl_listener new_drag_icon;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct wlr_data_control_device_v1 {
|
||||||
struct wl_resource *selection_offer_resource; // current selection offer
|
struct wl_resource *selection_offer_resource; // current selection offer
|
||||||
|
|
||||||
struct wl_listener seat_destroy;
|
struct wl_listener seat_destroy;
|
||||||
struct wl_listener seat_selection;
|
struct wl_listener seat_set_selection;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1_create(
|
struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1_create(
|
||||||
|
|
|
@ -165,6 +165,12 @@ 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests a selection to be set for the seat.
|
||||||
|
*/
|
||||||
|
void wlr_seat_request_set_selection(struct wlr_seat *seat,
|
||||||
|
struct wlr_data_source *source, uint32_t serial);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current selection for the seat. NULL can be provided to clear it.
|
* 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
|
* This removes the previous one if there was any. In case the selection doesn't
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct wlr_gtk_primary_selection_device {
|
||||||
|
|
||||||
struct wl_listener seat_destroy;
|
struct wl_listener seat_destroy;
|
||||||
struct wl_listener seat_focus_change;
|
struct wl_listener seat_focus_change;
|
||||||
struct wl_listener seat_primary_selection;
|
struct wl_listener seat_set_primary_selection;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
|
@ -48,6 +48,8 @@ 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);
|
||||||
|
|
||||||
|
void wlr_seat_request_set_primary_selection(struct wlr_seat *seat,
|
||||||
|
struct wlr_primary_selection_source *source, uint32_t serial);
|
||||||
/**
|
/**
|
||||||
* Sets the current primary selection for the seat. NULL can be provided to
|
* 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
|
* clear it. This removes the previous one if there was any. In case the
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
struct wlr_seat_client {
|
struct wlr_seat_client {
|
||||||
struct wl_client *client;
|
struct wl_client *client;
|
||||||
struct wlr_seat *seat;
|
struct wlr_seat *seat;
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
// lists of wl_resource
|
// lists of wl_resource
|
||||||
struct wl_list resources;
|
struct wl_list resources;
|
||||||
|
@ -34,8 +35,6 @@ struct wlr_seat_client {
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
struct wl_list link;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_touch_point {
|
struct wlr_touch_point {
|
||||||
|
@ -226,13 +225,18 @@ struct wlr_seat {
|
||||||
struct wl_signal touch_grab_begin;
|
struct wl_signal touch_grab_begin;
|
||||||
struct wl_signal touch_grab_end;
|
struct wl_signal touch_grab_end;
|
||||||
|
|
||||||
|
// wlr_seat_pointer_request_set_cursor_event
|
||||||
struct wl_signal request_set_cursor;
|
struct wl_signal request_set_cursor;
|
||||||
|
|
||||||
struct wl_signal selection;
|
// wlr_seat_request_set_selection_event
|
||||||
struct wl_signal primary_selection;
|
struct wl_signal request_set_selection;
|
||||||
|
struct wl_signal set_selection;
|
||||||
|
// wlr_seat_request_set_primary_selection_event
|
||||||
|
struct wl_signal request_set_primary_selection;
|
||||||
|
struct wl_signal set_primary_selection;
|
||||||
|
|
||||||
struct wl_signal start_drag;
|
struct wl_signal start_drag; // wlr_drag
|
||||||
struct wl_signal new_drag_icon;
|
struct wl_signal new_drag_icon; // wlr_drag_icon
|
||||||
|
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
} events;
|
} events;
|
||||||
|
@ -247,6 +251,16 @@ struct wlr_seat_pointer_request_set_cursor_event {
|
||||||
int32_t hotspot_x, hotspot_y;
|
int32_t hotspot_x, hotspot_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wlr_seat_request_set_selection_event {
|
||||||
|
struct wlr_data_source *source;
|
||||||
|
uint32_t serial;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_seat_request_set_primary_selection_event {
|
||||||
|
struct wlr_primary_selection_source *source;
|
||||||
|
uint32_t serial;
|
||||||
|
};
|
||||||
|
|
||||||
struct wlr_seat_pointer_focus_change_event {
|
struct wlr_seat_pointer_focus_change_event {
|
||||||
struct wlr_seat *seat;
|
struct wlr_seat *seat;
|
||||||
struct wlr_surface *old_surface, *new_surface;
|
struct wlr_surface *old_surface, *new_surface;
|
||||||
|
|
|
@ -128,8 +128,8 @@ struct wlr_xwm {
|
||||||
|
|
||||||
struct wl_listener compositor_new_surface;
|
struct wl_listener compositor_new_surface;
|
||||||
struct wl_listener compositor_destroy;
|
struct wl_listener compositor_destroy;
|
||||||
struct wl_listener seat_selection;
|
struct wl_listener seat_set_selection;
|
||||||
struct wl_listener seat_primary_selection;
|
struct wl_listener seat_set_primary_selection;
|
||||||
struct wl_listener seat_start_drag;
|
struct wl_listener seat_start_drag;
|
||||||
struct wl_listener seat_drag_focus;
|
struct wl_listener seat_drag_focus;
|
||||||
struct wl_listener seat_drag_motion;
|
struct wl_listener seat_drag_motion;
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <wlr/backend/libinput.h>
|
#include <wlr/backend/libinput.h>
|
||||||
#include <wlr/config.h>
|
#include <wlr/config.h>
|
||||||
|
#include <wlr/types/wlr_data_device.h>
|
||||||
#include <wlr/types/wlr_idle.h>
|
#include <wlr/types/wlr_idle.h>
|
||||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
#include "wlr/types/wlr_switch.h"
|
#include <wlr/types/wlr_primary_selection.h>
|
||||||
|
#include <wlr/types/wlr_switch.h>
|
||||||
#include <wlr/types/wlr_tablet_v2.h>
|
#include <wlr/types/wlr_tablet_v2.h>
|
||||||
#include <wlr/types/wlr_xcursor_manager.h>
|
#include <wlr/types/wlr_xcursor_manager.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
@ -20,7 +22,6 @@
|
||||||
#include "rootston/text_input.h"
|
#include "rootston/text_input.h"
|
||||||
#include "rootston/xcursor.h"
|
#include "rootston/xcursor.h"
|
||||||
|
|
||||||
|
|
||||||
static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
||||||
struct roots_keyboard *keyboard =
|
struct roots_keyboard *keyboard =
|
||||||
wl_container_of(listener, keyboard, keyboard_key);
|
wl_container_of(listener, keyboard, keyboard_key);
|
||||||
|
@ -536,6 +537,22 @@ static void roots_seat_handle_new_drag_icon(struct wl_listener *listener,
|
||||||
roots_drag_icon_update_position(icon);
|
roots_drag_icon_update_position(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void roots_seat_handle_request_set_selection(
|
||||||
|
struct wl_listener *listener, void *data) {
|
||||||
|
struct roots_seat *seat =
|
||||||
|
wl_container_of(listener, seat, request_set_selection);
|
||||||
|
struct wlr_seat_request_set_selection_event *event = data;
|
||||||
|
wlr_seat_set_selection(seat->seat, event->source, event->serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void roots_seat_handle_request_set_primary_selection(
|
||||||
|
struct wl_listener *listener, void *data) {
|
||||||
|
struct roots_seat *seat =
|
||||||
|
wl_container_of(listener, seat, request_set_primary_selection);
|
||||||
|
struct wlr_seat_request_set_primary_selection_event *event = data;
|
||||||
|
wlr_seat_set_primary_selection(seat->seat, event->source, event->serial);
|
||||||
|
}
|
||||||
|
|
||||||
void roots_drag_icon_update_position(struct roots_drag_icon *icon) {
|
void roots_drag_icon_update_position(struct roots_drag_icon *icon) {
|
||||||
roots_drag_icon_damage_whole(icon);
|
roots_drag_icon_damage_whole(icon);
|
||||||
|
|
||||||
|
@ -621,6 +638,14 @@ struct roots_seat *roots_seat_create(struct roots_input *input, char *name) {
|
||||||
|
|
||||||
wl_list_insert(&input->seats, &seat->link);
|
wl_list_insert(&input->seats, &seat->link);
|
||||||
|
|
||||||
|
seat->request_set_selection.notify =
|
||||||
|
roots_seat_handle_request_set_selection;
|
||||||
|
wl_signal_add(&seat->seat->events.request_set_selection,
|
||||||
|
&seat->request_set_selection);
|
||||||
|
seat->request_set_primary_selection.notify =
|
||||||
|
roots_seat_handle_request_set_primary_selection;
|
||||||
|
wl_signal_add(&seat->seat->events.request_set_primary_selection,
|
||||||
|
&seat->request_set_primary_selection);
|
||||||
seat->new_drag_icon.notify = roots_seat_handle_new_drag_icon;
|
seat->new_drag_icon.notify = roots_seat_handle_new_drag_icon;
|
||||||
wl_signal_add(&seat->seat->events.new_drag_icon, &seat->new_drag_icon);
|
wl_signal_add(&seat->seat->events.new_drag_icon, &seat->new_drag_icon);
|
||||||
seat->destroy.notify = roots_seat_handle_destroy;
|
seat->destroy.notify = roots_seat_handle_destroy;
|
||||||
|
|
|
@ -32,13 +32,13 @@ static void data_device_set_selection(struct wl_client *client,
|
||||||
source = client_data_source_from_resource(source_resource);
|
source = client_data_source_from_resource(source_resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_data_source *wlr_source =
|
|
||||||
source != NULL ? &source->source : NULL;
|
|
||||||
wlr_seat_set_selection(seat_client->seat, wlr_source, serial);
|
|
||||||
|
|
||||||
if (source != NULL) {
|
if (source != NULL) {
|
||||||
source->finalized = true;
|
source->finalized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_data_source *wlr_source =
|
||||||
|
source != NULL ? &source->source : NULL;
|
||||||
|
wlr_seat_request_set_selection(seat_client->seat, wlr_source, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void data_device_start_drag(struct wl_client *client,
|
static void data_device_start_drag(struct wl_client *client,
|
||||||
|
@ -116,7 +116,23 @@ void wlr_seat_client_send_selection(struct wlr_seat_client *seat_client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seat_client_selection_source_destroy(
|
void wlr_seat_request_set_selection(struct wlr_seat *seat,
|
||||||
|
struct wlr_data_source *source, uint32_t serial) {
|
||||||
|
if (seat->selection_source &&
|
||||||
|
seat->selection_serial - serial < UINT32_MAX / 2) {
|
||||||
|
wlr_log(WLR_DEBUG, "Rejecting set_selection request, invalid serial "
|
||||||
|
"(%"PRIu32" <= %"PRIu32")", serial, seat->selection_serial);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_seat_request_set_selection_event event = {
|
||||||
|
.source = source,
|
||||||
|
.serial = serial,
|
||||||
|
};
|
||||||
|
wlr_signal_emit_safe(&seat->events.request_set_selection, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void seat_handle_selection_source_destroy(
|
||||||
struct wl_listener *listener, void *data) {
|
struct wl_listener *listener, void *data) {
|
||||||
struct wlr_seat *seat =
|
struct wlr_seat *seat =
|
||||||
wl_container_of(listener, seat, selection_source_destroy);
|
wl_container_of(listener, seat, selection_source_destroy);
|
||||||
|
@ -132,16 +148,11 @@ static void seat_client_selection_source_destroy(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_signal_emit_safe(&seat->events.selection, seat);
|
wlr_signal_emit_safe(&seat->events.set_selection, seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
if (seat->selection_source &&
|
|
||||||
seat->selection_serial - serial < UINT32_MAX / 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (seat->selection_source) {
|
if (seat->selection_source) {
|
||||||
wl_list_remove(&seat->selection_source_destroy.link);
|
wl_list_remove(&seat->selection_source_destroy.link);
|
||||||
wlr_data_source_cancel(seat->selection_source);
|
wlr_data_source_cancel(seat->selection_source);
|
||||||
|
@ -153,19 +164,18 @@ void wlr_seat_set_selection(struct wlr_seat *seat,
|
||||||
|
|
||||||
struct wlr_seat_client *focused_client =
|
struct wlr_seat_client *focused_client =
|
||||||
seat->keyboard_state.focused_client;
|
seat->keyboard_state.focused_client;
|
||||||
|
|
||||||
if (focused_client) {
|
if (focused_client) {
|
||||||
wlr_seat_client_send_selection(focused_client);
|
wlr_seat_client_send_selection(focused_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_signal_emit_safe(&seat->events.selection, seat);
|
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
seat->selection_source_destroy.notify =
|
seat->selection_source_destroy.notify =
|
||||||
seat_client_selection_source_destroy;
|
seat_handle_selection_source_destroy;
|
||||||
wl_signal_add(&source->events.destroy,
|
wl_signal_add(&source->events.destroy,
|
||||||
&seat->selection_source_destroy);
|
&seat->selection_source_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_signal_emit_safe(&seat->events.set_selection, seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -274,8 +274,10 @@ struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
|
||||||
|
|
||||||
wl_signal_init(&seat->events.request_set_cursor);
|
wl_signal_init(&seat->events.request_set_cursor);
|
||||||
|
|
||||||
wl_signal_init(&seat->events.selection);
|
wl_signal_init(&seat->events.request_set_selection);
|
||||||
wl_signal_init(&seat->events.primary_selection);
|
wl_signal_init(&seat->events.set_selection);
|
||||||
|
wl_signal_init(&seat->events.request_set_primary_selection);
|
||||||
|
wl_signal_init(&seat->events.set_primary_selection);
|
||||||
|
|
||||||
wl_signal_init(&seat->events.pointer_grab_begin);
|
wl_signal_init(&seat->events.pointer_grab_begin);
|
||||||
wl_signal_init(&seat->events.pointer_grab_end);
|
wl_signal_init(&seat->events.pointer_grab_end);
|
||||||
|
|
|
@ -184,9 +184,8 @@ static void control_handle_set_selection(struct wl_client *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_data_source *wlr_source = source ? &source->source : NULL;
|
struct wlr_data_source *wlr_source = source ? &source->source : NULL;
|
||||||
struct wl_display *display = wl_client_get_display(client);
|
wlr_seat_request_set_selection(device->seat, wlr_source,
|
||||||
wlr_seat_set_selection(device->seat, wlr_source,
|
wl_display_next_serial(device->seat->display));
|
||||||
wl_display_next_serial(display));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void control_handle_destroy(struct wl_client *client,
|
static void control_handle_destroy(struct wl_client *client,
|
||||||
|
@ -232,10 +231,10 @@ static void control_handle_seat_destroy(struct wl_listener *listener,
|
||||||
wlr_data_control_device_v1_destroy(device);
|
wlr_data_control_device_v1_destroy(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void control_handle_seat_selection(struct wl_listener *listener,
|
static void control_handle_seat_set_selection(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct wlr_data_control_device_v1 *device =
|
struct wlr_data_control_device_v1 *device =
|
||||||
wl_container_of(listener, device, seat_selection);
|
wl_container_of(listener, device, seat_set_selection);
|
||||||
control_send_selection(device);
|
control_send_selection(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +249,7 @@ void wlr_data_control_device_v1_destroy(struct wlr_data_control_device_v1 *devic
|
||||||
wl_resource_set_user_data(device->selection_offer_resource, NULL);
|
wl_resource_set_user_data(device->selection_offer_resource, NULL);
|
||||||
}
|
}
|
||||||
wl_list_remove(&device->seat_destroy.link);
|
wl_list_remove(&device->seat_destroy.link);
|
||||||
wl_list_remove(&device->seat_selection.link);
|
wl_list_remove(&device->seat_set_selection.link);
|
||||||
wl_list_remove(&device->link);
|
wl_list_remove(&device->link);
|
||||||
free(device);
|
free(device);
|
||||||
}
|
}
|
||||||
|
@ -319,8 +318,9 @@ static void manager_handle_get_data_device(struct wl_client *client,
|
||||||
device->seat_destroy.notify = control_handle_seat_destroy;
|
device->seat_destroy.notify = control_handle_seat_destroy;
|
||||||
wl_signal_add(&device->seat->events.destroy, &device->seat_destroy);
|
wl_signal_add(&device->seat->events.destroy, &device->seat_destroy);
|
||||||
|
|
||||||
device->seat_selection.notify = control_handle_seat_selection;
|
device->seat_set_selection.notify = control_handle_seat_set_selection;
|
||||||
wl_signal_add(&device->seat->events.selection, &device->seat_selection);
|
wl_signal_add(&device->seat->events.set_selection,
|
||||||
|
&device->seat_set_selection);
|
||||||
|
|
||||||
wl_list_insert(&manager->devices, &device->link);
|
wl_list_insert(&manager->devices, &device->link);
|
||||||
wlr_signal_emit_safe(&manager->events.new_device, device);
|
wlr_signal_emit_safe(&manager->events.new_device, device);
|
||||||
|
|
|
@ -208,7 +208,7 @@ static void device_handle_set_selection(struct wl_client *client,
|
||||||
source = &client_source->source;
|
source = &client_source->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_seat_set_primary_selection(device->seat, source, serial);
|
wlr_seat_request_set_primary_selection(device->seat, source, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_handle_destroy(struct wl_client *client,
|
static void device_handle_destroy(struct wl_client *client,
|
||||||
|
@ -272,10 +272,10 @@ static void device_handle_seat_focus_change(struct wl_listener *listener,
|
||||||
device_send_selection(device);
|
device_send_selection(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_handle_seat_primary_selection(struct wl_listener *listener,
|
static void device_handle_seat_set_primary_selection(
|
||||||
void *data) {
|
struct wl_listener *listener, void *data) {
|
||||||
struct wlr_gtk_primary_selection_device *device =
|
struct wlr_gtk_primary_selection_device *device =
|
||||||
wl_container_of(listener, device, seat_primary_selection);
|
wl_container_of(listener, device, seat_set_primary_selection);
|
||||||
|
|
||||||
struct wl_resource *resource, *tmp;
|
struct wl_resource *resource, *tmp;
|
||||||
wl_resource_for_each_safe(resource, tmp, &device->offers) {
|
wl_resource_for_each_safe(resource, tmp, &device->offers) {
|
||||||
|
@ -314,10 +314,10 @@ static struct wlr_gtk_primary_selection_device *get_or_create_device(
|
||||||
wl_signal_add(&seat->keyboard_state.events.focus_change,
|
wl_signal_add(&seat->keyboard_state.events.focus_change,
|
||||||
&device->seat_focus_change);
|
&device->seat_focus_change);
|
||||||
|
|
||||||
device->seat_primary_selection.notify =
|
device->seat_set_primary_selection.notify =
|
||||||
device_handle_seat_primary_selection;
|
device_handle_seat_set_primary_selection;
|
||||||
wl_signal_add(&seat->events.primary_selection,
|
wl_signal_add(&seat->events.set_primary_selection,
|
||||||
&device->seat_primary_selection);
|
&device->seat_set_primary_selection);
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ static void device_destroy(struct wlr_gtk_primary_selection_device *device) {
|
||||||
wl_list_remove(&device->link);
|
wl_list_remove(&device->link);
|
||||||
wl_list_remove(&device->seat_destroy.link);
|
wl_list_remove(&device->seat_destroy.link);
|
||||||
wl_list_remove(&device->seat_focus_change.link);
|
wl_list_remove(&device->seat_focus_change.link);
|
||||||
wl_list_remove(&device->seat_primary_selection.link);
|
wl_list_remove(&device->seat_set_primary_selection.link);
|
||||||
struct wl_resource *resource, *resource_tmp;
|
struct wl_resource *resource, *resource_tmp;
|
||||||
wl_resource_for_each_safe(resource, resource_tmp, &device->offers) {
|
wl_resource_for_each_safe(resource, resource_tmp, &device->offers) {
|
||||||
destroy_offer(resource);
|
destroy_offer(resource);
|
||||||
|
|
|
@ -41,13 +41,30 @@ void wlr_primary_selection_source_send(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wlr_seat_request_set_primary_selection(struct wlr_seat *seat,
|
||||||
|
struct wlr_primary_selection_source *source, uint32_t serial) {
|
||||||
|
if (seat->primary_selection_source &&
|
||||||
|
seat->primary_selection_serial - serial < UINT32_MAX / 2) {
|
||||||
|
wlr_log(WLR_DEBUG, "Rejecting set_primary_selection request, "
|
||||||
|
"invalid serial (%"PRIu32" <= %"PRIu32")",
|
||||||
|
serial, seat->primary_selection_serial);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_seat_request_set_primary_selection_event event = {
|
||||||
|
.source = source,
|
||||||
|
.serial = serial,
|
||||||
|
};
|
||||||
|
wlr_signal_emit_safe(&seat->events.request_set_primary_selection, &event);
|
||||||
|
}
|
||||||
|
|
||||||
static void seat_handle_primary_selection_source_destroy(
|
static void seat_handle_primary_selection_source_destroy(
|
||||||
struct wl_listener *listener, void *data) {
|
struct wl_listener *listener, void *data) {
|
||||||
struct wlr_seat *seat =
|
struct wlr_seat *seat =
|
||||||
wl_container_of(listener, seat, primary_selection_source_destroy);
|
wl_container_of(listener, seat, primary_selection_source_destroy);
|
||||||
wl_list_remove(&seat->primary_selection_source_destroy.link);
|
wl_list_remove(&seat->primary_selection_source_destroy.link);
|
||||||
seat->primary_selection_source = NULL;
|
seat->primary_selection_source = NULL;
|
||||||
wlr_signal_emit_safe(&seat->events.primary_selection, seat);
|
wlr_signal_emit_safe(&seat->events.set_primary_selection, seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_seat_set_primary_selection(struct wlr_seat *seat,
|
void wlr_seat_set_primary_selection(struct wlr_seat *seat,
|
||||||
|
@ -75,5 +92,5 @@ void wlr_seat_set_primary_selection(struct wlr_seat *seat,
|
||||||
&seat->primary_selection_source_destroy);
|
&seat->primary_selection_source_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_signal_emit_safe(&seat->events.primary_selection, seat);
|
wlr_signal_emit_safe(&seat->events.set_primary_selection, seat);
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,7 +350,7 @@ 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_selection(xwm->seat, &source->base,
|
wlr_seat_request_set_selection(xwm->seat, &source->base,
|
||||||
wl_display_next_serial(xwm->xwayland->wl_display));
|
wl_display_next_serial(xwm->xwayland->wl_display));
|
||||||
} else {
|
} else {
|
||||||
wlr_data_source_cancel(&source->base);
|
wlr_data_source_cancel(&source->base);
|
||||||
|
@ -425,10 +425,10 @@ int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
|
||||||
// A real X client selection went away, not our
|
// A real X client selection went away, not our
|
||||||
// proxy selection
|
// proxy selection
|
||||||
if (selection == &xwm->clipboard_selection) {
|
if (selection == &xwm->clipboard_selection) {
|
||||||
wlr_seat_set_selection(xwm->seat, NULL,
|
wlr_seat_request_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_request_set_primary_selection(xwm->seat, NULL,
|
||||||
wl_display_next_serial(xwm->xwayland->wl_display));
|
wl_display_next_serial(xwm->xwayland->wl_display));
|
||||||
} else if (selection == &xwm->dnd_selection) {
|
} else if (selection == &xwm->dnd_selection) {
|
||||||
// TODO: DND
|
// TODO: DND
|
||||||
|
|
|
@ -255,11 +255,11 @@ static void xwm_selection_set_owner(struct wlr_xwm_selection *selection,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seat_handle_selection(struct wl_listener *listener,
|
static void handle_seat_set_selection(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct wlr_seat *seat = data;
|
struct wlr_seat *seat = data;
|
||||||
struct wlr_xwm *xwm =
|
struct wlr_xwm *xwm =
|
||||||
wl_container_of(listener, xwm, seat_selection);
|
wl_container_of(listener, xwm, seat_set_selection);
|
||||||
struct wlr_data_source *source = seat->selection_source;
|
struct wlr_data_source *source = seat->selection_source;
|
||||||
|
|
||||||
if (source != NULL && data_source_is_xwayland(source)) {
|
if (source != NULL && data_source_is_xwayland(source)) {
|
||||||
|
@ -269,11 +269,11 @@ static void seat_handle_selection(struct wl_listener *listener,
|
||||||
xwm_selection_set_owner(&xwm->clipboard_selection, source != NULL);
|
xwm_selection_set_owner(&xwm->clipboard_selection, source != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seat_handle_primary_selection(struct wl_listener *listener,
|
static void handle_seat_set_primary_selection(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct wlr_seat *seat = data;
|
struct wlr_seat *seat = data;
|
||||||
struct wlr_xwm *xwm =
|
struct wlr_xwm *xwm =
|
||||||
wl_container_of(listener, xwm, seat_primary_selection);
|
wl_container_of(listener, xwm, seat_set_primary_selection);
|
||||||
struct wlr_primary_selection_source *source =
|
struct wlr_primary_selection_source *source =
|
||||||
seat->primary_selection_source;
|
seat->primary_selection_source;
|
||||||
|
|
||||||
|
@ -294,8 +294,8 @@ static void seat_handle_start_drag(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
void xwm_set_seat(struct wlr_xwm *xwm, struct wlr_seat *seat) {
|
void xwm_set_seat(struct wlr_xwm *xwm, struct wlr_seat *seat) {
|
||||||
if (xwm->seat != NULL) {
|
if (xwm->seat != NULL) {
|
||||||
wl_list_remove(&xwm->seat_selection.link);
|
wl_list_remove(&xwm->seat_set_selection.link);
|
||||||
wl_list_remove(&xwm->seat_primary_selection.link);
|
wl_list_remove(&xwm->seat_set_primary_selection.link);
|
||||||
wl_list_remove(&xwm->seat_start_drag.link);
|
wl_list_remove(&xwm->seat_start_drag.link);
|
||||||
xwm->seat = NULL;
|
xwm->seat = NULL;
|
||||||
}
|
}
|
||||||
|
@ -306,13 +306,14 @@ void xwm_set_seat(struct wlr_xwm *xwm, struct wlr_seat *seat) {
|
||||||
|
|
||||||
xwm->seat = seat;
|
xwm->seat = seat;
|
||||||
|
|
||||||
wl_signal_add(&seat->events.selection, &xwm->seat_selection);
|
wl_signal_add(&seat->events.set_selection, &xwm->seat_set_selection);
|
||||||
xwm->seat_selection.notify = seat_handle_selection;
|
xwm->seat_set_selection.notify = handle_seat_set_selection;
|
||||||
wl_signal_add(&seat->events.primary_selection, &xwm->seat_primary_selection);
|
wl_signal_add(&seat->events.set_primary_selection,
|
||||||
xwm->seat_primary_selection.notify = seat_handle_primary_selection;
|
&xwm->seat_set_primary_selection);
|
||||||
|
xwm->seat_set_primary_selection.notify = handle_seat_set_primary_selection;
|
||||||
wl_signal_add(&seat->events.start_drag, &xwm->seat_start_drag);
|
wl_signal_add(&seat->events.start_drag, &xwm->seat_start_drag);
|
||||||
xwm->seat_start_drag.notify = seat_handle_start_drag;
|
xwm->seat_start_drag.notify = seat_handle_start_drag;
|
||||||
|
|
||||||
seat_handle_selection(&xwm->seat_selection, seat);
|
handle_seat_set_selection(&xwm->seat_set_selection, seat);
|
||||||
seat_handle_primary_selection(&xwm->seat_primary_selection, seat);
|
handle_seat_set_primary_selection(&xwm->seat_set_primary_selection, seat);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue