blob: 9715307b95f63b6dd2889dcf18cbc488ff9bc752 [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{
Kristian Høgsberg6bce89d2010-09-07 21:34:45 -0400198 struct wl_closure *closure;
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500199 va_list ap;
200
201 va_start(ap, opcode);
Kristian Høgsberg6bce89d2010-09-07 21:34:45 -0400202 closure = wl_connection_vmarshal(proxy->display->connection,
203 &proxy->base, opcode, ap,
204 &proxy->base.interface->methods[opcode]);
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500205 va_end(ap);
Kristian Høgsberg6bce89d2010-09-07 21:34:45 -0400206
207 wl_closure_send(closure, proxy->display->connection);
208 wl_closure_destroy(closure);
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500209}
210
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500211static void
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400212add_visual(struct wl_display *display, uint32_t id)
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500213{
214 struct wl_visual *visual;
215
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500216 visual = (struct wl_visual *)
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400217 wl_proxy_create_for_id(display, &wl_visual_interface, id);
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500218 if (display->argb_visual == NULL)
219 display->argb_visual = visual;
220 else if (display->premultiplied_argb_visual == NULL)
221 display->premultiplied_argb_visual = visual;
222 else
223 display->rgb_visual = visual;
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500224}
225
226WL_EXPORT struct wl_visual *
227wl_display_get_argb_visual(struct wl_display *display)
228{
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500229 return display->argb_visual;
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500230}
231
232WL_EXPORT struct wl_visual *
233wl_display_get_premultiplied_argb_visual(struct wl_display *display)
234{
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500235 return display->premultiplied_argb_visual;
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500236}
237
238WL_EXPORT struct wl_visual *
239wl_display_get_rgb_visual(struct wl_display *display)
240{
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500241 return display->rgb_visual;
242}
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500243
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500244static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500245display_handle_invalid_object(void *data,
246 struct wl_display *display, uint32_t id)
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500247{
248 fprintf(stderr, "sent request to invalid object\n");
Kristian Høgsbergc071f4d2010-08-05 17:44:31 -0400249 abort();
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500250}
251
252static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500253display_handle_invalid_method(void *data,
254 struct wl_display *display,
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500255 uint32_t id, uint32_t opcode)
256{
257 fprintf(stderr, "sent invalid request opcode\n");
Kristian Høgsbergc071f4d2010-08-05 17:44:31 -0400258 abort();
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500259}
260
261static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500262display_handle_no_memory(void *data,
263 struct wl_display *display)
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500264{
265 fprintf(stderr, "server out of memory\n");
Kristian Høgsbergc071f4d2010-08-05 17:44:31 -0400266 abort();
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500267}
268
269static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500270display_handle_global(void *data,
271 struct wl_display *display,
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500272 uint32_t id, const char *interface, uint32_t version)
273{
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400274 struct wl_global_listener *listener;
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500275
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400276 if (strcmp(interface, "display") == 0)
Kristian Høgsbergf52e03f2010-02-26 11:42:59 -0500277 wl_hash_table_insert(display->objects,
278 id, &display->proxy.base);
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400279 else if (strcmp(interface, "visual") == 0)
280 add_visual(display, id);
281
282 wl_list_for_each(listener, &display->global_listener_list, link)
283 (*listener->handler)(display,
284 id, interface, version, listener->data);
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500285}
286
287static void
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500288display_handle_range(void *data,
289 struct wl_display *display, uint32_t range)
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500290{
291 display->next_range = range;
292}
293
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400294static void
295display_handle_sync(void *data, struct wl_display *display, uint32_t key)
296{
297 struct wl_sync_handler *handler;
298
299 handler = container_of(display->sync_list.next,
300 struct wl_sync_handler, link);
301 if (handler->key != key) {
302 fprintf(stderr, "unsolicited sync event, client gone?\n");
303 return;
304 }
305
306 wl_list_remove(&handler->link);
307 handler->func(handler->data);
308 free(handler);
309}
310
311static void
312display_handle_frame(void *data,
313 struct wl_display *display, uint32_t key, uint32_t time)
314{
315 struct wl_frame_handler *handler;
316
317 handler = container_of(display->frame_list. next,
318 struct wl_frame_handler, link);
319 if (handler->key != key) {
320 fprintf(stderr, "unsolicited frame event, client gone?\n");
321 return;
322 }
323
324 wl_list_remove(&handler->link);
325 handler->func(handler->data, time);
326 free(handler);
327}
328
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500329static const struct wl_display_listener display_listener = {
330 display_handle_invalid_object,
331 display_handle_invalid_method,
332 display_handle_no_memory,
333 display_handle_global,
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400334 display_handle_range,
335 display_handle_sync,
336 display_handle_frame
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500337};
338
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500339WL_EXPORT struct wl_display *
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500340wl_display_create(const char *name, size_t name_size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400341{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400342 struct wl_display *display;
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500343 struct sockaddr_un addr;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400344 socklen_t size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400345
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400346 display = malloc(sizeof *display);
347 if (display == NULL)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400348 return NULL;
349
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400350 memset(display, 0, sizeof *display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400351 display->fd = socket(PF_LOCAL, SOCK_STREAM, 0);
352 if (display->fd < 0) {
353 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400354 return NULL;
355 }
356
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500357 addr.sun_family = AF_LOCAL;
358 memcpy(addr.sun_path, name, name_size);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400359
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500360 size = offsetof (struct sockaddr_un, sun_path) + name_size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400361
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500362 if (connect(display->fd, (struct sockaddr *) &addr, size) < 0) {
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400363 close(display->fd);
364 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400365 return NULL;
366 }
367
Kristian Høgsbergf52e03f2010-02-26 11:42:59 -0500368 display->objects = wl_hash_table_create();
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500369 wl_list_init(&display->global_listener_list);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400370
Kristian Høgsbergfabd4392008-12-22 18:06:49 -0500371 display->proxy.base.interface = &wl_display_interface;
Kristian Høgsbergfabd4392008-12-22 18:06:49 -0500372 display->proxy.base.id = 1;
Kristian Høgsbergfe831a72008-12-21 21:50:23 -0500373 display->proxy.display = display;
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500374 wl_list_init(&display->proxy.listener_list);
375
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400376 wl_list_init(&display->sync_list);
377 wl_list_init(&display->frame_list);
378
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500379 display->listener.implementation = (void(**)(void)) &display_listener;
380 wl_list_insert(display->proxy.listener_list.prev, &display->listener.link);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400381
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400382 display->connection = wl_connection_create(display->fd,
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500383 connection_update,
384 display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400385
386 return display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400387}
388
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500389WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400390wl_display_destroy(struct wl_display *display)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400391{
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400392 wl_connection_destroy(display->connection);
393 close(display->fd);
394 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400395}
396
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500397WL_EXPORT int
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500398wl_display_get_fd(struct wl_display *display,
399 wl_display_update_func_t update, void *data)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400400{
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500401 display->update = update;
402 display->update_data = data;
403
404 display->update(display->mask, display->update_data);
405
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400406 return display->fd;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400407}
408
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400409WL_EXPORT int
410wl_display_sync_callback(struct wl_display *display,
411 wl_display_sync_func_t func, void *data)
412{
413 struct wl_sync_handler *handler;
414
415 handler = malloc(sizeof *handler);
416 if (handler == NULL)
417 return -1;
418
419 handler->func = func;
420 handler->key = display->key++;
421 handler->data = data;
422
423 wl_list_insert(display->sync_list.prev, &handler->link);
424 wl_display_sync(display, handler->key);
425
426 return 0;
427}
428
429WL_EXPORT int
430wl_display_frame_callback(struct wl_display *display,
431 wl_display_frame_func_t func, void *data)
432{
433 struct wl_frame_handler *handler;
434
435 handler = malloc(sizeof *handler);
436 if (handler == NULL)
437 return -1;
438
439 handler->func = func;
440 handler->key = display->key++;
441 handler->data = data;
442
443 wl_list_insert(display->frame_list.prev, &handler->link);
444 wl_display_frame(display, handler->key);
445
446 return 0;
447}
448
Kristian Høgsbergee02ca62008-12-21 23:37:12 -0500449static void
Kristian Høgsberg40979232008-11-25 22:40:39 -0500450handle_event(struct wl_display *display,
Kristian Høgsbergfabd4392008-12-22 18:06:49 -0500451 uint32_t id, uint32_t opcode, uint32_t size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400452{
Kristian Høgsbergbf967b42008-12-21 20:25:16 -0500453 uint32_t p[32];
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500454 struct wl_listener *listener;
455 struct wl_proxy *proxy;
Kristian Høgsberg45b77892010-08-30 09:47:36 -0400456 struct wl_closure *closure;
Kristian Høgsberg5c63df72010-09-01 17:18:33 -0400457 const struct wl_message *message;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400458
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500459 wl_connection_copy(display->connection, p, size);
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500460 if (id == 1)
Kristian Høgsberg94448c02008-12-30 11:03:33 -0500461 proxy = &display->proxy;
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500462 else
Kristian Høgsbergb036ad42010-08-13 10:39:57 -0400463 proxy = wl_hash_table_lookup(display->objects, id);
Kristian Høgsbergfabd4392008-12-22 18:06:49 -0500464
Kristian Høgsberg45b77892010-08-30 09:47:36 -0400465 if (proxy == NULL) {
466 wl_connection_consume(display->connection, size);
467 return;
468 }
Kristian Høgsbergb3131d92008-12-24 19:30:25 -0500469
Kristian Høgsberg45b77892010-08-30 09:47:36 -0400470 message = &proxy->base.interface->events[opcode];
471 closure = wl_connection_demarshal(display->connection,
472 size, display->objects, message);
473
474 wl_list_for_each(listener, &proxy->listener_list, link)
475 wl_closure_invoke(closure, &proxy->base,
476 listener->implementation[opcode],
477 listener->data);
478
479 wl_closure_destroy(closure);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400480}
481
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500482WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400483wl_display_iterate(struct wl_display *display, uint32_t mask)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400484{
Kristian Høgsberg40979232008-11-25 22:40:39 -0500485 uint32_t p[2], object, opcode, size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400486 int len;
487
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400488 len = wl_connection_data(display->connection, mask);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400489 while (len > 0) {
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400490 if (len < sizeof p)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400491 break;
492
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400493 wl_connection_copy(display->connection, p, sizeof p);
Kristian Høgsberg40979232008-11-25 22:40:39 -0500494 object = p[0];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400495 opcode = p[1] & 0xffff;
496 size = p[1] >> 16;
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400497 if (len < size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400498 break;
499
Kristian Høgsberg40979232008-11-25 22:40:39 -0500500 handle_event(display, object, opcode, size);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500501 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400502 }
503
504 if (len < 0) {
505 fprintf(stderr, "read error: %m\n");
506 exit(EXIT_FAILURE);
507 }
508}
509
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500510WL_EXPORT uint32_t
511wl_display_allocate_id(struct wl_display *display)
512{
Kristian Høgsberg97079ad2008-12-21 22:45:33 -0500513 if (display->id_count == 0) {
514 display->id_count = 256;
515 display->id = display->next_range;
516 }
517
518 display->id_count--;
519
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500520 return display->id++;
521}
522
523WL_EXPORT void
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400524wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -0400525{
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400526 proxy->user_data = user_data;
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -0400527}
528
529WL_EXPORT void *
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400530wl_proxy_get_user_data(struct wl_proxy *proxy)
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -0400531{
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400532 return proxy->user_data;
Kristian Høgsbergecf65fe2009-09-18 09:49:21 -0400533}