aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_data_control_v1.h2
-rw-r--r--protocol/wlr-data-control-unstable-v1.xml89
-rw-r--r--types/wlr_data_control_v1.c416
3 files changed, 434 insertions, 73 deletions
diff --git a/include/wlr/types/wlr_data_control_v1.h b/include/wlr/types/wlr_data_control_v1.h
index 7d336344..32d169b4 100644
--- a/include/wlr/types/wlr_data_control_v1.h
+++ b/include/wlr/types/wlr_data_control_v1.h
@@ -32,9 +32,11 @@ struct wlr_data_control_device_v1 {
struct wlr_seat *seat;
struct wl_resource *selection_offer_resource; // current selection offer
+ struct wl_resource *primary_selection_offer_resource; // current primary selection offer
struct wl_listener seat_destroy;
struct wl_listener seat_set_selection;
+ struct wl_listener seat_set_primary_selection;
};
struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1_create(
diff --git a/protocol/wlr-data-control-unstable-v1.xml b/protocol/wlr-data-control-unstable-v1.xml
index a5887550..3e39f2ac 100644
--- a/protocol/wlr-data-control-unstable-v1.xml
+++ b/protocol/wlr-data-control-unstable-v1.xml
@@ -2,6 +2,7 @@
<protocol name="wlr_data_control_unstable_v1">
<copyright>
Copyright © 2018 Simon Ser
+ Copyright © 2019 Ivan Molodetskikh
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
@@ -40,7 +41,7 @@
interface version number is reset.
</description>
- <interface name="zwlr_data_control_manager_v1" version="1">
+ <interface name="zwlr_data_control_manager_v1" version="2">
<description summary="manager to control data devices">
This interface is a manager that allows creating per-seat data device
controls.
@@ -68,9 +69,18 @@
appropriate destroy request has been called.
</description>
</request>
+
+ <!-- Version 2 additions -->
+
+ <event name="primary_selection" since="2">
+ <description summary="advertise primary selection support">
+ This event can be sent when binding to the wlr_data_control_manager
+ global to advertise that it supports the primary selection.
+ </description>
+ </event>
</interface>
- <interface name="zwlr_data_control_device_v1" version="1">
+ <interface name="zwlr_data_control_device_v1" version="2">
<description summary="manage a data device for a seat">
This interface allows a client to manage a seat's selection.
@@ -79,8 +89,14 @@
<request name="set_selection">
<description summary="copy data to the selection">
- All objects created by the device will still remain valid, until their
- appropriate destroy request has been called.
+ This request asks the compositor to set the selection to the data from
+ the source on behalf of the client.
+
+ The given source may not be used in any further set_selection or
+ set_primary_selection requests. Attempting to use a previously used
+ source is a protocol error.
+
+ To unset the selection, set the source to NULL.
</description>
<arg name="source" type="object" interface="zwlr_data_control_source_v1"
allow-null="true"/>
@@ -95,20 +111,19 @@
<event name="data_offer">
<description summary="introduce a new wlr_data_control_offer">
The data_offer event introduces a new wlr_data_control_offer object,
- which will subsequently be used in the wlr_data_control_device.selection
- event. Immediately following the wlr_data_control_device.data_offer
- event, the new data_offer object will send out
- wlr_data_control_offer.offer events to describe the MIME types it
- offers.
-
- This event replaces the previous data offer, which should be destroyed
- by the client.
+ which will subsequently be used in either the
+ wlr_data_control_device.selection event (for the regular clipboard
+ selections) or the wlr_data_control_device.primary_selection event (for
+ the primary clipboard selections). Immediately following the
+ wlr_data_control_device.data_offer event, the new data_offer object
+ will send out wlr_data_control_offer.offer events to describe the MIME
+ types it offers.
</description>
<arg name="id" type="new_id" interface="zwlr_data_control_offer_v1"/>
</event>
<event name="selection">
- <description summary="introduce a new wlr_data_control_offer">
+ <description summary="advertise new selection">
The selection event is sent out to notify the client of a new
wlr_data_control_offer for the selection for this device. The
wlr_data_control_device.data_offer and the wlr_data_control_offer.offer
@@ -118,6 +133,9 @@
wlr_data_control_offer or NULL is received. The client must destroy the
previous selection wlr_data_control_offer, if any, upon receiving this
event.
+
+ The first selection event is sent upon binding the
+ wlr_data_control_device object.
</description>
<arg name="id" type="object" interface="zwlr_data_control_offer_v1"
allow-null="true"/>
@@ -129,6 +147,51 @@
the client.
</description>
</event>
+
+ <!-- Version 2 additions -->
+
+ <event name="primary_selection" since="2">
+ <description summary="advertise new primary selection">
+ The primary_selection event is sent out to notify the client of a new
+ wlr_data_control_offer for the primary selection for this device. The
+ wlr_data_control_device.data_offer and the wlr_data_control_offer.offer
+ events are sent out immediately before this event to introduce the data
+ offer object. The primary_selection event is sent to a client when a
+ new primary selection is set. The wlr_data_control_offer is valid until
+ a new wlr_data_control_offer or NULL is received. The client must
+ destroy the previous primary selection wlr_data_control_offer, if any,
+ upon receiving this event.
+
+ If the compositor supports primary selection, the first
+ primary_selection event is sent upon binding the
+ wlr_data_control_device object.
+ </description>
+ <arg name="id" type="object" interface="zwlr_data_control_offer_v1"
+ allow-null="true"/>
+ </event>
+
+ <request name="set_primary_selection" since="2">
+ <description summary="copy data to the primary selection">
+ This request asks the compositor to set the primary selection to the
+ data from the source on behalf of the client.
+
+ The given source may not be used in any further set_selection or
+ set_primary_selection requests. Attempting to use a previously used
+ source is a protocol error.
+
+ To unset the primary selection, set the source to NULL.
+
+ The compositor will ignore this request if it does not support primary
+ selection.
+ </description>
+ <arg name="source" type="object" interface="zwlr_data_control_source_v1"
+ allow-null="true"/>
+ </request>
+
+ <enum name="error" since="2">
+ <entry name="used_source" value="1"
+ summary="source given to set_selection or set_primary_selection was already used before"/>
+ </enum>
</interface>
<interface name="zwlr_data_control_source_v1" version="1">
diff --git a/types/wlr_data_control_v1.c b/types/wlr_data_control_v1.c
index 2b1a33bf..99dd0dae 100644
--- a/types/wlr_data_control_v1.c
+++ b/types/wlr_data_control_v1.c
@@ -5,51 +5,26 @@
#include <unistd.h>
#include <wlr/types/wlr_data_control_v1.h>
#include <wlr/types/wlr_data_device.h>
+#include <wlr/types/wlr_primary_selection.h>
#include <wlr/util/log.h>
#include "util/signal.h"
#include "wlr-data-control-unstable-v1-protocol.h"
-#define DATA_CONTROL_MANAGER_VERSION 1
+#define DATA_CONTROL_MANAGER_VERSION 2
-struct client_data_source {
- struct wlr_data_source source;
+struct data_control_source {
struct wl_resource *resource;
+ struct wl_array mime_types;
bool finalized;
-};
-
-static const struct wlr_data_source_impl client_source_impl;
-
-static struct client_data_source *
- client_data_source_from_source(struct wlr_data_source *wlr_source) {
- assert(wlr_source->impl == &client_source_impl);
- return (struct client_data_source *)wlr_source;
-}
-
-static void client_source_send(struct wlr_data_source *wlr_source,
- const char *mime_type, int fd) {
- struct client_data_source *source =
- client_data_source_from_source(wlr_source);
- zwlr_data_control_source_v1_send_send(source->resource, mime_type, fd);
- close(fd);
-}
-
-static void client_source_destroy(struct wlr_data_source *wlr_source) {
- struct client_data_source *source =
- client_data_source_from_source(wlr_source);
- zwlr_data_control_source_v1_send_cancelled(source->resource);
- // Make the resource inert
- wl_resource_set_user_data(source->resource, NULL);
- free(source);
-}
-static const struct wlr_data_source_impl client_source_impl = {
- .send = client_source_send,
- .destroy = client_source_destroy,
+ // Only one of these is non-NULL.
+ struct wlr_data_source *active_source;
+ struct wlr_primary_selection_source *active_primary_source;
};
static const struct zwlr_data_control_source_v1_interface source_impl;
-static struct client_data_source *source_from_resource(
+static struct data_control_source *source_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource,
&zwlr_data_control_source_v1_interface, &source_impl));
@@ -58,7 +33,7 @@ static struct client_data_source *source_from_resource(
static void source_handle_offer(struct wl_client *client,
struct wl_resource *resource, const char *mime_type) {
- struct client_data_source *source = source_from_resource(resource);
+ struct data_control_source *source = source_from_resource(resource);
if (source == NULL) {
return;
}
@@ -66,12 +41,13 @@ static void source_handle_offer(struct wl_client *client,
if (source->finalized) {
wl_resource_post_error(resource,
ZWLR_DATA_CONTROL_SOURCE_V1_ERROR_INVALID_OFFER,
- "cannot mutate offer after set_selection");
+ "cannot mutate offer after set_selection or "
+ "set_primary_selection");
return;
}
const char **mime_type_ptr;
- wl_array_for_each(mime_type_ptr, &source->source.mime_types) {
+ wl_array_for_each(mime_type_ptr, &source->mime_types) {
if (strcmp(*mime_type_ptr, mime_type) == 0) {
wlr_log(WLR_DEBUG, "Ignoring duplicate MIME type offer %s",
mime_type);
@@ -85,7 +61,7 @@ static void source_handle_offer(struct wl_client *client,
return;
}
- char **p = wl_array_add(&source->source.mime_types, sizeof(char *));
+ char **p = wl_array_add(&source->mime_types, sizeof(char *));
if (p == NULL) {
free(dup_mime_type);
wl_resource_post_no_memory(resource);
@@ -105,18 +81,156 @@ static const struct zwlr_data_control_source_v1_interface source_impl = {
.destroy = source_handle_destroy,
};
+static void data_control_source_destroy(struct data_control_source *source) {
+ if (source == NULL) {
+ return;
+ }
+
+ char **p;
+ wl_array_for_each(p, &source->mime_types) {
+ free(*p);
+ }
+ wl_array_release(&source->mime_types);
+
+ // Prevent destructors below from calling this recursively.
+ wl_resource_set_user_data(source->resource, NULL);
+
+ if (source->active_source != NULL) {
+ wlr_data_source_destroy(source->active_source);
+ } else if (source->active_primary_source != NULL) {
+ wlr_primary_selection_source_destroy(
+ source->active_primary_source);
+ }
+
+ free(source);
+}
+
static void source_handle_resource_destroy(struct wl_resource *resource) {
- struct client_data_source *source = source_from_resource(resource);
+ struct data_control_source *source = source_from_resource(resource);
+ data_control_source_destroy(source);
+}
+
+
+struct client_data_source {
+ struct wlr_data_source source;
+ struct wl_resource *resource;
+};
+
+static const struct wlr_data_source_impl client_source_impl;
+
+static struct client_data_source *
+ client_data_source_from_source(struct wlr_data_source *wlr_source) {
+ assert(wlr_source->impl == &client_source_impl);
+ return (struct client_data_source *)wlr_source;
+}
+
+static void client_source_send(struct wlr_data_source *wlr_source,
+ const char *mime_type, int fd) {
+ struct client_data_source *source =
+ client_data_source_from_source(wlr_source);
+ zwlr_data_control_source_v1_send_send(source->resource, mime_type, fd);
+ close(fd);
+}
+
+static void client_source_destroy(struct wlr_data_source *wlr_source) {
+ struct client_data_source *client_source =
+ client_data_source_from_source(wlr_source);
+ struct data_control_source *source =
+ source_from_resource(client_source->resource);
+ free(client_source);
+
if (source == NULL) {
return;
}
- wlr_data_source_destroy(&source->source);
+
+ source->active_source = NULL;
+
+ zwlr_data_control_source_v1_send_cancelled(source->resource);
+ data_control_source_destroy(source);
}
+static const struct wlr_data_source_impl client_source_impl = {
+ .send = client_source_send,
+ .destroy = client_source_destroy,
+};
+
+
+struct client_primary_selection_source {
+ struct wlr_primary_selection_source source;
+ struct wl_resource *resource;
+};
+
+static const struct wlr_primary_selection_source_impl
+client_primary_selection_source_impl;
+
+static struct client_primary_selection_source *
+ client_primary_selection_source_from_source(
+ struct wlr_primary_selection_source *wlr_source) {
+ assert(wlr_source->impl == &client_primary_selection_source_impl);
+ return (struct client_primary_selection_source *)wlr_source;
+}
+
+static void client_primary_selection_source_send(
+ struct wlr_primary_selection_source *wlr_source,
+ const char *mime_type, int fd) {
+ struct client_primary_selection_source *source =
+ client_primary_selection_source_from_source(wlr_source);
+ zwlr_data_control_source_v1_send_send(source->resource, mime_type, fd);
+ close(fd);
+}
+
+static void client_primary_selection_source_destroy(
+ struct wlr_primary_selection_source *wlr_source) {
+ struct client_primary_selection_source *client_source =
+ client_primary_selection_source_from_source(wlr_source);
+ struct data_control_source *source =
+ source_from_resource(client_source->resource);
+ free(client_source);
+
+ if (source == NULL) {
+ return;
+ }
+
+ source->active_primary_source = NULL;
+
+ zwlr_data_control_source_v1_send_cancelled(source->resource);
+ data_control_source_destroy(source);
+}
+
+static const struct wlr_primary_selection_source_impl
+client_primary_selection_source_impl = {
+ .send = client_primary_selection_source_send,
+ .destroy = client_primary_selection_source_destroy,
+};
+
+
+struct data_offer {
+ struct wl_resource *resource;
+ struct wlr_data_control_device_v1 *device;
+ bool is_primary;
+};
+
+static void data_offer_destroy(struct data_offer *offer) {
+ if (offer == NULL) {
+ return;
+ }
+
+ struct wlr_data_control_device_v1 *device = offer->device;
+ if (device != NULL) {
+ if (offer->is_primary) {
+ device->primary_selection_offer_resource = NULL;
+ } else {
+ device->selection_offer_resource = NULL;
+ }
+ }
+
+ wl_resource_set_user_data(offer->resource, NULL);
+ free(offer);
+}
static const struct zwlr_data_control_offer_v1_interface offer_impl;
-static struct wlr_data_control_device_v1 *control_from_offer_resource(
+static struct data_offer *data_offer_from_offer_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource,
&zwlr_data_control_offer_v1_interface, &offer_impl));
@@ -125,12 +239,33 @@ static struct wlr_data_control_device_v1 *control_from_offer_resource(
static void offer_handle_receive(struct wl_client *client,
struct wl_resource *resource, const char *mime_type, int fd) {
- struct wlr_data_control_device_v1 *device = control_from_offer_resource(resource);
- if (device == NULL || device->seat->selection_source == NULL) {
+ struct data_offer *offer = data_offer_from_offer_resource(resource);
+ if (offer == NULL) {
+ close(fd);
+ return;
+ }
+
+ struct wlr_data_control_device_v1 *device = offer->device;
+ if (device == NULL) {
close(fd);
return;
}
- wlr_data_source_send(device->seat->selection_source, mime_type, fd);
+
+ if (offer->is_primary) {
+ if (device->seat->primary_selection_source == NULL) {
+ close(fd);
+ return;
+ }
+ wlr_primary_selection_source_send(
+ device->seat->primary_selection_source,
+ mime_type, fd);
+ } else {
+ if (device->seat->selection_source == NULL) {
+ close(fd);
+ return;
+ }
+ wlr_data_source_send(device->seat->selection_source, mime_type, fd);
+ }
}
static void offer_handle_destroy(struct wl_client *client,
@@ -144,28 +279,39 @@ static const struct zwlr_data_control_offer_v1_interface offer_impl = {
};
static void offer_handle_resource_destroy(struct wl_resource *resource) {
- struct wlr_data_control_device_v1 *device = control_from_offer_resource(resource);
- if (device != NULL) {
- device->selection_offer_resource = NULL;
- }
+ struct data_offer *offer = data_offer_from_offer_resource(resource);
+ data_offer_destroy(offer);
}
static struct wl_resource *create_offer(struct wlr_data_control_device_v1 *device,
- struct wlr_data_source *source) {
+ struct wl_array *mime_types, bool is_primary) {
struct wl_client *client = wl_resource_get_client(device->resource);
+
+ struct data_offer *offer = calloc(1, sizeof(struct data_offer));
+ if (offer == NULL) {
+ wl_client_post_no_memory(client);
+ return NULL;
+ }
+
+ offer->device = device;
+ offer->is_primary = is_primary;
+
uint32_t version = wl_resource_get_version(device->resource);
struct wl_resource *resource = wl_resource_create(client,
&zwlr_data_control_offer_v1_interface, version, 0);
if (resource == NULL) {
return NULL;
}
- wl_resource_set_implementation(resource, &offer_impl, device,
+
+ offer->resource = resource;
+
+ wl_resource_set_implementation(resource, &offer_impl, offer,
offer_handle_resource_destroy);
zwlr_data_control_device_v1_send_data_offer(device->resource, resource);
char **p;
- wl_array_for_each(p, &source->mime_types) {
+ wl_array_for_each(p, mime_types) {
zwlr_data_control_offer_v1_send_offer(resource, *p);
}
@@ -191,16 +337,103 @@ static void control_handle_set_selection(struct wl_client *client,
return;
}
- struct client_data_source *source = NULL;
+ struct data_control_source *source = NULL;
if (source_resource != NULL) {
source = source_from_resource(source_resource);
}
- struct wlr_data_source *wlr_source = source ? &source->source : NULL;
+ if (source == NULL) {
+ wlr_seat_request_set_selection(device->seat, NULL,
+ wl_display_next_serial(device->seat->display));
+
+ return;
+ }
+
+ if (source->active_source != NULL ||
+ source->active_primary_source != NULL) {
+ wl_resource_post_error(control_resource,
+ ZWLR_DATA_CONTROL_DEVICE_V1_ERROR_USED_SOURCE,
+ "cannot use a data source in set_selection or "
+ "set_primary_selection more than once");
+
+ return;
+ }
+
+ struct client_data_source *client_source =
+ calloc(1, sizeof(struct client_data_source));
+ if (client_source == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ client_source->resource = source_resource;
+
+ struct wlr_data_source *wlr_source = &client_source->source;
+ wlr_data_source_init(wlr_source, &client_source_impl);
+ source->active_source = wlr_source;
+
+ wl_array_release(&wlr_source->mime_types);
+ wlr_source->mime_types = source->mime_types;
+ wl_array_init(&source->mime_types);
+
+ source->finalized = true;
+
wlr_seat_request_set_selection(device->seat, wlr_source,
wl_display_next_serial(device->seat->display));
}
+static void control_handle_set_primary_selection(struct wl_client *client,
+ struct wl_resource *control_resource,
+ struct wl_resource *source_resource) {
+ struct wlr_data_control_device_v1 *device =
+ control_from_resource(control_resource);
+ if (device == NULL) {
+ return;
+ }
+
+ struct data_control_source *source = NULL;
+ if (source_resource != NULL) {
+ source = source_from_resource(source_resource);
+ }
+
+ if (source == NULL) {
+ wlr_seat_request_set_primary_selection(device->seat, NULL,
+ wl_display_next_serial(device->seat->display));
+
+ return;
+ }
+
+ if (source->active_source != NULL ||
+ source->active_primary_source != NULL) {
+ wl_resource_post_error(control_resource,
+ ZWLR_DATA_CONTROL_DEVICE_V1_ERROR_USED_SOURCE,
+ "cannot use a data source in set_selection or "
+ "set_primary_selection more than once");
+
+ return;
+ }
+
+ struct client_primary_selection_source *client_source =
+ calloc(1, sizeof(struct client_primary_selection_source));
+ if (client_source == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ client_source->resource = source_resource;
+
+ struct wlr_primary_selection_source *wlr_source = &client_source->source;
+ wlr_primary_selection_source_init(wlr_source, &client_primary_selection_source_impl);
+ source->active_primary_source = wlr_source;
+
+ wl_array_release(&wlr_source->mime_types);
+ wlr_source->mime_types = source->mime_types;
+ wl_array_init(&source->mime_types);
+
+ source->finalized = true;
+
+ wlr_seat_request_set_primary_selection(device->seat, wlr_source,
+ wl_display_next_serial(device->seat->display));
+}
+
static void control_handle_destroy(struct wl_client *client,
struct wl_resource *control_resource) {
wl_resource_destroy(control_resource);
@@ -208,6 +441,7 @@ static void control_handle_destroy(struct wl_client *client,
static const struct zwlr_data_control_device_v1_interface control_impl = {
.set_selection = control_handle_set_selection,
+ .set_primary_selection = control_handle_set_primary_selection,
.destroy = control_handle_destroy,
};
@@ -216,12 +450,15 @@ static void control_send_selection(struct wlr_data_control_device_v1 *device) {
if (device->selection_offer_resource != NULL) {
// Make the offer inert
- wl_resource_set_user_data(device->selection_offer_resource, NULL);
+ struct data_offer *offer = data_offer_from_offer_resource(
+ device->selection_offer_resource);
+ data_offer_destroy(offer);
}
device->selection_offer_resource = NULL;
if (source != NULL) {
- device->selection_offer_resource = create_offer(device, source);
+ device->selection_offer_resource =
+ create_offer(device, &source->mime_types, false);
if (device->selection_offer_resource == NULL) {
wl_resource_post_no_memory(device->resource);
return;
@@ -232,6 +469,37 @@ static void control_send_selection(struct wlr_data_control_device_v1 *device) {
device->selection_offer_resource);
}
+static void control_send_primary_selection(
+ struct wlr_data_control_device_v1 *device) {
+ uint32_t version = wl_resource_get_version(device->resource);
+ if (version < ZWLR_DATA_CONTROL_DEVICE_V1_PRIMARY_SELECTION_SINCE_VERSION) {
+ return;
+ }
+
+ struct wlr_primary_selection_source *source =
+ device->seat->primary_selection_source;
+
+ if (device->primary_selection_offer_resource != NULL) {
+ // Make the offer inert
+ struct data_offer *offer = data_offer_from_offer_resource(
+ device->primary_selection_offer_resource);
+ data_offer_destroy(offer);
+ }
+
+ device->primary_selection_offer_resource = NULL;
+ if (source != NULL) {
+ device->primary_selection_offer_resource =
+ create_offer(device, &source->mime_types, true);
+ if (device->primary_selection_offer_resource == NULL) {
+ wl_resource_post_no_memory(device->resource);
+ return;
+ }
+ }
+
+ zwlr_data_control_device_v1_send_primary_selection(device->resource,
+ device->primary_selection_offer_resource);
+}
+
static void control_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_data_control_device_v1 *device = control_from_resource(resource);
wlr_data_control_device_v1_destroy(device);
@@ -251,6 +519,14 @@ static void control_handle_seat_set_selection(struct wl_listener *listener,
control_send_selection(device);
}
+static void control_handle_seat_set_primary_selection(
+ struct wl_listener *listener,
+ void *data) {
+ struct wlr_data_control_device_v1 *device =
+ wl_container_of(listener, device, seat_set_primary_selection);
+ control_send_primary_selection(device);
+}
+
void wlr_data_control_device_v1_destroy(struct wlr_data_control_device_v1 *device) {
if (device == NULL) {
return;
@@ -259,10 +535,18 @@ void wlr_data_control_device_v1_destroy(struct wlr_data_control_device_v1 *devic
// Make the resources inert
wl_resource_set_user_data(device->resource, NULL);
if (device->selection_offer_resource != NULL) {
- wl_resource_set_user_data(device->selection_offer_resource, NULL);
+ struct data_offer *offer = data_offer_from_offer_resource(
+ device->selection_offer_resource);
+ data_offer_destroy(offer);
+ }
+ if (device->primary_selection_offer_resource != NULL) {
+ struct data_offer *offer = data_offer_from_offer_resource(
+ device->primary_selection_offer_resource);
+ data_offer_destroy(offer);
}
wl_list_remove(&device->seat_destroy.link);
wl_list_remove(&device->seat_set_selection.link);
+ wl_list_remove(&device->seat_set_primary_selection.link);
wl_list_remove(&device->link);
free(device);
}
@@ -279,19 +563,21 @@ static struct wlr_data_control_manager_v1 *manager_from_resource(
static void manager_handle_create_data_source(struct wl_client *client,
struct wl_resource *manager_resource, uint32_t id) {
- struct client_data_source *source =
- calloc(1, sizeof(struct client_data_source));
+ struct data_control_source *source =
+ calloc(1, sizeof(struct data_control_source));
if (source == NULL) {
wl_resource_post_no_memory(manager_resource);
return;
}
- wlr_data_source_init(&source->source, &client_source_impl);
+
+ wl_array_init(&source->mime_types);
uint32_t version = wl_resource_get_version(manager_resource);
source->resource = wl_resource_create(client,
&zwlr_data_control_source_v1_interface, version, id);
if (source->resource == NULL) {
wl_resource_post_no_memory(manager_resource);
+ wl_array_release(&source->mime_types);
free(source);
return;
}
@@ -335,6 +621,11 @@ static void manager_handle_get_data_device(struct wl_client *client,
wl_signal_add(&device->seat->events.set_selection,
&device->seat_set_selection);
+ device->seat_set_primary_selection.notify =
+ control_handle_seat_set_primary_selection;
+ wl_signal_add(&device->seat->events.set_primary_selection,
+ &device->seat_set_primary_selection);
+
wl_list_insert(&manager->devices, &device->link);
wlr_signal_emit_safe(&manager->events.new_device, device);
@@ -343,6 +634,7 @@ static void manager_handle_get_data_device(struct wl_client *client,
device = control_from_resource(resource);
if (device != NULL) {
control_send_selection(device);
+ control_send_primary_selection(device);
}
}
@@ -375,6 +667,10 @@ static void manager_bind(struct wl_client *client, void *data, uint32_t version,
manager_handle_resource_destroy);
wl_list_insert(&manager->resources, wl_resource_get_link(resource));
+
+ if (version >= ZWLR_DATA_CONTROL_MANAGER_V1_PRIMARY_SELECTION_SINCE_VERSION) {
+ zwlr_data_control_manager_v1_send_primary_selection(resource);
+ }
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
@@ -396,8 +692,8 @@ struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1_create(
wl_signal_init(&manager->events.new_device);
manager->global = wl_global_create(display,
- &zwlr_data_control_manager_v1_interface, DATA_CONTROL_MANAGER_VERSION,
- manager, manager_bind);
+ &zwlr_data_control_manager_v1_interface,
+ DATA_CONTROL_MANAGER_VERSION, manager, manager_bind);
if (manager->global == NULL) {
free(manager);
return NULL;