1 /*
2 * Copyright © 2011 Kristian Høgsberg
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23 /* The file is based on src/data-device.c from Weston */
24
25 #include "config.h"
26
27 #include "wayland/meta-wayland-data-device-primary-legacy.h"
28
29 #include "compositor/meta-dnd-actor-private.h"
30 #include "meta/meta-selection-source-memory.h"
31 #include "wayland/meta-selection-source-wayland-private.h"
32 #include "wayland/meta-wayland-data-offer-primary-legacy.h"
33 #include "wayland/meta-wayland-data-source-primary-legacy.h"
34 #include "wayland/meta-wayland-dnd-surface.h"
35 #include "wayland/meta-wayland-pointer.h"
36 #include "wayland/meta-wayland-private.h"
37 #include "wayland/meta-wayland-seat.h"
38
39 #include "gtk-primary-selection-server-protocol.h"
40
41 static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevicePrimaryLegacy *data_device,
42 struct wl_resource *target);
43
44 static void
move_resources(struct wl_list * destination,struct wl_list * source)45 move_resources (struct wl_list *destination,
46 struct wl_list *source)
47 {
48 wl_list_insert_list (destination, source);
49 wl_list_init (source);
50 }
51
52 static void
move_resources_for_client(struct wl_list * destination,struct wl_list * source,struct wl_client * client)53 move_resources_for_client (struct wl_list *destination,
54 struct wl_list *source,
55 struct wl_client *client)
56 {
57 struct wl_resource *resource, *tmp;
58 wl_resource_for_each_safe (resource, tmp, source)
59 {
60 if (wl_resource_get_client (resource) == client)
61 {
62 wl_list_remove (wl_resource_get_link (resource));
63 wl_list_insert (destination, wl_resource_get_link (resource));
64 }
65 }
66 }
67
68 static void
unbind_resource(struct wl_resource * resource)69 unbind_resource (struct wl_resource *resource)
70 {
71 wl_list_remove (wl_resource_get_link (resource));
72 }
73
74 static void
default_destructor(struct wl_client * client,struct wl_resource * resource)75 default_destructor (struct wl_client *client,
76 struct wl_resource *resource)
77 {
78 wl_resource_destroy (resource);
79 }
80
81 static void
set_selection_source(MetaWaylandDataDevicePrimaryLegacy * data_device,MetaSelectionSource * selection_source)82 set_selection_source (MetaWaylandDataDevicePrimaryLegacy *data_device,
83 MetaSelectionSource *selection_source)
84
85 {
86 MetaDisplay *display = meta_get_display ();
87
88 meta_selection_set_owner (meta_display_get_selection (display),
89 META_SELECTION_PRIMARY,
90 selection_source);
91 g_set_object (&data_device->owner, selection_source);
92 }
93
94 static void
unset_selection_source(MetaWaylandDataDevicePrimaryLegacy * data_device)95 unset_selection_source (MetaWaylandDataDevicePrimaryLegacy *data_device)
96 {
97 MetaDisplay *display = meta_get_display ();
98
99 if (!data_device->owner)
100 return;
101
102 meta_selection_unset_owner (meta_display_get_selection (display),
103 META_SELECTION_PRIMARY,
104 data_device->owner);
105 g_clear_object (&data_device->owner);
106 }
107
108 static void
primary_source_destroyed(gpointer data,GObject * object_was_here)109 primary_source_destroyed (gpointer data,
110 GObject *object_was_here)
111 {
112 MetaWaylandDataDevicePrimaryLegacy *data_device = data;
113
114 data_device->data_source = NULL;
115 unset_selection_source (data_device);
116 }
117
118 static void
meta_wayland_data_device_primary_legacy_set_selection(MetaWaylandDataDevicePrimaryLegacy * data_device,MetaWaylandDataSource * source,uint32_t serial)119 meta_wayland_data_device_primary_legacy_set_selection (MetaWaylandDataDevicePrimaryLegacy *data_device,
120 MetaWaylandDataSource *source,
121 uint32_t serial)
122 {
123 MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device);
124 MetaSelectionSource *selection_source;
125
126 g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY (source));
127
128 if (data_device->data_source &&
129 data_device->serial - serial < UINT32_MAX / 2)
130 return;
131
132 if (data_device->data_source)
133 {
134 g_object_weak_unref (G_OBJECT (data_device->data_source),
135 primary_source_destroyed,
136 data_device);
137 }
138
139 data_device->data_source = source;
140 data_device->serial = serial;
141
142 if (source)
143 {
144 meta_wayland_data_source_set_seat (source, seat);
145 g_object_weak_ref (G_OBJECT (source),
146 primary_source_destroyed,
147 data_device);
148
149 selection_source = meta_selection_source_wayland_new (source);
150 }
151 else
152 {
153 selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
154 }
155
156 set_selection_source (data_device, selection_source);
157 g_object_unref (selection_source);
158 }
159
160 static void
primary_device_set_selection(struct wl_client * client,struct wl_resource * resource,struct wl_resource * source_resource,uint32_t serial)161 primary_device_set_selection (struct wl_client *client,
162 struct wl_resource *resource,
163 struct wl_resource *source_resource,
164 uint32_t serial)
165 {
166 MetaWaylandDataDevicePrimaryLegacy *data_device = wl_resource_get_user_data (resource);
167 MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device);
168 MetaWaylandDataSource *source = NULL;
169
170 if (source_resource)
171 source = wl_resource_get_user_data (source_resource);
172
173 if (wl_resource_get_client (resource) !=
174 meta_wayland_keyboard_get_focus_client (seat->keyboard))
175 {
176 if (source)
177 meta_wayland_data_source_cancel (source);
178 return;
179 }
180
181 meta_wayland_data_device_primary_legacy_set_selection (data_device, source, serial);
182 }
183
184 static const struct gtk_primary_selection_device_interface primary_device_interface = {
185 primary_device_set_selection,
186 default_destructor,
187 };
188
189 static void
owner_changed_cb(MetaSelection * selection,MetaSelectionType selection_type,MetaSelectionSource * new_owner,MetaWaylandDataDevicePrimaryLegacy * data_device)190 owner_changed_cb (MetaSelection *selection,
191 MetaSelectionType selection_type,
192 MetaSelectionSource *new_owner,
193 MetaWaylandDataDevicePrimaryLegacy *data_device)
194 {
195 MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
196 MetaWaylandSeat *seat = compositor->seat;
197 struct wl_resource *data_device_resource;
198 struct wl_client *focus_client;
199
200 focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
201 if (!focus_client)
202 return;
203
204 if (selection_type == META_SELECTION_PRIMARY)
205 {
206 wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
207 {
208 struct wl_resource *offer = NULL;
209
210 if (new_owner)
211 {
212 offer = create_and_send_primary_offer (data_device,
213 data_device_resource);
214 }
215
216 gtk_primary_selection_device_send_selection (data_device_resource,
217 offer);
218 }
219 }
220 }
221
222 static void
ensure_owners_changed_handler_connected(MetaWaylandDataDevicePrimaryLegacy * data_device)223 ensure_owners_changed_handler_connected (MetaWaylandDataDevicePrimaryLegacy *data_device)
224 {
225 if (data_device->selection_owner_signal_id != 0)
226 return;
227
228 data_device->selection_owner_signal_id =
229 g_signal_connect (meta_display_get_selection (meta_get_display ()),
230 "owner-changed",
231 G_CALLBACK (owner_changed_cb), data_device);
232 }
233
234 static void
primary_device_manager_create_source(struct wl_client * client,struct wl_resource * manager_resource,guint32 id)235 primary_device_manager_create_source (struct wl_client *client,
236 struct wl_resource *manager_resource,
237 guint32 id)
238 {
239 struct wl_resource *source_resource;
240
241 source_resource =
242 wl_resource_create (client, >k_primary_selection_source_interface,
243 wl_resource_get_version (manager_resource),
244 id);
245 meta_wayland_data_source_primary_legacy_new (source_resource);
246 }
247
248 static void
primary_device_manager_get_device(struct wl_client * client,struct wl_resource * manager_resource,guint32 id,struct wl_resource * seat_resource)249 primary_device_manager_get_device (struct wl_client *client,
250 struct wl_resource *manager_resource,
251 guint32 id,
252 struct wl_resource *seat_resource)
253 {
254 MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
255 struct wl_resource *cr;
256
257 cr = wl_resource_create (client, >k_primary_selection_device_interface,
258 wl_resource_get_version (manager_resource), id);
259 wl_resource_set_implementation (cr, &primary_device_interface,
260 &seat->primary_legacy_data_device, unbind_resource);
261 wl_list_insert (&seat->primary_legacy_data_device.resource_list,
262 wl_resource_get_link (cr));
263
264 ensure_owners_changed_handler_connected (&seat->primary_legacy_data_device);
265 }
266
267 static const struct gtk_primary_selection_device_manager_interface primary_manager_interface = {
268 primary_device_manager_create_source,
269 primary_device_manager_get_device,
270 default_destructor,
271 };
272
273 static void
bind_primary_manager(struct wl_client * client,void * data,uint32_t version,uint32_t id)274 bind_primary_manager (struct wl_client *client,
275 void *data,
276 uint32_t version,
277 uint32_t id)
278 {
279 struct wl_resource *resource;
280
281 resource = wl_resource_create (client, >k_primary_selection_device_manager_interface,
282 version, id);
283 wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL);
284 }
285
286 void
meta_wayland_data_device_primary_legacy_manager_init(MetaWaylandCompositor * compositor)287 meta_wayland_data_device_primary_legacy_manager_init (MetaWaylandCompositor *compositor)
288 {
289 if (wl_global_create (compositor->wayland_display,
290 >k_primary_selection_device_manager_interface,
291 META_GTK_PRIMARY_SELECTION_VERSION,
292 NULL, bind_primary_manager) == NULL)
293 g_error ("Could not create data_device");
294 }
295
296 void
meta_wayland_data_device_primary_legacy_init(MetaWaylandDataDevicePrimaryLegacy * data_device)297 meta_wayland_data_device_primary_legacy_init (MetaWaylandDataDevicePrimaryLegacy *data_device)
298 {
299 wl_list_init (&data_device->resource_list);
300 wl_list_init (&data_device->focus_resource_list);
301 }
302
303 static struct wl_resource *
create_and_send_primary_offer(MetaWaylandDataDevicePrimaryLegacy * data_device,struct wl_resource * target)304 create_and_send_primary_offer (MetaWaylandDataDevicePrimaryLegacy *data_device,
305 struct wl_resource *target)
306 {
307 MetaWaylandDataOffer *offer;
308 MetaDisplay *display = meta_get_display ();
309 struct wl_resource *resource;
310 GList *mimetypes, *l;
311
312 mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display),
313 META_SELECTION_PRIMARY);
314 if (!mimetypes)
315 return NULL;
316
317 offer = meta_wayland_data_offer_primary_legacy_new (target);
318 resource = meta_wayland_data_offer_get_resource (offer);
319
320 gtk_primary_selection_device_send_data_offer (target, resource);
321
322 for (l = mimetypes; l; l = l->next)
323 gtk_primary_selection_offer_send_offer (resource, l->data);
324
325 g_list_free_full (mimetypes, g_free);
326
327 return resource;
328 }
329
330 void
meta_wayland_data_device_primary_legacy_set_keyboard_focus(MetaWaylandDataDevicePrimaryLegacy * data_device)331 meta_wayland_data_device_primary_legacy_set_keyboard_focus (MetaWaylandDataDevicePrimaryLegacy *data_device)
332 {
333 MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device);
334 struct wl_client *focus_client;
335 struct wl_resource *data_device_resource;
336
337 focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
338
339 if (focus_client == data_device->focus_client)
340 return;
341
342 data_device->focus_client = focus_client;
343 move_resources (&data_device->resource_list,
344 &data_device->focus_resource_list);
345
346 if (!focus_client)
347 return;
348
349 move_resources_for_client (&data_device->focus_resource_list,
350 &data_device->resource_list,
351 focus_client);
352
353 wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
354 {
355 struct wl_resource *offer;
356 offer = create_and_send_primary_offer (data_device, data_device_resource);
357 gtk_primary_selection_device_send_selection (data_device_resource, offer);
358 }
359 }
360