blob: 2d731b009586c5b0fbb1ecfaa12010570d21d564 [file] [log] [blame]
Kristian Høgsbergffd710e2008-12-02 15:15:01 -05001/*
2 * Copyright © 2008 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
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040023#include <stdlib.h>
24#include <stdint.h>
25#include <stddef.h>
26#include <stdio.h>
27#include <errno.h>
28#include <string.h>
29#include <unistd.h>
30#include <sys/socket.h>
31#include <sys/un.h>
32#include <ctype.h>
Kristian Høgsbergfe831a72008-12-21 21:50:23 -050033#include <assert.h>
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040034#include <sys/poll.h>
35
Kristian Høgsberga1f3f602010-08-03 09:26:44 -040036#include "wayland-client-protocol.h"
Kristian Høgsberg427524a2008-10-08 13:32:07 -040037#include "connection.h"
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050038#include "wayland-util.h"
Kristian Høgsberg427524a2008-10-08 13:32:07 -040039#include "wayland-client.h"
40
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040041static const char socket_name[] = "\0wayland";
42
Kristian Høgsberg94448c02008-12-30 11:03:33 -050043struct wl_global_listener {
44 wl_display_global_func_t handler;
45 void *data;
46 struct wl_list link;
47};
48
49struct wl_listener {
50 void (**implementation)(void);
51 void *data;
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050052 struct wl_list link;
53};
54
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040055struct wl_proxy {
Kristian Høgsbergfabd4392008-12-22 18:06:49 -050056 struct wl_object base;
Kristian Høgsbergfe831a72008-12-21 21:50:23 -050057 struct wl_display *display;
Kristian Høgsberg94448c02008-12-30 11:03:33 -050058 struct wl_list listener_list;
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -040059 void *user_data;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040060};
61
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -040062struct wl_sync_handler {
63 wl_display_sync_func_t func;
64 uint32_t key;
65 void *data;
66 struct wl_list link;
67};
68
69struct wl_frame_handler {
70 wl_display_frame_func_t func;
71 uint32_t key;
72 void *data;
73 struct wl_list link;
74};
75
Kristian Høgsberg94448c02008-12-30 11:03:33 -050076struct wl_display {
77 struct wl_proxy proxy;
78 struct wl_connection *connection;
79 int fd;
80 uint32_t id, id_count, next_range;
81 uint32_t mask;
Kristian Høgsbergf52e03f2010-02-26 11:42:59 -050082 struct wl_hash_table *objects;
Kristian Høgsberg94448c02008-12-30 11:03:33 -050083 struct wl_listener listener;
84 struct wl_list global_listener_list;
85
86 struct wl_visual *argb_visual;
87 struct wl_visual *premultiplied_argb_visual;
88 struct wl_visual *rgb_visual;
89
90 wl_display_update_func_t update;
91 void *update_data;
92
93 wl_display_global_func_t global_handler;
94 void *global_handler_data;
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -040095
96 struct wl_list sync_list, frame_list;
97 uint32_t key;
Kristian Høgsberg94448c02008-12-30 11:03:33 -050098};
99
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500100static int
101connection_update(struct wl_connection *connection,
102 uint32_t mask, void *data)
103{
104 struct wl_display *display = data;
105
106 display->mask = mask;
107 if (display->update)
108 return display->update(display->mask,
109 display->update_data);
110
111 return 0;
112}
113
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500114WL_EXPORT struct wl_global_listener *
115wl_display_add_global_listener(struct wl_display *display,
116 wl_display_global_func_t handler, void *data)
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500117{
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500118 struct wl_global_listener *listener;
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500119
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500120 listener = malloc(sizeof *listener);
121 if (listener == NULL)
122 return NULL;
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500123
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500124 listener->handler = handler;
125 listener->data = data;
126 wl_list_insert(display->global_listener_list.prev, &listener->link);
127
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500128 return listener;
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500129}
130
Kristian Høgsbergee02ca62008-12-21 23:37:12 -0500131WL_EXPORT void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500132wl_display_remove_global_listener(struct wl_display *display,
133 struct wl_global_listener *listener)
Kristian Høgsbergee02ca62008-12-21 23:37:12 -0500134{
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500135 wl_list_remove(&listener->link);
136 free(listener);
137}
138
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400139WL_EXPORT struct wl_proxy *
140wl_proxy_create_for_id(struct wl_display *display,
141 const struct wl_interface *interface, uint32_t id)
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500142{
143 struct wl_proxy *proxy;
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500144
145 proxy = malloc(sizeof *proxy);
146 if (proxy == NULL)
147 return NULL;
148
149 proxy->base.interface = interface;
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400150 proxy->base.id = id;
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500151 proxy->display = display;
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500152 wl_list_init(&proxy->listener_list);
Kristian Høgsbergf52e03f2010-02-26 11:42:59 -0500153 wl_hash_table_insert(display->objects, proxy->base.id, proxy);
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500154
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500155 return proxy;
156}
157
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400158WL_EXPORT struct wl_proxy *
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400159wl_proxy_create(struct wl_proxy *factory,
160 const struct wl_interface *interface)
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400161{
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400162 return wl_proxy_create_for_id(factory->display, interface,
163 wl_display_allocate_id(factory->display));
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400164}
165
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400166WL_EXPORT void
167wl_proxy_destroy(struct wl_proxy *proxy)
168{
169 struct wl_listener *listener, *next;
170
171 wl_list_for_each_safe(listener, next, &proxy->listener_list, link)
172 free(listener);
173
174 wl_hash_table_remove(proxy->display->objects, proxy->base.id);
175 free(proxy);
176}
177
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400178WL_EXPORT int
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400179wl_proxy_add_listener(struct wl_proxy *proxy,
180 void (**implementation)(void), void *data)
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500181{
182 struct wl_listener *listener;
183
184 listener = malloc(sizeof *listener);
185 if (listener == NULL)
186 return -1;
187
188 listener->implementation = (void (**)(void)) implementation;
189 listener->data = data;
190 wl_list_insert(proxy->listener_list.prev, &listener->link);
191
192 return 0;
193}
194
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400195WL_EXPORT void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500196wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
197{
198 va_list ap;
199
200 va_start(ap, opcode);
201 wl_connection_vmarshal(proxy->display->connection,
202 &proxy->base, opcode, ap,
203 &proxy->base.interface->methods[opcode]);
204 va_end(ap);
205}
206
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500207static void
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400208add_visual(struct wl_display *display, uint32_t id)
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500209{
210 struct wl_visual *visual;
211
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500212 visual = (struct wl_visual *)
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400213 wl_proxy_create_for_id(display, &wl_visual_interface, id);
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500214 if (display->argb_visual == NULL)
215 display->argb_visual = visual;
216 else if (display->premultiplied_argb_visual == NULL)
217 display->premultiplied_argb_visual = visual;
218 else
219 display->rgb_visual = visual;
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500220}
221
222WL_EXPORT struct wl_visual *
223wl_display_get_argb_visual(struct wl_display *display)
224{
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500225 return display->argb_visual;
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500226}
227
228WL_EXPORT struct wl_visual *
229wl_display_get_premultiplied_argb_visual(struct wl_display *display)
230{
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500231 return display->premultiplied_argb_visual;
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500232}
233
234WL_EXPORT struct wl_visual *
235wl_display_get_rgb_visual(struct wl_display *display)
236{
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500237 return display->rgb_visual;
238}
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500239
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500240static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500241display_handle_invalid_object(void *data,
242 struct wl_display *display, uint32_t id)
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500243{
244 fprintf(stderr, "sent request to invalid object\n");
Kristian Høgsbergc071f4d2010-08-05 17:44:31 -0400245 abort();
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500246}
247
248static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500249display_handle_invalid_method(void *data,
250 struct wl_display *display,
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500251 uint32_t id, uint32_t opcode)
252{
253 fprintf(stderr, "sent invalid request opcode\n");
Kristian Høgsbergc071f4d2010-08-05 17:44:31 -0400254 abort();
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500255}
256
257static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500258display_handle_no_memory(void *data,
259 struct wl_display *display)
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500260{
261 fprintf(stderr, "server out of memory\n");
Kristian Høgsbergc071f4d2010-08-05 17:44:31 -0400262 abort();
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500263}
264
265static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500266display_handle_global(void *data,
267 struct wl_display *display,
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500268 uint32_t id, const char *interface, uint32_t version)
269{
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400270 struct wl_global_listener *listener;
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500271
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400272 if (strcmp(interface, "display") == 0)
Kristian Høgsbergf52e03f2010-02-26 11:42:59 -0500273 wl_hash_table_insert(display->objects,
274 id, &display->proxy.base);
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400275 else if (strcmp(interface, "visual") == 0)
276 add_visual(display, id);
277
278 wl_list_for_each(listener, &display->global_listener_list, link)
279 (*listener->handler)(display,
280 id, interface, version, listener->data);
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500281}
282
283static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500284display_handle_range(void *data,
285 struct wl_display *display, uint32_t range)
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500286{
287 display->next_range = range;
288}
289
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400290static void
291display_handle_sync(void *data, struct wl_display *display, uint32_t key)
292{
293 struct wl_sync_handler *handler;
294
295 handler = container_of(display->sync_list.next,
296 struct wl_sync_handler, link);
297 if (handler->key != key) {
298 fprintf(stderr, "unsolicited sync event, client gone?\n");
299 return;
300 }
301
302 wl_list_remove(&handler->link);
303 handler->func(handler->data);
304 free(handler);
305}
306
307static void
308display_handle_frame(void *data,
309 struct wl_display *display, uint32_t key, uint32_t time)
310{
311 struct wl_frame_handler *handler;
312
313 handler = container_of(display->frame_list. next,
314 struct wl_frame_handler, link);
315 if (handler->key != key) {
316 fprintf(stderr, "unsolicited frame event, client gone?\n");
317 return;
318 }
319
320 wl_list_remove(&handler->link);
321 handler->func(handler->data, time);
322 free(handler);
323}
324
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500325static const struct wl_display_listener display_listener = {
326 display_handle_invalid_object,
327 display_handle_invalid_method,
328 display_handle_no_memory,
329 display_handle_global,
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400330 display_handle_range,
331 display_handle_sync,
332 display_handle_frame
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500333};
334
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500335WL_EXPORT struct wl_display *
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500336wl_display_create(const char *name, size_t name_size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400337{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400338 struct wl_display *display;
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500339 struct sockaddr_un addr;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400340 socklen_t size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400341
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400342 display = malloc(sizeof *display);
343 if (display == NULL)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400344 return NULL;
345
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400346 memset(display, 0, sizeof *display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400347 display->fd = socket(PF_LOCAL, SOCK_STREAM, 0);
348 if (display->fd < 0) {
349 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400350 return NULL;
351 }
352
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500353 addr.sun_family = AF_LOCAL;
354 memcpy(addr.sun_path, name, name_size);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400355
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500356 size = offsetof (struct sockaddr_un, sun_path) + name_size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400357
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500358 if (connect(display->fd, (struct sockaddr *) &addr, size) < 0) {
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400359 close(display->fd);
360 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400361 return NULL;
362 }
363
Kristian Høgsbergf52e03f2010-02-26 11:42:59 -0500364 display->objects = wl_hash_table_create();
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500365 wl_list_init(&display->global_listener_list);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400366
Kristian Høgsbergfabd4392008-12-22 18:06:49 -0500367 display->proxy.base.interface = &wl_display_interface;
Kristian Høgsbergfabd4392008-12-22 18:06:49 -0500368 display->proxy.base.id = 1;
Kristian Høgsbergfe831a72008-12-21 21:50:23 -0500369 display->proxy.display = display;
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500370 wl_list_init(&display->proxy.listener_list);
371
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400372 wl_list_init(&display->sync_list);
373 wl_list_init(&display->frame_list);
374
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500375 display->listener.implementation = (void(**)(void)) &display_listener;
376 wl_list_insert(display->proxy.listener_list.prev, &display->listener.link);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400377
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400378 display->connection = wl_connection_create(display->fd,
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500379 connection_update,
380 display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400381
382 return display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400383}
384
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500385WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400386wl_display_destroy(struct wl_display *display)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400387{
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400388 wl_connection_destroy(display->connection);
389 close(display->fd);
390 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400391}
392
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500393WL_EXPORT int
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500394wl_display_get_fd(struct wl_display *display,
395 wl_display_update_func_t update, void *data)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400396{
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500397 display->update = update;
398 display->update_data = data;
399
400 display->update(display->mask, display->update_data);
401
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400402 return display->fd;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400403}
404
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400405WL_EXPORT int
406wl_display_sync_callback(struct wl_display *display,
407 wl_display_sync_func_t func, void *data)
408{
409 struct wl_sync_handler *handler;
410
411 handler = malloc(sizeof *handler);
412 if (handler == NULL)
413 return -1;
414
415 handler->func = func;
416 handler->key = display->key++;
417 handler->data = data;
418
419 wl_list_insert(display->sync_list.prev, &handler->link);
420 wl_display_sync(display, handler->key);
421
422 return 0;
423}
424
425WL_EXPORT int
426wl_display_frame_callback(struct wl_display *display,
427 wl_display_frame_func_t func, void *data)
428{
429 struct wl_frame_handler *handler;
430
431 handler = malloc(sizeof *handler);
432 if (handler == NULL)
433 return -1;
434
435 handler->func = func;
436 handler->key = display->key++;
437 handler->data = data;
438
439 wl_list_insert(display->frame_list.prev, &handler->link);
440 wl_display_frame(display, handler->key);
441
442 return 0;
443}
444
Kristian Høgsbergee02ca62008-12-21 23:37:12 -0500445static void
Kristian Høgsberg40979232008-11-25 22:40:39 -0500446handle_event(struct wl_display *display,
Kristian Høgsbergfabd4392008-12-22 18:06:49 -0500447 uint32_t id, uint32_t opcode, uint32_t size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400448{
Kristian Høgsbergbf967b42008-12-21 20:25:16 -0500449 uint32_t p[32];
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500450 struct wl_listener *listener;
451 struct wl_proxy *proxy;
Kristian Høgsberg45b77892010-08-30 09:47:36 -0400452 struct wl_closure *closure;
Kristian Høgsberg5c63df72010-09-01 17:18:33 -0400453 const struct wl_message *message;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400454
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500455 wl_connection_copy(display->connection, p, size);
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500456 if (id == 1)
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500457 proxy = &display->proxy;
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500458 else
Kristian Høgsbergb036ad42010-08-13 10:39:57 -0400459 proxy = wl_hash_table_lookup(display->objects, id);
Kristian Høgsbergfabd4392008-12-22 18:06:49 -0500460
Kristian Høgsberg45b77892010-08-30 09:47:36 -0400461 if (proxy == NULL) {
462 wl_connection_consume(display->connection, size);
463 return;
464 }
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500465
Kristian Høgsberg45b77892010-08-30 09:47:36 -0400466 message = &proxy->base.interface->events[opcode];
467 closure = wl_connection_demarshal(display->connection,
468 size, display->objects, message);
469
470 wl_list_for_each(listener, &proxy->listener_list, link)
471 wl_closure_invoke(closure, &proxy->base,
472 listener->implementation[opcode],
473 listener->data);
474
475 wl_closure_destroy(closure);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400476}
477
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500478WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400479wl_display_iterate(struct wl_display *display, uint32_t mask)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400480{
Kristian Høgsberg40979232008-11-25 22:40:39 -0500481 uint32_t p[2], object, opcode, size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400482 int len;
483
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400484 len = wl_connection_data(display->connection, mask);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400485 while (len > 0) {
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400486 if (len < sizeof p)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400487 break;
488
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400489 wl_connection_copy(display->connection, p, sizeof p);
Kristian Høgsberg40979232008-11-25 22:40:39 -0500490 object = p[0];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400491 opcode = p[1] & 0xffff;
492 size = p[1] >> 16;
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400493 if (len < size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400494 break;
495
Kristian Høgsberg40979232008-11-25 22:40:39 -0500496 handle_event(display, object, opcode, size);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500497 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400498 }
499
500 if (len < 0) {
501 fprintf(stderr, "read error: %m\n");
502 exit(EXIT_FAILURE);
503 }
504}
505
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500506WL_EXPORT uint32_t
507wl_display_allocate_id(struct wl_display *display)
508{
Kristian Høgsberg97079ad2008-12-21 22:45:33 -0500509 if (display->id_count == 0) {
510 display->id_count = 256;
511 display->id = display->next_range;
512 }
513
514 display->id_count--;
515
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500516 return display->id++;
517}
518
519WL_EXPORT void
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400520wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -0400521{
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400522 proxy->user_data = user_data;
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -0400523}
524
525WL_EXPORT void *
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400526wl_proxy_get_user_data(struct wl_proxy *proxy)
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -0400527{
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400528 return proxy->user_data;
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -0400529}