commit ba0d051
Michael Forney
·
2013-07-01 11:37:34 +0000 UTC
parent 7c074d1
Implement copy and paste (data_{device{,_manager},source,offer})
+1,
-0
1@@ -19,6 +19,7 @@ libswc_la_SOURCES = \
2 seat.c seat.h \
3 data_device_manager.c data_device_manager.h \
4 data_device.c data_device.h \
5+ data.c data.h \
6 mode.c mode.h \
7 tty.c tty.h \
8 evdev_device.c evdev_device.h \
A
data.c
+174,
-0
1@@ -0,0 +1,174 @@
2+/* swc: data.c
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#include "data.h"
26+#include "util.h"
27+
28+#include <stdlib.h>
29+#include <string.h>
30+
31+struct data
32+{
33+ struct wl_array mime_types;
34+ struct wl_resource * source;
35+ struct wl_list offers;
36+};
37+
38+static void offer_accept(struct wl_client * client,
39+ struct wl_resource * offer,
40+ uint32_t serial, const char * mime_type)
41+{
42+ struct data * data = wl_resource_get_user_data(offer);
43+
44+ /* Protect against expired data_offers being used. */
45+ if (data)
46+ wl_data_source_send_target(data->source, mime_type);
47+}
48+
49+static void offer_receive(struct wl_client * client,
50+ struct wl_resource * offer,
51+ const char * mime_type, int fd)
52+{
53+ struct data * data = wl_resource_get_user_data(offer);
54+
55+ /* Protect against expired data_offers being used. */
56+ if (data)
57+ wl_data_source_send_send(data->source, mime_type, fd);
58+}
59+
60+static void offer_destroy(struct wl_client * client,
61+ struct wl_resource * offer)
62+{
63+ wl_resource_destroy(offer);
64+}
65+
66+struct wl_data_offer_interface data_offer_implementation = {
67+ .accept = &offer_accept,
68+ .receive = &offer_receive,
69+ .destroy = &offer_destroy
70+};
71+
72+static void source_offer(struct wl_client * client,
73+ struct wl_resource * source,
74+ const char * mime_type)
75+{
76+ struct data * data = wl_resource_get_user_data(source);
77+ char ** destination;
78+
79+ destination = wl_array_add(&data->mime_types, sizeof *destination);
80+ *destination = strdup(mime_type);
81+}
82+
83+static void source_destroy(struct wl_client * client,
84+ struct wl_resource * source)
85+{
86+ wl_resource_destroy(source);
87+}
88+
89+struct wl_data_source_interface data_source_implementation = {
90+ .offer = &source_offer,
91+ .destroy = &source_destroy
92+};
93+
94+static void data_destroy(struct wl_resource * source)
95+{
96+ struct data * data = wl_resource_get_user_data(source);
97+ struct wl_resource * offer;
98+ char ** mime_type;
99+
100+ wl_array_for_each(mime_type, &data->mime_types)
101+ free(*mime_type);
102+ wl_array_release(&data->mime_types);
103+
104+ /* After this data_source is destroyed, each of the data_offer objects
105+ * associated with the data_source has a pointer to a free'd struct. We
106+ * can't destroy the resources because this results in a segfault on the
107+ * client when it correctly tries to call data_source.destroy. However, a
108+ * misbehaving client could still attempt to call accept or receive on the
109+ * data_offer, which would crash the server.
110+ *
111+ * So, we clear the user data on each of the offers to protect us. */
112+ wl_list_for_each(offer, &data->offers, link)
113+ wl_resource_set_user_data(offer, NULL);
114+
115+ free(data);
116+}
117+
118+static struct data * data_new()
119+{
120+ struct data * data;
121+
122+ data = malloc(sizeof *data);
123+
124+ if (!data)
125+ return NULL;
126+
127+ wl_array_init(&data->mime_types);
128+ wl_list_init(&data->offers);
129+
130+ return data;
131+}
132+
133+struct wl_resource * swc_data_source_new(struct wl_client * client, uint32_t id)
134+{
135+ struct data * data;
136+
137+ data = data_new();
138+
139+ if (!data)
140+ return NULL;
141+
142+ /* Add the data source to the client. */
143+ data->source = wl_client_add_object(client, &wl_data_source_interface,
144+ &data_source_implementation, id, data);
145+
146+ /* Destroy the data object when the source disappears. */
147+ wl_resource_set_destructor(data->source, &data_destroy);
148+
149+ return data->source;
150+}
151+
152+struct wl_resource * swc_data_offer_new(struct wl_client * client,
153+ struct wl_resource * source)
154+{
155+ struct data * data = wl_resource_get_user_data(source);
156+ struct wl_resource * offer;
157+
158+ offer = wl_client_new_object(client, &wl_data_offer_interface,
159+ &data_offer_implementation, data);
160+ wl_list_insert(&data->offers, wl_resource_get_link(offer));
161+ wl_resource_set_destructor(offer, &swc_remove_resource);
162+
163+ return offer;
164+}
165+
166+void swc_data_send_mime_types(struct wl_resource * source,
167+ struct wl_resource * offer)
168+{
169+ struct data * data = wl_resource_get_user_data(source);
170+ char ** mime_type;
171+
172+ wl_array_for_each(mime_type, &data->mime_types)
173+ wl_data_offer_send_offer(offer, *mime_type);
174+}
175+
A
data.h
+39,
-0
1@@ -0,0 +1,39 @@
2+/* swc: data.h
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#ifndef SWC_DATA_H
26+#define SWC_DATA_H 1
27+
28+#include <wayland-server.h>
29+
30+struct wl_resource * swc_data_source_new(struct wl_client * client,
31+ uint32_t id);
32+
33+struct wl_resource * swc_data_offer_new(struct wl_client * client,
34+ struct wl_resource * source);
35+
36+void swc_data_send_mime_types(struct wl_resource * source,
37+ struct wl_resource * offer);
38+
39+#endif
40+
+121,
-4
1@@ -1,16 +1,66 @@
2+/* swc: data_device.c
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25 #include "data_device.h"
26+#include "data.h"
27+#include "util.h"
28
29 static void start_drag(struct wl_client * client, struct wl_resource * resource,
30 struct wl_resource * source_resource,
31 struct wl_resource * origin_resource,
32 struct wl_resource * icon_resource, uint32_t serial)
33 {
34+ /* XXX: Implement */
35 }
36
37 static void set_selection(struct wl_client * client,
38 struct wl_resource * resource,
39- struct wl_resource * source_resource, uint32_t serial)
40+ struct wl_resource * data_source, uint32_t serial)
41 {
42+ struct swc_data_device * data_device = wl_resource_get_user_data(resource);
43+ struct swc_event event;
44+
45+ /* Check if this data source is already the current selection. */
46+ if (data_source == data_device->selection)
47+ return;
48+
49+ event.type = SWC_DATA_DEVICE_EVENT_SELECTION_CHANGED;
50+
51+ if (data_device->selection)
52+ {
53+ wl_data_source_send_cancelled(data_device->selection);
54+ wl_list_remove(&data_device->selection_destroy_listener.link);
55+ }
56+
57+ data_device->selection = data_source;
58+
59+ if (data_source)
60+ {
61+ wl_resource_add_destroy_listener
62+ (data_source, &data_device->selection_destroy_listener);
63+ }
64+
65+ wl_signal_emit(&data_device->event_signal, &event);
66 }
67
68 struct wl_data_device_interface data_device_implementation = {
69@@ -18,9 +68,76 @@ struct wl_data_device_interface data_device_implementation = {
70 .set_selection = &set_selection
71 };
72
73-void swc_data_device_new(struct wl_client * client, uint32_t id)
74+static void handle_selection_destroy(struct wl_listener * listener, void * data)
75+{
76+ struct swc_data_device * data_device
77+ = wl_container_of(listener, data_device, selection_destroy_listener);
78+ struct swc_event event;
79+
80+ event.type = SWC_DATA_DEVICE_EVENT_SELECTION_CHANGED;
81+ data_device->selection = NULL;
82+ wl_signal_emit(&data_device->event_signal, &event);
83+}
84+
85+bool swc_data_device_initialize(struct swc_data_device * data_device)
86+{
87+ data_device->selection_destroy_listener.notify = &handle_selection_destroy;
88+ wl_signal_init(&data_device->event_signal);
89+ wl_list_init(&data_device->resources);
90+
91+ return true;
92+}
93+
94+void swc_data_device_finish(struct swc_data_device * data_device)
95+{
96+ struct wl_resource * resource, * tmp;
97+
98+ wl_list_for_each_safe(resource, tmp, &data_device->resources, link)
99+ wl_resource_destroy(resource);
100+}
101+
102+void swc_data_device_bind(struct swc_data_device * data_device,
103+ struct wl_client * client, uint32_t id)
104+{
105+ struct wl_resource * resource;
106+
107+ resource = wl_client_add_object(client, &wl_data_device_interface,
108+ &data_device_implementation, id,
109+ data_device);
110+ wl_list_insert(&data_device->resources, &resource->link);
111+ wl_resource_set_destructor(resource, &swc_remove_resource);
112+}
113+
114+static struct wl_resource * new_offer(struct wl_resource * resource,
115+ struct wl_client * client,
116+ struct wl_resource * source)
117+{
118+ struct wl_resource * offer;
119+
120+ offer = swc_data_offer_new(client, source);
121+ wl_data_device_send_data_offer(resource, offer);
122+ swc_data_send_mime_types(source, offer);
123+
124+ return offer;
125+}
126+
127+void swc_data_device_offer_selection(struct swc_data_device * data_device,
128+ struct wl_client * client)
129 {
130- wl_client_add_object(client, &wl_data_device_interface,
131- &data_device_implementation, id, NULL);
132+ struct wl_resource * resource;
133+ struct wl_resource * offer;
134+
135+ /* Look for the client's data_device resource. */
136+ resource = wl_resource_find_for_client(&data_device->resources, client);
137+
138+ /* If the client does not have a data device, there is nothing to do. */
139+ if (!resource)
140+ return;
141+
142+ /* If we don't have a selection, send NULL to the client. */
143+ offer = data_device->selection
144+ ? new_offer(resource, client, data_device->selection) : NULL;
145+
146+ wl_data_device_send_selection(resource, offer);
147 }
148
+49,
-1
1@@ -1,9 +1,57 @@
2+/* swc: data_device.h
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25 #ifndef SWC_DATA_DEVICE_H
26 #define SWC_DATA_DEVICE_H 1
27
28+#include "event.h"
29+
30+#include <stdbool.h>
31 #include <wayland-server.h>
32
33-void swc_data_device_new(struct wl_client * client, uint32_t id);
34+enum swc_data_device_event_type
35+{
36+ SWC_DATA_DEVICE_EVENT_SELECTION_CHANGED
37+};
38+
39+struct swc_data_device
40+{
41+ /* The data source corresponding to the current selection. */
42+ struct wl_resource * selection;
43+ struct wl_listener selection_destroy_listener;
44+
45+ struct wl_signal event_signal;
46+ struct wl_list resources;
47+};
48+
49+bool swc_data_device_initialize(struct swc_data_device * data_device);
50+void swc_data_device_finish(struct swc_data_device * data_device);
51+
52+void swc_data_device_bind(struct swc_data_device * data_device,
53+ struct wl_client * client, uint32_t id);
54+
55+void swc_data_device_offer_selection(struct swc_data_device * data_device,
56+ struct wl_client * client);
57
58 #endif
59
+33,
-5
1@@ -1,11 +1,40 @@
2+/* swc: data_device_manager.c
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25 #include "data_device_manager.h"
26 #include "data_device.h"
27-
28-#include <stdio.h>
29+#include "data.h"
30+#include "seat.h"
31
32 static void create_data_source(struct wl_client * client,
33 struct wl_resource * resource, uint32_t id)
34 {
35+ struct wl_resource * data_source;
36+
37+ data_source = swc_data_source_new(client, id);
38+
39+ if (!data_source)
40+ wl_resource_post_no_memory(resource);
41 }
42
43 static void get_data_device(struct wl_client * client,
44@@ -14,10 +43,9 @@ static void get_data_device(struct wl_client * client,
45 {
46 struct swc_seat * seat = wl_resource_get_user_data(seat_resource);
47
48- printf("get_data_device\n");
49+ printf("data_device_manager.get_data_device\n");
50
51- // TODO: keep track of resource?
52- swc_data_device_new(client, id);
53+ swc_data_device_bind(&seat->data_device, client, id);
54 }
55
56 static struct wl_data_device_manager_interface
+23,
-0
1@@ -1,3 +1,26 @@
2+/* swc: data_device_manager.h
3+ *
4+ * Copyright (c) 2013 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25 #ifndef SWC_DATA_DEVICE_MANAGER_H
26 #define SWC_DATA_DEVICE_MANAGER_H 1
27
M
seat.c
+56,
-0
1@@ -156,6 +156,48 @@ static void handle_evdev_event(struct wl_listener * listener, void * data)
2 }
3 }
4
5+static void handle_keyboard_focus_event(struct wl_listener * listener,
6+ void * data)
7+{
8+ struct swc_seat * seat
9+ = wl_container_of(listener, seat, keyboard_focus_listener);
10+ struct swc_event * event = data;
11+ struct swc_input_focus_event_data * event_data = event->data;
12+
13+ switch (event->type)
14+ {
15+ case SWC_INPUT_FOCUS_EVENT_CHANGED:
16+ if (event_data->new)
17+ {
18+ struct wl_client * client
19+ = wl_resource_get_client(event_data->new->resource);
20+
21+ /* Offer the selection to the new focus. */
22+ swc_data_device_offer_selection(&seat->data_device, client);
23+ }
24+ break;
25+ }
26+}
27+
28+static void handle_data_device_event(struct wl_listener * listener, void * data)
29+{
30+ struct swc_seat * seat
31+ = wl_container_of(listener, seat, data_device_listener);
32+ struct swc_event * event = data;
33+
34+ switch (event->type)
35+ {
36+ case SWC_DATA_DEVICE_EVENT_SELECTION_CHANGED:
37+ if (seat->keyboard.focus.resource)
38+ {
39+ struct wl_client * client
40+ = wl_resource_get_client(seat->keyboard.focus.resource);
41+ swc_data_device_offer_selection(&seat->data_device, client);
42+ }
43+ break;
44+ }
45+}
46+
47 /* Wayland Seat Interface */
48 static void get_pointer(struct wl_client * client, struct wl_resource * resource,
49 uint32_t id)
50@@ -260,6 +302,8 @@ static void add_device(struct swc_seat * seat, struct udev_device * udev_device)
51 {
52 printf("initializing keyboard\n");
53 swc_keyboard_initialize(&seat->keyboard);
54+ wl_signal_add(&seat->keyboard.focus.event_signal,
55+ &seat->keyboard_focus_listener);
56 seat->capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
57 update_capabilities(seat);
58 }
59@@ -274,6 +318,8 @@ bool swc_seat_initialize(struct swc_seat * seat, struct udev * udev,
60 {
61 seat->name = strdup(seat_name);
62 seat->capabilities = 0;
63+ seat->keyboard_focus_listener.notify = &handle_keyboard_focus_event;
64+ seat->data_device_listener.notify = &handle_data_device_event;
65
66 if (!swc_xkb_initialize(&seat->xkb))
67 {
68@@ -281,6 +327,14 @@ bool swc_seat_initialize(struct swc_seat * seat, struct udev * udev,
69 goto error_name;
70 }
71
72+ if (!swc_data_device_initialize(&seat->data_device))
73+ {
74+ printf("could not initialize data device\n");
75+ goto error_xkb;
76+ }
77+
78+ wl_signal_add(&seat->data_device.event_signal, &seat->data_device_listener);
79+
80 wl_list_init(&seat->resources);
81 wl_signal_init(&seat->destroy_signal);
82 wl_list_init(&seat->devices);
83@@ -288,6 +342,8 @@ bool swc_seat_initialize(struct swc_seat * seat, struct udev * udev,
84
85 return true;
86
87+ error_xkb:
88+ swc_xkb_finish(&seat->xkb);
89 error_name:
90 free(seat->name);
91 error_base:
M
seat.h
+6,
-0
1@@ -2,6 +2,7 @@
2 #define SWC_SEAT_H 1
3
4 #include "xkb.h"
5+#include "data_device.h"
6 #include "keyboard.h"
7 #include "pointer.h"
8
9@@ -20,7 +21,12 @@ struct swc_seat
10 struct wl_list resources;
11 struct wl_signal destroy_signal;
12
13+ struct swc_data_device data_device;
14+ struct wl_listener data_device_listener;
15+
16 struct swc_keyboard keyboard;
17+ struct wl_listener keyboard_focus_listener;
18+
19 struct swc_pointer pointer;
20
21 struct wl_list devices;