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
34 #include <sys/socket.h>
44 #include "wayland-server.h"
45 #include "wayland-server-protocol.h"
46 #include "connection.h"
51 struct sockaddr_un addr;
57 struct wl_connection *connection;
58 struct wl_event_source *source;
59 struct wl_display *display;
60 struct wl_list resource_list;
67 struct wl_object object;
68 struct wl_event_loop *loop;
69 struct wl_hash_table *objects;
72 struct wl_list frame_list;
73 uint32_t client_id_range;
76 struct wl_list global_list;
77 struct wl_list socket_list;
78 struct wl_list client_list;
81 struct wl_frame_listener {
82 struct wl_resource resource;
83 struct wl_client *client;
85 struct wl_surface *surface;
90 struct wl_object *object;
91 wl_global_bind_func_t func;
95 static int wl_debug = 0;
98 wl_client_post_event(struct wl_client *client, struct wl_object *sender,
101 struct wl_closure *closure;
104 va_start(ap, opcode);
105 closure = wl_connection_vmarshal(client->connection,
107 &sender->interface->events[opcode]);
110 wl_closure_send(closure, client->connection);
113 wl_closure_print(closure, sender, true);
115 wl_closure_destroy(closure);
119 wl_client_post_error(struct wl_client *client, struct wl_object *object,
120 uint32_t code, const char *msg, ...)
126 vsnprintf(buffer, sizeof buffer, msg, ap);
129 wl_client_post_event(client, &client->display->object,
130 WL_DISPLAY_ERROR, object, code, buffer);
134 wl_client_connection_data(int fd, uint32_t mask, void *data)
136 struct wl_client *client = data;
137 struct wl_connection *connection = client->connection;
138 struct wl_object *object;
139 struct wl_closure *closure;
140 const struct wl_message *message;
141 uint32_t p[2], opcode, size;
145 if (mask & WL_EVENT_READABLE)
146 cmask |= WL_CONNECTION_READABLE;
147 if (mask & WL_EVENT_WRITEABLE)
148 cmask |= WL_CONNECTION_WRITABLE;
150 len = wl_connection_data(connection, cmask);
152 wl_client_destroy(client);
156 while (len >= sizeof p) {
157 wl_connection_copy(connection, p, sizeof p);
158 opcode = p[1] & 0xffff;
163 object = wl_hash_table_lookup(client->display->objects, p[0]);
164 if (object == NULL) {
165 wl_client_post_error(client, &client->display->object,
166 WL_DISPLAY_ERROR_INVALID_OBJECT,
167 "invalid object %d", p[0]);
168 wl_connection_consume(connection, size);
173 if (opcode >= object->interface->method_count) {
174 wl_client_post_error(client, &client->display->object,
175 WL_DISPLAY_ERROR_INVALID_METHOD,
176 "invalid method %d, object %s@%d",
177 object->interface->name,
179 wl_connection_consume(connection, size);
184 message = &object->interface->methods[opcode];
185 closure = wl_connection_demarshal(client->connection, size,
186 client->display->objects,
190 if (closure == NULL && errno == EINVAL) {
191 wl_client_post_error(client, &client->display->object,
192 WL_DISPLAY_ERROR_INVALID_METHOD,
193 "invalid arguments for %s@%d.%s",
194 object->interface->name,
195 object->id, message->name);
197 } else if (closure == NULL && errno == ENOMEM) {
198 wl_client_post_no_memory(client);
204 wl_closure_print(closure, object, false);
206 wl_closure_invoke(closure, object,
207 object->implementation[opcode], client);
209 wl_closure_destroy(closure);
216 wl_client_connection_update(struct wl_connection *connection,
217 uint32_t mask, void *data)
219 struct wl_client *client = data;
223 if (mask & WL_CONNECTION_READABLE)
224 emask |= WL_EVENT_READABLE;
225 if (mask & WL_CONNECTION_WRITABLE)
226 emask |= WL_EVENT_WRITEABLE;
228 return wl_event_source_fd_update(client->source, emask);
232 wl_client_flush(struct wl_client *client)
234 if (client->mask & WL_CONNECTION_WRITABLE)
235 wl_connection_data(client->connection, WL_CONNECTION_WRITABLE);
238 WL_EXPORT struct wl_display *
239 wl_client_get_display(struct wl_client *client)
241 return client->display;
245 wl_display_post_range(struct wl_display *display, struct wl_client *client)
247 wl_client_post_event(client, &client->display->object,
248 WL_DISPLAY_RANGE, display->client_id_range);
249 display->client_id_range += 256;
250 client->id_count += 256;
253 WL_EXPORT struct wl_client *
254 wl_client_create(struct wl_display *display, int fd)
256 struct wl_client *client;
257 struct wl_global *global;
259 client = malloc(sizeof *client);
263 memset(client, 0, sizeof *client);
264 client->display = display;
265 client->source = wl_event_loop_add_fd(display->loop, fd,
267 wl_client_connection_data, client);
269 wl_connection_create(fd, wl_client_connection_update, client);
270 if (client->connection == NULL) {
275 wl_list_insert(display->client_list.prev, &client->link);
277 wl_list_init(&client->resource_list);
279 wl_display_post_range(display, client);
281 wl_list_for_each(global, &display->global_list, link)
282 wl_client_post_global(client, global->object);
288 wl_client_add_resource(struct wl_client *client,
289 struct wl_resource *resource)
291 struct wl_display *display = client->display;
293 if (client->id_count-- < 64)
294 wl_display_post_range(display, client);
296 wl_list_init(&resource->destroy_listener_list);
298 wl_hash_table_insert(client->display->objects,
299 resource->object.id, resource);
300 wl_list_insert(client->resource_list.prev, &resource->link);
304 wl_client_post_no_memory(struct wl_client *client)
306 wl_client_post_error(client, &client->display->object,
307 WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
311 wl_client_post_global(struct wl_client *client, struct wl_object *object)
313 wl_client_post_event(client,
314 &client->display->object,
317 object->interface->name,
318 object->interface->version);
322 wl_resource_destroy(struct wl_resource *resource,
323 struct wl_client *client, uint32_t time)
325 struct wl_display *display = client->display;
326 struct wl_listener *l, *next;
328 wl_list_for_each_safe(l, next,
329 &resource->destroy_listener_list, link)
330 l->func(l, resource, time);
332 wl_list_remove(&resource->link);
333 if (resource->object.id > 0)
334 wl_hash_table_remove(display->objects, resource->object.id);
335 resource->destroy(resource, client);
339 wl_client_destroy(struct wl_client *client)
341 struct wl_resource *resource, *tmp;
343 printf("disconnect from client %p\n", client);
345 wl_list_for_each_safe(resource, tmp, &client->resource_list, link)
346 wl_resource_destroy(resource, client, 0);
348 wl_event_source_remove(client->source);
349 wl_connection_destroy(client->connection);
350 wl_list_remove(&client->link);
355 lose_pointer_focus(struct wl_listener *listener,
356 struct wl_resource *resource, uint32_t time)
358 struct wl_input_device *device =
359 container_of(listener, struct wl_input_device,
360 pointer_focus_listener);
362 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
366 lose_keyboard_focus(struct wl_listener *listener,
367 struct wl_resource *resource, uint32_t time)
369 struct wl_input_device *device =
370 container_of(listener, struct wl_input_device,
371 keyboard_focus_listener);
373 wl_input_device_set_keyboard_focus(device, NULL, time);
377 wl_input_device_init(struct wl_input_device *device,
378 struct wl_compositor *compositor)
380 wl_list_init(&device->pointer_focus_listener.link);
381 device->pointer_focus_listener.func = lose_pointer_focus;
382 wl_list_init(&device->keyboard_focus_listener.link);
383 device->keyboard_focus_listener.func = lose_keyboard_focus;
387 device->compositor = compositor;
391 wl_input_device_set_pointer_focus(struct wl_input_device *device,
392 struct wl_surface *surface,
394 int32_t x, int32_t y,
395 int32_t sx, int32_t sy)
397 if (device->pointer_focus == surface)
400 if (device->pointer_focus &&
401 (!surface || device->pointer_focus->client != surface->client))
402 wl_client_post_event(device->pointer_focus->client,
404 WL_INPUT_DEVICE_POINTER_FOCUS,
405 time, NULL, 0, 0, 0, 0);
406 if (device->pointer_focus)
407 wl_list_remove(&device->pointer_focus_listener.link);
410 wl_client_post_event(surface->client,
412 WL_INPUT_DEVICE_POINTER_FOCUS,
413 time, surface, x, y, sx, sy);
414 wl_list_insert(surface->resource.destroy_listener_list.prev,
415 &device->pointer_focus_listener.link);
418 device->pointer_focus = surface;
419 device->pointer_focus_time = time;
424 wl_input_device_set_keyboard_focus(struct wl_input_device *device,
425 struct wl_surface *surface,
428 if (device->keyboard_focus == surface)
431 if (device->keyboard_focus &&
432 (!surface || device->keyboard_focus->client != surface->client))
433 wl_client_post_event(device->keyboard_focus->client,
435 WL_INPUT_DEVICE_KEYBOARD_FOCUS,
436 time, NULL, &device->keys);
437 if (device->keyboard_focus)
438 wl_list_remove(&device->keyboard_focus_listener.link);
441 wl_client_post_event(surface->client,
443 WL_INPUT_DEVICE_KEYBOARD_FOCUS,
444 time, surface, &device->keys);
445 wl_list_insert(surface->resource.destroy_listener_list.prev,
446 &device->keyboard_focus_listener.link);
449 device->keyboard_focus = surface;
450 device->keyboard_focus_time = time;
454 wl_input_device_end_grab(struct wl_input_device *device, uint32_t time)
456 const struct wl_grab_interface *interface;
458 interface = device->grab->interface;
459 interface->end(device->grab, time);
460 device->grab->input_device = NULL;
463 wl_list_remove(&device->grab_listener.link);
467 lose_grab_surface(struct wl_listener *listener,
468 struct wl_resource *resource, uint32_t time)
470 struct wl_input_device *device =
471 container_of(listener,
472 struct wl_input_device, grab_listener);
474 wl_input_device_end_grab(device, time);
478 wl_input_device_start_grab(struct wl_input_device *device,
479 struct wl_grab *grab,
480 uint32_t button, uint32_t time)
482 struct wl_surface *focus = device->pointer_focus;
485 device->grab_button = button;
486 device->grab_time = time;
487 device->grab_x = device->x;
488 device->grab_y = device->y;
490 device->grab_listener.func = lose_grab_surface;
491 wl_list_insert(focus->resource.destroy_listener_list.prev,
492 &device->grab_listener.link);
494 grab->input_device = device;
498 wl_input_device_update_grab(struct wl_input_device *device,
499 struct wl_grab *grab,
500 struct wl_surface *surface, uint32_t time)
502 if (device->grab != &device->motion_grab ||
503 device->grab_time != time ||
504 device->pointer_focus != surface)
508 grab->input_device = device;
514 display_bind(struct wl_client *client,
515 struct wl_display *display, uint32_t id,
516 const char *interface, uint32_t version)
518 struct wl_global *global;
520 wl_list_for_each(global, &display->global_list, link)
521 if (global->object->id == id)
524 if (&global->link == &display->global_list)
525 wl_client_post_error(client, &client->display->object,
526 WL_DISPLAY_ERROR_INVALID_OBJECT,
527 "invalid object %d", id);
528 else if (global->func)
529 global->func(client, global->object, version);
533 display_sync(struct wl_client *client,
534 struct wl_display *display, uint32_t key)
536 wl_client_post_event(client, &display->object, WL_DISPLAY_KEY, key, 0);
540 destroy_frame_listener(struct wl_resource *resource, struct wl_client *client)
542 struct wl_frame_listener *listener =
543 container_of(resource, struct wl_frame_listener, resource);
545 wl_list_remove(&listener->link);
550 display_frame(struct wl_client *client,
551 struct wl_display *display,
552 struct wl_surface *surface,
555 struct wl_frame_listener *listener;
557 listener = malloc(sizeof *listener);
558 if (listener == NULL) {
559 wl_client_post_no_memory(client);
563 /* The listener is a resource so we destroy it when the client
565 listener->resource.destroy = destroy_frame_listener;
566 listener->resource.object.id = 0;
567 listener->client = client;
569 listener->surface = surface;
570 wl_list_init(&listener->resource.destroy_listener_list);
571 wl_list_insert(client->resource_list.prev, &listener->resource.link);
572 wl_list_insert(display->frame_list.prev, &listener->link);
575 struct wl_display_interface display_interface = {
582 WL_EXPORT struct wl_display *
583 wl_display_create(void)
585 struct wl_display *display;
588 debug = getenv("WAYLAND_DEBUG");
592 display = malloc(sizeof *display);
596 display->loop = wl_event_loop_create();
597 if (display->loop == NULL) {
602 display->objects = wl_hash_table_create();
603 if (display->objects == NULL) {
604 wl_event_loop_destroy(display->loop);
609 wl_list_init(&display->frame_list);
610 wl_list_init(&display->global_list);
611 wl_list_init(&display->socket_list);
612 wl_list_init(&display->client_list);
614 display->client_id_range = 256; /* Gah, arbitrary... */
617 display->object.interface = &wl_display_interface;
618 display->object.implementation = (void (**)(void)) &display_interface;
619 wl_display_add_object(display, &display->object);
620 if (wl_display_add_global(display, &display->object, NULL)) {
621 wl_hash_table_destroy(display->objects);
622 wl_event_loop_destroy(display->loop);
631 wl_display_destroy(struct wl_display *display)
633 struct wl_socket *s, *next;
634 struct wl_global *global, *gnext;
636 wl_event_loop_destroy(display->loop);
637 wl_hash_table_destroy(display->objects);
638 wl_list_for_each_safe(s, next, &display->socket_list, link) {
640 unlink(s->addr.sun_path);
642 unlink(s->lock_addr);
646 wl_list_for_each_safe(global, gnext, &display->global_list, link)
653 wl_display_add_object(struct wl_display *display, struct wl_object *object)
655 object->id = display->id++;
656 wl_hash_table_insert(display->objects, object->id, object);
660 wl_display_add_global(struct wl_display *display,
661 struct wl_object *object, wl_global_bind_func_t func)
663 struct wl_global *global;
665 global = malloc(sizeof *global);
669 global->object = object;
671 wl_list_insert(display->global_list.prev, &global->link);
677 wl_display_remove_global(struct wl_display *display,
678 struct wl_object *object)
680 struct wl_global *global;
681 struct wl_client *client;
683 wl_list_for_each(global, &display->global_list, link)
684 if (global->object == object)
687 if (&global->link == &display->global_list)
690 wl_list_for_each(client, &display->client_list, link)
691 wl_client_post_event(client,
692 &client->display->object,
693 WL_DISPLAY_GLOBAL_REMOVE,
695 wl_list_remove(&global->link);
702 wl_display_post_frame(struct wl_display *display, struct wl_surface *surface,
705 struct wl_frame_listener *listener, *next;
707 wl_list_for_each_safe(listener, next, &display->frame_list, link) {
708 if (listener->surface != surface)
710 wl_client_post_event(listener->client, &display->object,
711 WL_DISPLAY_KEY, listener->key, time);
712 wl_resource_destroy(&listener->resource, listener->client, 0);
716 WL_EXPORT struct wl_event_loop *
717 wl_display_get_event_loop(struct wl_display *display)
719 return display->loop;
723 wl_display_terminate(struct wl_display *display)
729 wl_display_run(struct wl_display *display)
734 wl_event_loop_dispatch(display->loop, -1);
738 socket_data(int fd, uint32_t mask, void *data)
740 struct wl_display *display = data;
741 struct sockaddr_un name;
745 length = sizeof name;
747 accept4(fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC);
748 if (client_fd < 0 && errno == ENOSYS) {
749 client_fd = accept(fd, (struct sockaddr *) &name, &length);
750 if (client_fd >= 0 && fcntl(client_fd, F_SETFD, FD_CLOEXEC) == -1)
751 fprintf(stderr, "failed to set FD_CLOEXEC flag on client fd, errno: %d\n", errno);
755 fprintf(stderr, "failed to accept, errno: %d\n", errno);
757 wl_client_create(display, client_fd);
763 get_socket_lock(struct wl_socket *socket, socklen_t name_size)
765 struct stat socket_stat;
766 int lock_size = name_size + 5;
768 snprintf(socket->lock_addr, lock_size,
769 "%s.lock", socket->addr.sun_path);
771 socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC,
772 (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
774 if (socket->fd_lock < 0) {
776 "unable to open lockfile %s check permissions\n",
781 if (flock(socket->fd_lock, LOCK_EX | LOCK_NB) < 0) {
783 "unable to lock lockfile %s, maybe another compositor is running\n",
785 close(socket->fd_lock);
789 if (stat(socket->addr.sun_path, &socket_stat) < 0 ) {
790 if (errno != ENOENT) {
791 fprintf(stderr, "did not manage to stat file %s\n",
792 socket->addr.sun_path);
793 close(socket->fd_lock);
796 } else if (socket_stat.st_mode & S_IWUSR ||
797 socket_stat.st_mode & S_IWGRP) {
798 unlink(socket->addr.sun_path);
805 wl_display_add_socket(struct wl_display *display, const char *name)
808 socklen_t size, name_size;
809 const char *runtime_dir;
811 s = malloc(sizeof *s);
815 s->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
821 runtime_dir = getenv("XDG_RUNTIME_DIR");
822 if (runtime_dir == NULL) {
825 "XDG_RUNTIME_DIR not set, falling back to %s\n",
830 name = getenv("WAYLAND_DISPLAY");
834 memset(&s->addr, 0, sizeof s->addr);
835 s->addr.sun_family = AF_LOCAL;
836 name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
837 "%s/%s", runtime_dir, name) + 1;
838 fprintf(stderr, "using socket %s\n", s->addr.sun_path);
840 if (get_socket_lock(s,name_size) < 0) {
846 size = offsetof (struct sockaddr_un, sun_path) + name_size;
847 if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
853 if (listen(s->fd, 1) < 0) {
855 unlink(s->addr.sun_path);
860 if (wl_event_loop_add_fd(display->loop, s->fd,
862 socket_data, display) == NULL) {
864 unlink(s->addr.sun_path);
868 wl_list_insert(display->socket_list.prev, &s->link);
874 compositor_bind(struct wl_client *client,
875 struct wl_object *global, uint32_t version)
877 struct wl_compositor *compositor =
878 container_of(global, struct wl_compositor, object);
880 wl_client_post_event(client, global,
881 WL_COMPOSITOR_TOKEN_VISUAL,
882 &compositor->argb_visual.object,
883 WL_COMPOSITOR_VISUAL_ARGB32);
885 wl_client_post_event(client, global,
886 WL_COMPOSITOR_TOKEN_VISUAL,
887 &compositor->premultiplied_argb_visual.object,
888 WL_COMPOSITOR_VISUAL_PREMULTIPLIED_ARGB32);
890 wl_client_post_event(client, global,
891 WL_COMPOSITOR_TOKEN_VISUAL,
892 &compositor->rgb_visual.object,
893 WL_COMPOSITOR_VISUAL_XRGB32);
897 wl_compositor_init(struct wl_compositor *compositor,
898 const struct wl_compositor_interface *interface,
899 struct wl_display *display)
901 compositor->object.interface = &wl_compositor_interface;
902 compositor->object.implementation = (void (**)(void)) interface;
903 wl_display_add_object(display, &compositor->object);
904 if (wl_display_add_global(display,
905 &compositor->object, compositor_bind))
908 compositor->argb_visual.object.interface = &wl_visual_interface;
909 compositor->argb_visual.object.implementation = NULL;
910 wl_display_add_object(display, &compositor->argb_visual.object);
911 if (wl_display_add_global(display,
912 &compositor->argb_visual.object, NULL))
915 compositor->premultiplied_argb_visual.object.interface =
916 &wl_visual_interface;
917 compositor->premultiplied_argb_visual.object.implementation = NULL;
918 wl_display_add_object(display,
919 &compositor->premultiplied_argb_visual.object);
920 if (wl_display_add_global(display,
921 &compositor->premultiplied_argb_visual.object,
925 compositor->rgb_visual.object.interface = &wl_visual_interface;
926 compositor->rgb_visual.object.implementation = NULL;
927 wl_display_add_object(display, &compositor->rgb_visual.object);
928 if (wl_display_add_global(display,
929 &compositor->rgb_visual.object, NULL))