From ee02ca6fa489a99ddec5d1542d51cce9948d39a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Sun, 21 Dec 2008 23:37:12 -0500 Subject: [PATCH] Add hook to allow globals to send cold-plug events to new clients. This lets us boot strap the client side state cache. This commit also adds the first user of this feature, an output object that represents the current output. Very simple at this point, but will grow to something more like RandR 1.2. --- wayland-client.c | 27 ++++++++++++++++ wayland-client.h | 3 ++ wayland-protocol.c | 11 +++++++ wayland-protocol.h | 5 +++ wayland-system-compositor.c | 29 +++++++++++++++--- wayland.c | 61 ++++++++++++++++++++++++++----------- wayland.h | 10 +++++- 7 files changed, 124 insertions(+), 22 deletions(-) diff --git a/wayland-client.c b/wayland-client.c index f3358b40..27607062 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -67,6 +67,9 @@ struct wl_display { wl_display_event_func_t event_handler; void *event_handler_data; + + uint32_t output_id; + int32_t width, height; }; struct wl_compositor { @@ -96,6 +99,13 @@ connection_update(struct wl_connection *connection, return 0; } +WL_EXPORT void +wl_display_get_geometry(struct wl_display *display, int32_t *width, int32_t *height) +{ + *width = display->width; + *height = display->height; +} + static void add_visual(struct wl_display *display, struct wl_global *global) { @@ -258,6 +268,9 @@ handle_display_event(struct wl_display *display, if (strcmp(global->interface, "visual") == 0) add_visual(display, global); + else if (strcmp(global->interface, "output") == 0) { + display->output_id = p[0]; + } break; case WL_DISPLAY_RANGE: @@ -266,6 +279,18 @@ handle_display_event(struct wl_display *display, } } +static void +handle_output_event(struct wl_display *display, + uint32_t opcode, uint32_t *p, uint32_t size) +{ + switch (opcode) { + case WL_OUTPUT_PRESENCE: + display->width = p[0]; + display->height = p[1]; + break; + } +} + static void handle_event(struct wl_display *display, uint32_t object, uint32_t opcode, uint32_t size) @@ -275,6 +300,8 @@ handle_event(struct wl_display *display, wl_connection_copy(display->connection, p, size); if (object == 1) { handle_display_event(display, opcode, p + 2, size); + } if (object == display->output_id) { + handle_output_event(display, opcode, p + 2, size); } else if (display->event_handler != NULL) display->event_handler(display, object, opcode, size, p + 2, display->event_handler_data); diff --git a/wayland-client.h b/wayland-client.h index 1a412177..fd158399 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -57,6 +57,9 @@ void wl_display_set_event_handler(struct wl_display *display, wl_display_event_func_t handler, void *data); +void +wl_display_get_geometry(struct wl_display *display, + int32_t *width, int32_t *height); struct wl_compositor * wl_display_get_compositor(struct wl_display *display); struct wl_visual * diff --git a/wayland-protocol.c b/wayland-protocol.c index 4c618109..4ec40abd 100644 --- a/wayland-protocol.c +++ b/wayland-protocol.c @@ -83,3 +83,14 @@ WL_EXPORT const struct wl_interface wl_input_device_interface = { 0, NULL, ARRAY_LENGTH(input_device_events), input_device_events, }; + + +static const struct wl_message output_events[] = { + { "presence", "uu" }, +}; + +WL_EXPORT const struct wl_interface wl_output_interface = { + "output", 1, + 0, NULL, + ARRAY_LENGTH(output_events), output_events, +}; diff --git a/wayland-protocol.h b/wayland-protocol.h index c71cfdc5..76a80c59 100644 --- a/wayland-protocol.h +++ b/wayland-protocol.h @@ -78,4 +78,9 @@ extern const struct wl_interface wl_surface_interface; extern const struct wl_interface wl_input_device_interface; + +#define WL_OUTPUT_PRESENCE 0 + +extern const struct wl_interface wl_output_interface; + #endif diff --git a/wayland-system-compositor.c b/wayland-system-compositor.c index 69f785c3..f3ff5b08 100644 --- a/wayland-system-compositor.c +++ b/wayland-system-compositor.c @@ -56,6 +56,10 @@ struct wl_visual { struct wl_object base; }; +struct wl_output { + struct wl_object base; +}; + struct wlsc_input_device { struct wl_object base; int32_t x, y; @@ -70,6 +74,7 @@ struct wlsc_input_device { struct egl_compositor { struct wl_compositor base; + struct wl_output output; struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual; EGLDisplay display; @@ -825,19 +830,29 @@ add_visuals(struct egl_compositor *ec) ec->argb_visual.base.interface = &visual_interface; ec->argb_visual.base.implementation = NULL; wl_display_add_object(ec->wl_display, &ec->argb_visual.base); - wl_display_add_global(ec->wl_display, &ec->argb_visual.base); + wl_display_add_global(ec->wl_display, &ec->argb_visual.base, NULL); ec->premultiplied_argb_visual.base.interface = &visual_interface; ec->premultiplied_argb_visual.base.implementation = NULL; wl_display_add_object(ec->wl_display, &ec->premultiplied_argb_visual.base); wl_display_add_global(ec->wl_display, - &ec->premultiplied_argb_visual.base); + &ec->premultiplied_argb_visual.base, NULL); ec->rgb_visual.base.interface = &visual_interface; ec->rgb_visual.base.implementation = NULL; wl_display_add_object(ec->wl_display, &ec->rgb_visual.base); - wl_display_add_global(ec->wl_display, &ec->rgb_visual.base); + wl_display_add_global(ec->wl_display, &ec->rgb_visual.base, NULL); +} + +static void +post_output_presence(struct wl_client *client, struct wl_object *global) +{ + struct egl_compositor *ec = + container_of(global, struct egl_compositor, output.base); + + wl_client_post_event(client, global, + WL_OUTPUT_PRESENCE, ec->width, ec->height); } static const char gem_device[] = "/dev/dri/card0"; @@ -1021,6 +1036,12 @@ egl_compositor_create(struct wl_display *display) glClearColor(0, 0, 0.2, 1); wl_display_set_compositor(display, &ec->base, &compositor_interface); + + /* FIXME: This needs to be much more expressive... something like randr 1.2. */ + ec->output.base.interface = &wl_output_interface; + wl_display_add_object(display, &ec->output.base); + wl_display_add_global(display, &ec->output.base, post_output_presence); + add_visuals(ec); wl_list_init(&ec->input_device_list); @@ -1033,7 +1054,7 @@ egl_compositor_create(struct wl_display *display) shooter = screenshooter_create(ec); wl_display_add_object(display, &shooter->base); - wl_display_add_global(display, &shooter->base); + wl_display_add_global(display, &shooter->base, NULL); loop = wl_display_get_event_loop(ec->wl_display); diff --git a/wayland.c b/wayland.c index 6ad18876..0fe2a8de 100644 --- a/wayland.c +++ b/wayland.c @@ -64,6 +64,12 @@ struct wl_object_ref { struct wl_list link; }; +struct wl_global { + struct wl_object *object; + wl_client_connect_func_t func; + struct wl_list link; +}; + void wl_client_destroy(struct wl_client *client); @@ -122,6 +128,17 @@ wl_client_marshal(struct wl_client *client, struct wl_object *sender, va_end(ap); } +WL_EXPORT void +wl_client_post_event(struct wl_client *client, struct wl_object *sender, + uint32_t opcode, ...) +{ + va_list ap; + + va_start(ap, opcode); + wl_client_vmarshal(client, sender, opcode, ap); + va_end(ap); +} + static void wl_client_demarshal(struct wl_client *client, struct wl_object *target, uint32_t opcode, size_t size) @@ -284,7 +301,7 @@ static struct wl_client * wl_client_create(struct wl_display *display, int fd) { struct wl_client *client; - struct wl_object_ref *ref; + struct wl_global *global; client = malloc(sizeof *client); if (client == NULL) @@ -303,17 +320,25 @@ wl_client_create(struct wl_display *display, int fd) wl_display_post_range(display, client); - ref = container_of(display->global_list.next, - struct wl_object_ref, link); - while (&ref->link != &display->global_list) { + global = container_of(display->global_list.next, + struct wl_global, link); + while (&global->link != &display->global_list) { wl_client_marshal(client, &client->display->base, WL_DISPLAY_GLOBAL, - ref->object, - ref->object->interface->name, - ref->object->interface->version); + global->object, + global->object->interface->name, + global->object->interface->version); + global = container_of(global->link.next, + struct wl_global, link); + } - ref = container_of(ref->link.next, - struct wl_object_ref, link); + global = container_of(display->global_list.next, + struct wl_global, link); + while (&global->link != &display->global_list) { + if (global->func) + global->func(client, global->object); + global = container_of(global->link.next, + struct wl_global, link); } return client; @@ -403,7 +428,7 @@ wl_display_set_compositor(struct wl_display *display, compositor->base.implementation = (void (**)(void)) implementation; wl_display_add_object(display, &compositor->base); - if (wl_display_add_global(display, &compositor->base)) + if (wl_display_add_global(display, &compositor->base, NULL)) return -1; return 0; @@ -439,7 +464,7 @@ wl_display_create(void) display->base.interface = &wl_display_interface; display->base.implementation = NULL; wl_display_add_object(display, &display->base); - if (wl_display_add_global(display, &display->base)) { + if (wl_display_add_global(display, &display->base, NULL)) { wl_event_loop_destroy(display->loop); free(display); return NULL; @@ -456,16 +481,18 @@ wl_display_add_object(struct wl_display *display, struct wl_object *object) } WL_EXPORT int -wl_display_add_global(struct wl_display *display, struct wl_object *object) +wl_display_add_global(struct wl_display *display, + struct wl_object *object, wl_client_connect_func_t func) { - struct wl_object_ref *ref; + struct wl_global *global; - ref = malloc(sizeof *ref); - if (ref == NULL) + global = malloc(sizeof *global); + if (global == NULL) return -1; - ref->object = object; - wl_list_insert(display->global_list.prev, &ref->link); + global->object = object; + global->func = func; + wl_list_insert(display->global_list.prev, &global->link); return 0; } diff --git a/wayland.h b/wayland.h index ff435721..09567e08 100644 --- a/wayland.h +++ b/wayland.h @@ -85,7 +85,10 @@ int wl_display_add_socket(struct wl_display *display, const char *name, size_t n void wl_display_run(struct wl_display *display); void wl_display_add_object(struct wl_display *display, struct wl_object *object); -int wl_display_add_global(struct wl_display *display, struct wl_object *object); + +typedef void (*wl_client_connect_func_t)(struct wl_client *client, struct wl_object *global); + +int wl_display_add_global(struct wl_display *display, struct wl_object *object, wl_client_connect_func_t func); struct wl_compositor { struct wl_object base; @@ -120,6 +123,11 @@ struct wl_surface_interface { int32_t x, int32_t y, int32_t width, int32_t height); }; +void +wl_client_post_event(struct wl_client *client, + struct wl_object *sender, + uint32_t event, ...); + void wl_surface_post_event(struct wl_surface *surface, struct wl_object *sender,