2 * Copyright © 2012 Intel Corporation
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 #include <linux/input.h>
32 #include "compositor.h"
34 struct clipboard_source {
35 struct weston_data_source base;
36 struct wl_array contents;
37 struct clipboard *clipboard;
38 struct wl_event_source *event_source;
45 struct weston_seat *seat;
46 struct wl_listener selection_listener;
47 struct wl_listener destroy_listener;
48 struct clipboard_source *source;
51 static void clipboard_client_create(struct clipboard_source *source, int fd);
54 clipboard_source_unref(struct clipboard_source *source)
59 if (source->refcount > 0)
62 if (source->event_source) {
63 wl_event_source_remove(source->event_source);
66 wl_signal_emit(&source->base.destroy_signal,
68 s = source->base.mime_types.data;
70 wl_array_release(&source->base.mime_types);
71 wl_array_release(&source->contents);
76 clipboard_source_data(int fd, uint32_t mask, void *data)
78 struct clipboard_source *source = data;
79 struct clipboard *clipboard = source->clipboard;
83 if (source->contents.alloc - source->contents.size < 1024) {
84 wl_array_add(&source->contents, 1024);
85 source->contents.size -= 1024;
88 p = source->contents.data + source->contents.size;
89 size = source->contents.alloc - source->contents.size;
90 len = read(fd, p, size);
92 wl_event_source_remove(source->event_source);
94 source->event_source = NULL;
96 clipboard_source_unref(source);
97 clipboard->source = NULL;
99 source->contents.size += len;
106 clipboard_source_accept(struct weston_data_source *source,
107 uint32_t time, const char *mime_type)
112 clipboard_source_send(struct weston_data_source *base,
113 const char *mime_type, int32_t fd)
115 struct clipboard_source *source =
116 container_of(base, struct clipboard_source, base);
119 s = source->base.mime_types.data;
120 if (strcmp(mime_type, s[0]) == 0)
121 clipboard_client_create(source, fd);
127 clipboard_source_cancel(struct weston_data_source *source)
131 static struct clipboard_source *
132 clipboard_source_create(struct clipboard *clipboard,
133 const char *mime_type, uint32_t serial, int fd)
135 struct wl_display *display = clipboard->seat->compositor->wl_display;
136 struct wl_event_loop *loop = wl_display_get_event_loop(display);
137 struct clipboard_source *source;
140 source = malloc(sizeof *source);
144 wl_array_init(&source->contents);
145 wl_array_init(&source->base.mime_types);
146 source->base.resource = NULL;
147 source->base.accept = clipboard_source_accept;
148 source->base.send = clipboard_source_send;
149 source->base.cancel = clipboard_source_cancel;
150 wl_signal_init(&source->base.destroy_signal);
151 source->refcount = 1;
152 source->clipboard = clipboard;
153 source->serial = serial;
155 s = wl_array_add(&source->base.mime_types, sizeof *s);
158 *s = strdup(mime_type);
161 source->event_source =
162 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
163 clipboard_source_data, source);
164 if (source->event_source == NULL)
172 wl_array_release(&source->base.mime_types);
179 struct clipboard_client {
180 struct wl_event_source *event_source;
182 struct clipboard_source *source;
186 clipboard_client_data(int fd, uint32_t mask, void *data)
188 struct clipboard_client *client = data;
193 size = client->source->contents.size;
194 p = client->source->contents.data;
195 len = write(fd, p + client->offset, size - client->offset);
197 client->offset += len;
199 if (client->offset == size || len <= 0) {
201 wl_event_source_remove(client->event_source);
202 clipboard_source_unref(client->source);
210 clipboard_client_create(struct clipboard_source *source, int fd)
212 struct weston_seat *seat = source->clipboard->seat;
213 struct clipboard_client *client;
214 struct wl_event_loop *loop =
215 wl_display_get_event_loop(seat->compositor->wl_display);
217 client = malloc(sizeof *client);
220 client->source = source;
222 client->event_source =
223 wl_event_loop_add_fd(loop, fd, WL_EVENT_WRITABLE,
224 clipboard_client_data, client);
228 clipboard_set_selection(struct wl_listener *listener, void *data)
230 struct clipboard *clipboard =
231 container_of(listener, struct clipboard, selection_listener);
232 struct weston_seat *seat = data;
233 struct weston_data_source *source = seat->selection_data_source;
234 const char **mime_types;
237 if (source == NULL) {
238 if (clipboard->source)
239 weston_seat_set_selection(seat,
240 &clipboard->source->base,
241 clipboard->source->serial);
243 } else if (source->accept == clipboard_source_accept) {
244 /* Callback for our data source. */
248 if (clipboard->source)
249 clipboard_source_unref(clipboard->source);
251 clipboard->source = NULL;
253 mime_types = source->mime_types.data;
255 if (pipe2(p, O_CLOEXEC) == -1)
258 source->send(source, mime_types[0], p[1]);
261 clipboard_source_create(clipboard, mime_types[0],
262 seat->selection_serial, p[0]);
263 if (clipboard->source == NULL) {
270 clipboard_destroy(struct wl_listener *listener, void *data)
272 struct clipboard *clipboard =
273 container_of(listener, struct clipboard, destroy_listener);
275 wl_list_remove(&clipboard->selection_listener.link);
276 wl_list_remove(&clipboard->destroy_listener.link);
282 clipboard_create(struct weston_seat *seat)
284 struct clipboard *clipboard;
286 clipboard = zalloc(sizeof *clipboard);
287 if (clipboard == NULL)
290 clipboard->seat = seat;
291 clipboard->selection_listener.notify = clipboard_set_selection;
292 clipboard->destroy_listener.notify = clipboard_destroy;
294 wl_signal_add(&seat->selection_signal,
295 &clipboard->selection_listener);
296 wl_signal_add(&seat->destroy_signal,
297 &clipboard->destroy_listener);