From ee02ca6fa489a99ddec5d1542d51cce9948d39a9 Mon Sep 17 00:00:00 2001 From: =?utf8?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 f3358b4..2760706 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: @@ -267,6 +280,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 1a41217..fd15839 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 4c61810..4ec40ab 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 c71cfdc..76a80c5 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 69f785c..f3ff5b0 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 6ad1887..0fe2a8d 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 ff43572..09567e0 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; @@ -121,6 +124,11 @@ struct wl_surface_interface { }; 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, uint32_t event, ...); -- 2.7.4