From 9074db5d626e01d6d310cfed11b77827f3284c22 Mon Sep 17 00:00:00 2001 From: Casey Dahlin Date: Thu, 19 Apr 2012 22:50:09 -0400 Subject: [PATCH] Send surface enter/leave events These new protocol events allow us to tell which outputs a surface is on, and potentially update where we allocate our buffers from. Signed-off-by: Casey Dahlin --- clients/window.c | 18 ++++++++++++++++++ src/compositor.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- src/compositor.h | 7 +++++++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/clients/window.c b/clients/window.c index e79747bb..ecb9bc37 100644 --- a/clients/window.c +++ b/clients/window.c @@ -2176,6 +2176,23 @@ window_damage(struct window *window, int32_t x, int32_t y, wl_surface_damage(window->surface, x, y, width, height); } +static void +surface_enter(void *data, + struct wl_surface *wl_surface, struct wl_output *output) +{ +} + +static void +surface_leave(void *data, + struct wl_surface *wl_surface, struct wl_output *output) +{ +} + +static const struct wl_surface_listener surface_listener = { + surface_enter, + surface_leave +}; + static struct window * window_create_internal(struct display *display, struct window *parent) { @@ -2189,6 +2206,7 @@ window_create_internal(struct display *display, struct window *parent) window->display = display; window->parent = parent; window->surface = wl_compositor_create_surface(display->compositor); + wl_surface_add_listener(window->surface, &surface_listener, window); if (display->shell) { window->shell_surface = wl_shell_get_shell_surface(display->shell, diff --git a/src/compositor.c b/src/compositor.c index 17a0cc6e..ddbc0773 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1138,19 +1138,48 @@ find_resource_for_client(struct wl_list *list, struct wl_client *client) return NULL; } +static void +weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask) +{ + uint32_t different = es->output_mask ^ mask; + uint32_t entered = mask & different; + uint32_t left = es->output_mask & different; + struct weston_output *output; + struct wl_resource *resource; + struct wl_client *client = es->surface.resource.client; + + if (es->surface.resource.client == NULL) + return; + if (different == 0) + return; + + es->output_mask = mask; + wl_list_for_each(output, &es->compositor->output_list, link) { + if (1 << output->id & different) + resource = + find_resource_for_client(&output->resource_list, + client); + if (1 << output->id & entered) + wl_surface_send_enter(&es->surface.resource, resource); + if (1 << output->id & left) + wl_surface_send_leave(&es->surface.resource, resource); + } +} + WL_EXPORT void weston_surface_assign_output(struct weston_surface *es) { struct weston_compositor *ec = es->compositor; struct weston_output *output, *new_output; pixman_region32_t region; - uint32_t max, area; + uint32_t max, area, mask; pixman_box32_t *e; weston_surface_update_transform(es); new_output = NULL; max = 0; + mask = 0; pixman_region32_init(®ion); wl_list_for_each(output, &ec->output_list, link) { pixman_region32_intersect(®ion, &es->transform.boundingbox, @@ -1159,6 +1188,9 @@ weston_surface_assign_output(struct weston_surface *es) e = pixman_region32_extents(®ion); area = (e->x2 - e->x1) * (e->y2 - e->y1); + if (area > 0) + mask |= 1 << output->id; + if (area >= max) { new_output = output; max = area; @@ -1167,6 +1199,8 @@ weston_surface_assign_output(struct weston_surface *es) pixman_region32_fini(®ion); es->output = new_output; + weston_surface_update_output_mask(es, mask); + if (!wl_list_empty(&es->frame_callback_list)) { wl_list_insert_list(new_output->frame_callback_list.prev, &es->frame_callback_list); @@ -1962,7 +1996,7 @@ handle_drag_surface_destroy(struct wl_listener *listener, void *data) device->drag_surface = NULL; } -static void unbind_input_device(struct wl_resource *resource) +static void unbind_resource(struct wl_resource *resource) { wl_list_remove(&resource->link); free(resource); @@ -1978,7 +2012,7 @@ bind_input_device(struct wl_client *client, resource = wl_client_add_object(client, &wl_input_device_interface, &input_device_interface, id, data); wl_list_insert(&device->resource_list, &resource->link); - resource->destroy = unbind_input_device; + resource->destroy = unbind_resource; } static void @@ -2152,6 +2186,9 @@ bind_output(struct wl_client *client, resource = wl_client_add_object(client, &wl_output_interface, NULL, id, data); + wl_list_insert(&output->resource_list, &resource->link); + resource->destroy = unbind_resource; + wl_output_send_geometry(resource, output->x, output->y, @@ -2275,6 +2312,7 @@ weston_output_destroy(struct weston_output *output) pixman_region32_fini(&output->region); pixman_region32_fini(&output->previous_damage); + output->compositor->output_id_pool &= ~(1 << output->id); wl_display_remove_global(c->wl_display, output->global); } @@ -2364,6 +2402,7 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c, weston_output_damage(output); wl_list_init(&output->frame_callback_list); + wl_list_init(&output->resource_list); output->id = ffs(~output->compositor->output_id_pool) - 1; output->compositor->output_id_pool |= 1 << output->id; diff --git a/src/compositor.h b/src/compositor.h index 0ef342b5..648b045a 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -76,6 +76,7 @@ struct weston_output { uint32_t id; struct wl_list link; + struct wl_list resource_list; struct wl_global *global; struct weston_compositor *compositor; struct weston_matrix matrix; @@ -339,6 +340,12 @@ struct weston_surface { */ struct weston_output *output; + /* + * A more complete representation of all outputs this surface is + * displayed on. + */ + uint32_t output_mask; + struct wl_list frame_callback_list; EGLImageKHR image;