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,