From 4cb0697e576820774013f399c89fe85673e2f338 Mon Sep 17 00:00:00 2001
From: emersion <contact@emersion.fr>
Date: Thu, 29 Nov 2018 19:30:04 +0100
Subject: 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
---
 include/wlr/types/wlr_data_control_v1.h       |  2 +-
 include/wlr/types/wlr_data_device.h           |  6 ++++++
 include/wlr/types/wlr_gtk_primary_selection.h |  2 +-
 include/wlr/types/wlr_primary_selection.h     |  2 ++
 include/wlr/types/wlr_seat.h                  | 26 ++++++++++++++++++++------
 5 files changed, 30 insertions(+), 8 deletions(-)

(limited to 'include/wlr')

diff --git a/include/wlr/types/wlr_data_control_v1.h b/include/wlr/types/wlr_data_control_v1.h
index 50c96736..7d336344 100644
--- a/include/wlr/types/wlr_data_control_v1.h
+++ b/include/wlr/types/wlr_data_control_v1.h
@@ -34,7 +34,7 @@ struct wlr_data_control_device_v1 {
 	struct wl_resource *selection_offer_resource; // current selection offer
 
 	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(
diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h
index 209d917d..4ab181db 100644
--- a/include/wlr/types/wlr_data_device.h
+++ b/include/wlr/types/wlr_data_device.h
@@ -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);
 
+/**
+ * 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.
  * This removes the previous one if there was any. In case the selection doesn't
diff --git a/include/wlr/types/wlr_gtk_primary_selection.h b/include/wlr/types/wlr_gtk_primary_selection.h
index 7cf34201..4d7f84af 100644
--- a/include/wlr/types/wlr_gtk_primary_selection.h
+++ b/include/wlr/types/wlr_gtk_primary_selection.h
@@ -39,7 +39,7 @@ struct wlr_gtk_primary_selection_device {
 
 	struct wl_listener seat_destroy;
 	struct wl_listener seat_focus_change;
-	struct wl_listener seat_primary_selection;
+	struct wl_listener seat_set_primary_selection;
 
 	void *data;
 };
diff --git a/include/wlr/types/wlr_primary_selection.h b/include/wlr/types/wlr_primary_selection.h
index a2b23574..b1d45b61 100644
--- a/include/wlr/types/wlr_primary_selection.h
+++ b/include/wlr/types/wlr_primary_selection.h
@@ -48,6 +48,8 @@ void wlr_primary_selection_source_send(
 	struct wlr_primary_selection_source *source, const char *mime_type,
 	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
  * clear it. This removes the previous one if there was any. In case the
diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h
index 1ad5542e..6bc4af1a 100644
--- a/include/wlr/types/wlr_seat.h
+++ b/include/wlr/types/wlr_seat.h
@@ -23,6 +23,7 @@
 struct wlr_seat_client {
 	struct wl_client *client;
 	struct wlr_seat *seat;
+	struct wl_list link;
 
 	// lists of wl_resource
 	struct wl_list resources;
@@ -34,8 +35,6 @@ struct wlr_seat_client {
 	struct {
 		struct wl_signal destroy;
 	} events;
-
-	struct wl_list link;
 };
 
 struct wlr_touch_point {
@@ -226,13 +225,18 @@ struct wlr_seat {
 		struct wl_signal touch_grab_begin;
 		struct wl_signal touch_grab_end;
 
+		// wlr_seat_pointer_request_set_cursor_event
 		struct wl_signal request_set_cursor;
 
-		struct wl_signal selection;
-		struct wl_signal primary_selection;
+		// wlr_seat_request_set_selection_event
+		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 new_drag_icon;
+		struct wl_signal start_drag; // wlr_drag
+		struct wl_signal new_drag_icon; // wlr_drag_icon
 
 		struct wl_signal destroy;
 	} events;
@@ -247,6 +251,16 @@ struct wlr_seat_pointer_request_set_cursor_event {
 	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 *seat;
 	struct wlr_surface *old_surface, *new_surface;
-- 
cgit v1.2.3