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 wl_data_source base;
36 struct wl_array contents;
37 struct clipboard *clipboard;
38 struct wl_event_source *event_source;
44 struct weston_seat *seat;
45 struct wl_listener selection_listener;
46 struct wl_listener destroy_listener;
47 struct clipboard_source *source;
50 static void clipboard_client_create(struct clipboard_source *source, int fd);
53 clipboard_source_unref(struct clipboard_source *source)
58 if (source->refcount > 0)
61 if (source->event_source)
62 wl_event_source_remove(source->event_source);
63 wl_signal_emit(&source->base.resource.destroy_signal,
64 &source->base.resource);
65 s = source->base.mime_types.data;
67 wl_array_release(&source->base.mime_types);
68 wl_array_release(&source->contents);
73 clipboard_source_data(int fd, uint32_t mask, void *data)
75 struct clipboard_source *source = data;
76 struct clipboard *clipboard = source->clipboard;
80 if (source->contents.alloc - source->contents.size < 1024) {
81 wl_array_add(&source->contents, 1024);
82 source->contents.size -= 1024;
85 p = source->contents.data + source->contents.size;
86 size = source->contents.alloc - source->contents.size;
87 len = read(fd, p, size);
89 wl_event_source_remove(source->event_source);
90 source->event_source = NULL;
92 clipboard_source_unref(source);
93 clipboard->source = NULL;
95 source->contents.size += len;
102 clipboard_source_accept(struct wl_data_source *source,
103 uint32_t time, const char *mime_type)
108 clipboard_source_send(struct wl_data_source *base,
109 const char *mime_type, int32_t fd)
111 struct clipboard_source *source =
112 container_of(base, struct clipboard_source, base);
115 s = source->base.mime_types.data;
116 if (strcmp(mime_type, s[0]) == 0)
117 clipboard_client_create(source, fd);
123 clipboard_source_cancel(struct wl_data_source *source)
127 static struct clipboard_source *
128 clipboard_source_create(struct clipboard *clipboard,
129 const char *mime_type, uint32_t serial, int fd)
131 struct wl_display *display = clipboard->seat->compositor->wl_display;
132 struct wl_event_loop *loop = wl_display_get_event_loop(display);
133 struct clipboard_source *source;
136 source = malloc(sizeof *source);
137 wl_array_init(&source->contents);
138 wl_array_init(&source->base.mime_types);
139 source->base.accept = clipboard_source_accept;
140 source->base.send = clipboard_source_send;
141 source->base.cancel = clipboard_source_cancel;
142 source->base.resource.data = &source->base;
143 wl_signal_init(&source->base.resource.destroy_signal);
144 source->refcount = 1;
145 source->clipboard = clipboard;
146 source->serial = serial;
148 s = wl_array_add(&source->base.mime_types, sizeof *s);
149 *s = strdup(mime_type);
151 source->event_source =
152 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
153 clipboard_source_data, source);
158 struct clipboard_client {
159 struct wl_event_source *event_source;
161 struct clipboard_source *source;
165 clipboard_client_data(int fd, uint32_t mask, void *data)
167 struct clipboard_client *client = data;
172 size = client->source->contents.size;
173 p = client->source->contents.data;
174 len = write(fd, p + client->offset, size - client->offset);
176 client->offset += len;
178 if (client->offset == size || len <= 0) {
180 wl_event_source_remove(client->event_source);
181 clipboard_source_unref(client->source);
189 clipboard_client_create(struct clipboard_source *source, int fd)
191 struct weston_seat *seat = source->clipboard->seat;
192 struct clipboard_client *client;
193 struct wl_event_loop *loop =
194 wl_display_get_event_loop(seat->compositor->wl_display);
196 client = malloc(sizeof *client);
199 client->source = source;
201 client->event_source =
202 wl_event_loop_add_fd(loop, fd, WL_EVENT_WRITABLE,
203 clipboard_client_data, client);
207 clipboard_set_selection(struct wl_listener *listener, void *data)
209 struct clipboard *clipboard =
210 container_of(listener, struct clipboard, selection_listener);
211 struct weston_seat *seat = data;
212 struct wl_data_source *source = seat->seat.selection_data_source;
213 const char **mime_types;
216 if (source == NULL) {
217 if (clipboard->source)
218 wl_seat_set_selection(&seat->seat,
219 &clipboard->source->base,
220 clipboard->source->serial);
222 } else if (source->accept == clipboard_source_accept) {
223 /* Callback for our data source. */
227 if (clipboard->source)
228 clipboard_source_unref(clipboard->source);
230 clipboard->source = NULL;
232 mime_types = source->mime_types.data;
234 if (pipe2(p, O_CLOEXEC) == -1)
237 source->send(source, mime_types[0], p[1]);
240 clipboard_source_create(clipboard, mime_types[0],
241 seat->seat.selection_serial, p[0]);
242 if (clipboard->source == NULL)
247 clipboard_destroy(struct wl_listener *listener, void *data)
249 struct clipboard *clipboard =
250 container_of(listener, struct clipboard, destroy_listener);
252 wl_list_remove(&clipboard->selection_listener.link);
258 clipboard_create(struct weston_seat *seat)
260 struct clipboard *clipboard;
262 clipboard = malloc(sizeof *clipboard);
263 if (clipboard == NULL)
265 memset(clipboard, 0, sizeof *clipboard);
267 clipboard->seat = seat;
268 clipboard->selection_listener.notify = clipboard_set_selection;
269 clipboard->destroy_listener.notify = clipboard_destroy;
271 wl_signal_add(&seat->seat.selection_signal,
272 &clipboard->selection_listener);
273 wl_signal_add(&seat->seat.destroy_signal,
274 &clipboard->destroy_listener);