2 * Copyright © 2008 Kristian Høgsberg
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.
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
31 #include <sys/socket.h>
38 #include "wayland-server-protocol.h"
39 #include "connection.h"
42 struct wl_connection *connection;
43 struct wl_event_source *source;
44 struct wl_display *display;
45 struct wl_list surface_list;
51 struct wl_object base;
52 struct wl_event_loop *loop;
53 struct wl_hash_table *objects;
55 struct wl_list pending_frame_list;
56 uint32_t client_id_range;
59 struct wl_list global_list;
63 struct wl_object *object;
64 wl_client_connect_func_t func;
69 wl_client_post_event(struct wl_client *client, struct wl_object *sender,
75 wl_connection_vmarshal(client->connection,
77 &sender->interface->events[opcode]);
82 wl_client_connection_data(int fd, uint32_t mask, void *data)
84 struct wl_client *client = data;
85 struct wl_connection *connection = client->connection;
86 struct wl_object *object;
87 uint32_t p[2], opcode, size;
91 if (mask & WL_EVENT_READABLE)
92 cmask |= WL_CONNECTION_READABLE;
93 if (mask & WL_EVENT_WRITEABLE)
94 cmask |= WL_CONNECTION_WRITABLE;
96 len = wl_connection_data(connection, cmask);
98 wl_client_destroy(client);
102 while (len >= sizeof p) {
103 wl_connection_copy(connection, p, sizeof p);
104 opcode = p[1] & 0xffff;
109 object = wl_hash_table_lookup(client->display->objects, p[0]);
110 if (object == NULL) {
111 wl_client_post_event(client, &client->display->base,
112 WL_DISPLAY_INVALID_OBJECT, p[0]);
113 wl_connection_consume(connection, size);
118 if (opcode >= object->interface->method_count) {
119 wl_client_post_event(client, &client->display->base,
120 WL_DISPLAY_INVALID_METHOD, p[0], opcode);
121 wl_connection_consume(connection, size);
126 wl_connection_demarshal(client->connection,
128 client->display->objects,
129 object->implementation[opcode],
132 &object->interface->methods[opcode]);
134 wl_connection_consume(connection, size);
140 wl_client_connection_update(struct wl_connection *connection,
141 uint32_t mask, void *data)
143 struct wl_client *client = data;
146 if (mask & WL_CONNECTION_READABLE)
147 emask |= WL_EVENT_READABLE;
148 if (mask & WL_CONNECTION_WRITABLE)
149 emask |= WL_EVENT_WRITEABLE;
151 return wl_event_source_fd_update(client->source, mask);
155 wl_display_post_range(struct wl_display *display, struct wl_client *client)
157 wl_client_post_event(client, &client->display->base,
158 WL_DISPLAY_RANGE, display->client_id_range);
159 display->client_id_range += 256;
160 client->id_count += 256;
163 static struct wl_client *
164 wl_client_create(struct wl_display *display, int fd)
166 struct wl_client *client;
167 struct wl_global *global;
169 client = malloc(sizeof *client);
173 memset(client, 0, sizeof *client);
174 client->display = display;
175 client->source = wl_event_loop_add_fd(display->loop, fd,
177 wl_client_connection_data, client);
179 wl_connection_create(fd, wl_client_connection_update, client);
181 wl_list_init(&client->surface_list);
182 wl_list_init(&client->link);
184 wl_display_post_range(display, client);
186 wl_list_for_each(global, &display->global_list, link)
187 wl_client_post_event(client, &client->display->base,
190 global->object->interface->name,
191 global->object->interface->version);
193 wl_list_for_each(global, &display->global_list, link)
195 global->func(client, global->object);
201 wl_object_destroy(struct wl_object *object)
203 const struct wl_surface_interface *interface =
204 (const struct wl_surface_interface *) object->implementation;
206 /* FIXME: Need generic object destructor. */
207 interface->destroy(NULL, (struct wl_surface *) object);
211 wl_client_destroy(struct wl_client *client)
213 struct wl_surface *surface;
215 printf("disconnect from client %p\n", client);
217 wl_list_remove(&client->link);
219 while (client->surface_list.next != &client->surface_list) {
220 surface = container_of(client->surface_list.next,
221 struct wl_surface, link);
222 wl_list_remove(&surface->link);
223 wl_object_destroy(&surface->base);
226 wl_event_source_remove(client->source);
227 wl_connection_destroy(client->connection);
232 wl_client_add_surface(struct wl_client *client,
233 struct wl_surface *surface,
234 const struct wl_surface_interface *implementation,
237 struct wl_display *display = client->display;
239 if (client->id_count-- < 64)
240 wl_display_post_range(display, client);
242 surface->base.id = id;
243 surface->base.interface = &wl_surface_interface;
244 surface->base.implementation = (void (**)(void)) implementation;
245 surface->client = client;
247 wl_hash_table_insert(display->objects, id, surface);
248 wl_list_insert(client->surface_list.prev, &surface->link);
254 wl_client_remove_surface(struct wl_client *client,
255 struct wl_surface *surface)
257 struct wl_display *display = client->display;
259 wl_hash_table_remove(display->objects, surface->base.id);
260 wl_list_remove(&surface->link);
264 wl_client_send_acknowledge(struct wl_client *client,
265 struct wl_compositor *compositor,
266 uint32_t key, uint32_t frame)
268 wl_list_remove(&client->link);
269 wl_list_insert(client->display->pending_frame_list.prev,
271 wl_client_post_event(client, &compositor->base,
272 WL_COMPOSITOR_ACKNOWLEDGE, key, frame);
276 post_compositor_device(struct wl_client *client, struct wl_object *global)
278 struct wl_compositor *compositor =
279 container_of(global, struct wl_compositor, base);
281 wl_client_post_event(client, global,
282 WL_COMPOSITOR_DEVICE, compositor->device);
286 wl_display_set_compositor(struct wl_display *display,
287 struct wl_compositor *compositor,
288 const struct wl_compositor_interface *implementation)
290 compositor->base.interface = &wl_compositor_interface;
291 compositor->base.implementation = (void (**)(void)) implementation;
293 wl_display_add_object(display, &compositor->base);
294 if (wl_display_add_global(display, &compositor->base, post_compositor_device))
300 WL_EXPORT struct wl_display *
301 wl_display_create(void)
303 struct wl_display *display;
305 display = malloc(sizeof *display);
309 display->loop = wl_event_loop_create();
310 if (display->loop == NULL) {
315 display->objects = wl_hash_table_create();
316 if (display->objects == NULL) {
321 wl_list_init(&display->pending_frame_list);
322 wl_list_init(&display->global_list);
324 display->client_id_range = 256; /* Gah, arbitrary... */
327 display->base.interface = &wl_display_interface;
328 display->base.implementation = NULL;
329 wl_display_add_object(display, &display->base);
330 if (wl_display_add_global(display, &display->base, NULL)) {
331 wl_event_loop_destroy(display->loop);
340 wl_display_add_object(struct wl_display *display, struct wl_object *object)
342 object->id = display->id++;
343 wl_hash_table_insert(display->objects, object->id, object);
347 wl_display_add_global(struct wl_display *display,
348 struct wl_object *object, wl_client_connect_func_t func)
350 struct wl_global *global;
352 global = malloc(sizeof *global);
356 global->object = object;
358 wl_list_insert(display->global_list.prev, &global->link);
364 wl_surface_post_event(struct wl_surface *surface,
365 struct wl_object *sender,
371 wl_connection_vmarshal(surface->client->connection,
373 &sender->interface->events[event]);
378 wl_display_post_frame(struct wl_display *display,
379 struct wl_compositor *compositor,
380 uint32_t frame, uint32_t msecs)
382 struct wl_client *client;
384 wl_list_for_each(client, &display->pending_frame_list, link)
385 wl_client_post_event(client, &compositor->base,
386 WL_COMPOSITOR_FRAME, frame, msecs);
388 wl_list_remove(&display->pending_frame_list);
389 wl_list_init(&display->pending_frame_list);
392 WL_EXPORT struct wl_event_loop *
393 wl_display_get_event_loop(struct wl_display *display)
395 return display->loop;
399 wl_display_run(struct wl_display *display)
402 wl_event_loop_wait(display->loop);
406 socket_data(int fd, uint32_t mask, void *data)
408 struct wl_display *display = data;
409 struct sockaddr_un name;
413 length = sizeof name;
414 client_fd = accept (fd, (struct sockaddr *) &name, &length);
416 fprintf(stderr, "failed to accept\n");
418 wl_client_create(display, client_fd);
422 wl_display_add_socket(struct wl_display *display,
423 const char *name, size_t name_size)
425 struct sockaddr_un addr;
429 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
433 addr.sun_family = AF_LOCAL;
434 memcpy(addr.sun_path, name, name_size);
436 size = offsetof (struct sockaddr_un, sun_path) + name_size;
437 if (bind(sock, (struct sockaddr *) &addr, size) < 0)
440 if (listen(sock, 1) < 0)
443 wl_event_loop_add_fd(display->loop, sock,
445 socket_data, display);