diff --git a/clients/simple-egl.c b/clients/simple-egl.c index 95604ded..13c33bd9 100644 --- a/clients/simple-egl.c +++ b/clients/simple-egl.c @@ -63,6 +63,7 @@ struct window { struct wl_egl_window *native; struct wl_surface *surface; + struct wl_shell_surface *shell_surface; EGLSurface egl_surface; }; @@ -198,6 +199,8 @@ create_surface(struct window *window) }; window->surface = wl_compositor_create_surface(display->compositor); + window->shell_surface = wl_shell_get_shell_surface(display->shell, + window->surface); window->native = wl_egl_window_create(window->surface, window->geometry.width, @@ -208,7 +211,7 @@ create_surface(struct window *window) window->native, surface_attribs); - wl_shell_set_toplevel(display->shell, window->surface); + wl_shell_surface_set_toplevel(window->shell_surface); ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface, window->egl_surface, window->display->egl.ctx); diff --git a/clients/simple-shm.c b/clients/simple-shm.c index c112303f..8a760aea 100644 --- a/clients/simple-shm.c +++ b/clients/simple-shm.c @@ -45,6 +45,7 @@ struct window { struct display *display; int width, height; struct wl_surface *surface; + struct wl_shell_surface *shell_surface; struct wl_buffer *buffer; void *data; }; @@ -100,12 +101,14 @@ create_window(struct display *display, int width, int height) window->width = width; window->height = height; window->surface = wl_compositor_create_surface(display->compositor); + window->shell_surface = wl_shell_get_shell_surface(display->shell, + window->surface); window->buffer = create_shm_buffer(display, width, height, WL_SHM_FORMAT_XRGB32, &window->data); - wl_shell_set_toplevel(display->shell, window->surface); + wl_shell_surface_set_toplevel(window->shell_surface); return window; } diff --git a/clients/window.c b/clients/window.c index 5324795d..0f242500 100644 --- a/clients/window.c +++ b/clients/window.c @@ -103,6 +103,7 @@ struct window { struct display *display; struct window *parent; struct wl_surface *surface; + struct wl_shell_surface *shell_surface; char *title; struct rectangle allocation, saved_allocation, server_allocation; int x, y; @@ -749,19 +750,17 @@ window_get_resize_dx_dy(struct window *window, int *x, int *y) static void window_set_type(struct window *window) { - struct display *display = window->display; - switch (window->type) { case TYPE_FULLSCREEN: - wl_shell_set_fullscreen(display->shell, window->surface); + wl_shell_surface_set_fullscreen(window->shell_surface); break; case TYPE_TOPLEVEL: - wl_shell_set_toplevel(display->shell, window->surface); + wl_shell_surface_set_toplevel(window->shell_surface); break; case TYPE_TRANSIENT: - wl_shell_set_transient(display->shell, window->surface, - window->parent->surface, - window->x, window->y, 0); + wl_shell_surface_set_transient(window->shell_surface, + window->parent->shell_surface, + window->x, window->y, 0); break; case TYPE_CUSTOM: break; @@ -1009,6 +1008,7 @@ window_destroy(struct window *window) input->keyboard_focus = NULL; } + wl_shell_surface_destroy(window->shell_surface); wl_surface_destroy(window->surface); wl_list_remove(&window->link); free(window); @@ -1104,6 +1104,12 @@ window_get_wl_surface(struct window *window) return window->surface; } +struct wl_shell_surface * +window_get_wl_shell_surface(struct window *window) +{ + return window->shell_surface; +} + static int get_pointer_location(struct window *window, int32_t x, int32_t y) { @@ -1269,8 +1275,8 @@ window_handle_button(void *data, button == BTN_LEFT && state == 1) { switch (location) { case WINDOW_TITLEBAR: - wl_shell_move(window->display->shell, - window->surface, input_device, time); + wl_shell_surface_move(window->shell_surface, + input_device, time); break; case WINDOW_RESIZING_TOP: case WINDOW_RESIZING_BOTTOM: @@ -1280,9 +1286,9 @@ window_handle_button(void *data, case WINDOW_RESIZING_TOP_RIGHT: case WINDOW_RESIZING_BOTTOM_LEFT: case WINDOW_RESIZING_BOTTOM_RIGHT: - wl_shell_resize(window->display->shell, - window->surface, input_device, time, - location); + wl_shell_surface_resize(window->shell_surface, + input_device, time, + location); break; case WINDOW_CLIENT_AREA: if (window->button_handler) @@ -1685,17 +1691,16 @@ input_receive_selection_data(struct input *input, const char *mime_type, void window_move(struct window *window, struct input *input, uint32_t time) { - if (window->display->shell) - wl_shell_move(window->display->shell, - window->surface, input->input_device, time); + wl_shell_surface_move(window->shell_surface, + input->input_device, time); } static void -handle_configure(void *data, struct wl_shell *shell, +handle_configure(void *data, struct wl_shell_surface *shell_surface, uint32_t time, uint32_t edges, - struct wl_surface *surface, int32_t width, int32_t height) + int32_t width, int32_t height) { - struct window *window = wl_surface_get_user_data(surface); + struct window *window = data; int32_t child_width, child_height; /* FIXME: this is probably the wrong place to check for width @@ -1722,7 +1727,7 @@ handle_configure(void *data, struct wl_shell *shell, } } -static const struct wl_shell_listener shell_listener = { +static const struct wl_shell_surface_listener shell_surface_listener = { handle_configure, }; @@ -1961,6 +1966,8 @@ window_create_internal(struct display *display, struct window *parent, window->display = display; window->parent = parent; window->surface = wl_compositor_create_surface(display->compositor); + window->shell_surface = wl_shell_get_shell_surface(display->shell, + window->surface); window->allocation.x = 0; window->allocation.y = 0; window->allocation.width = width; @@ -1984,6 +1991,9 @@ window_create_internal(struct display *display, struct window *parent, wl_surface_set_user_data(window->surface, window); wl_list_insert(display->window_list.prev, &window->link); + wl_shell_surface_add_listener(window->shell_surface, + &shell_surface_listener, window); + return window; } @@ -2128,7 +2138,6 @@ display_handle_global(struct wl_display *display, uint32_t id, display_add_input(d, id); } else if (strcmp(interface, "wl_shell") == 0) { d->shell = wl_display_bind(display, id, &wl_shell_interface); - wl_shell_add_listener(d->shell, &shell_listener, d); } else if (strcmp(interface, "wl_shm") == 0) { d->shm = wl_display_bind(display, id, &wl_shm_interface); } else if (strcmp(interface, "wl_data_device_manager") == 0) { diff --git a/clients/window.h b/clients/window.h index 7c62f11f..8d17340f 100644 --- a/clients/window.h +++ b/clients/window.h @@ -228,6 +228,9 @@ window_get_surface(struct window *window); struct wl_surface * window_get_wl_surface(struct window *window); +struct wl_shell_surface * +window_get_wl_shell_surface(struct window *window); + void window_flush(struct window *window); diff --git a/compositor/compositor-wayland.c b/compositor/compositor-wayland.c index 790fe96f..237f56b9 100644 --- a/compositor/compositor-wayland.c +++ b/compositor/compositor-wayland.c @@ -67,6 +67,7 @@ struct wayland_output { struct { struct wl_surface *surface; + struct wl_shell_surface *shell_surface; struct wl_egl_window *egl_window; } parent; EGLSurface egl_surface; @@ -281,7 +282,11 @@ wayland_compositor_create_output(struct wayland_compositor *c, return -1; } - wl_shell_set_toplevel(c->parent.shell, output->parent.surface); + output->parent.shell_surface = + wl_shell_get_shell_surface(c->parent.shell, + output->parent.surface); + /* FIXME: add shell_surface listener for resizing */ + wl_shell_surface_set_toplevel(output->parent.shell_surface); glClearColor(0, 0, 0, 0.5); @@ -346,23 +351,6 @@ static const struct wl_output_listener output_listener = { display_handle_mode }; -/* parent shell interface */ -static void -handle_configure(void *data, struct wl_shell *shell, - uint32_t time, uint32_t edges, - struct wl_surface *surface, int32_t width, int32_t height) -{ -#if 0 - struct output *output = wl_surface_get_user_data(surface); - - /* FIXME: add resize? */ -#endif -} - -static const struct wl_shell_listener shell_listener = { - handle_configure, -}; - /* parent input interface */ static void input_handle_motion(void *data, struct wl_input_device *input_device, @@ -482,7 +470,6 @@ display_handle_global(struct wl_display *display, uint32_t id, } else if (strcmp(interface, "wl_shell") == 0) { c->parent.shell = wl_display_bind(display, id, &wl_shell_interface); - wl_shell_add_listener(c->parent.shell, &shell_listener, c); } } diff --git a/compositor/shell.c b/compositor/shell.c index 509d4488..11907b33 100644 --- a/compositor/shell.c +++ b/compositor/shell.c @@ -70,8 +70,10 @@ enum shell_surface_type { }; struct shell_surface { + struct wl_resource resource; + struct wlsc_surface *surface; - struct wl_listener destroy_listener; + struct wl_listener surface_destroy_listener; enum shell_surface_type type; int32_t saved_x, saved_y; @@ -86,47 +88,10 @@ struct wlsc_move_grab { int32_t dx, dy; }; -static void -destroy_shell_surface(struct shell_surface *priv) -{ - wl_list_remove(&priv->destroy_listener.link); - wl_list_remove(&priv->link); - free(priv); -} - -static void -handle_shell_surface_destroy(struct wl_listener *listener, - struct wl_resource *resource, uint32_t time) -{ - struct shell_surface *priv = - container_of(listener, struct shell_surface, destroy_listener); - destroy_shell_surface(priv); -} - static struct shell_surface * get_shell_surface(struct wlsc_surface *surface) { - struct shell_surface *priv; - - if (surface->shell_priv) - return surface->shell_priv; - - priv = calloc(1, sizeof *priv); - if (!priv) - return NULL; - - priv->destroy_listener.func = handle_shell_surface_destroy; - wl_list_insert(surface->surface.resource.destroy_listener_list.prev, - &priv->destroy_listener.link); - - surface->shell_priv = priv; - priv->surface = surface; - /* init link so its safe to always remove it in destroy_shell_surface */ - wl_list_init(&priv->link); - - priv->type = SHELL_SURFACE_NORMAL; - - return priv; + return surface->shell_priv; } static void @@ -185,14 +150,13 @@ wlsc_surface_move(struct wlsc_surface *es, } static void -shell_move(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *surface_resource, - struct wl_resource *input_resource, uint32_t time) +shell_surface_move(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *input_resource, uint32_t time) { struct wlsc_input_device *wd = input_resource->data; - struct wlsc_surface *es = surface_resource->data; + struct shell_surface *shsurf = resource->data; - if (wlsc_surface_move(es, wd, time) < 0) + if (wlsc_surface_move(shsurf->surface, wd, time) < 0) wl_resource_post_no_memory(resource); } @@ -200,8 +164,7 @@ struct wlsc_resize_grab { struct wl_grab grab; uint32_t edges; int32_t dx, dy, width, height; - struct wlsc_surface *surface; - struct wl_resource *resource; + struct shell_surface *shsurf; }; static void @@ -210,28 +173,27 @@ resize_grab_motion(struct wl_grab *grab, { struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab; struct wl_input_device *device = grab->input_device; - struct wl_surface *surface = &resize->surface->surface; int32_t width, height; - if (resize->edges & WL_SHELL_RESIZE_LEFT) { + if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) { width = device->grab_x - x + resize->width; - } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) { + } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) { width = x - device->grab_x + resize->width; } else { width = resize->width; } - if (resize->edges & WL_SHELL_RESIZE_TOP) { + if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) { height = device->grab_y - y + resize->height; - } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) { + } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) { height = y - device->grab_y + resize->height; } else { height = resize->height; } - wl_resource_post_event(resize->resource, - WL_SHELL_CONFIGURE, time, resize->edges, - surface, width, height); + wl_resource_post_event(&resize->shsurf->resource, + WL_SHELL_SURFACE_CONFIGURE, time, resize->edges, + width, height); } static void @@ -253,12 +215,12 @@ static const struct wl_grab_interface resize_grab_interface = { }; static int -wlsc_surface_resize(struct wlsc_surface *es, +wlsc_surface_resize(struct shell_surface *shsurf, struct wlsc_input_device *wd, - uint32_t time, uint32_t edges, - struct wl_resource *resource) + uint32_t time, uint32_t edges) { struct wlsc_resize_grab *resize; + struct wlsc_surface *es = shsurf->surface; enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR; /* FIXME: Reject if fullscreen */ @@ -273,36 +235,35 @@ wlsc_surface_resize(struct wlsc_surface *es, resize->dy = es->y - wd->input_device.grab_y; resize->width = es->width; resize->height = es->height; - resize->surface = es; - resize->resource = resource; + resize->shsurf = shsurf; if (edges == 0 || edges > 15 || (edges & 3) == 3 || (edges & 12) == 12) return 0; switch (edges) { - case WL_SHELL_RESIZE_TOP: + case WL_SHELL_SURFACE_RESIZE_TOP: pointer = WLSC_POINTER_TOP; break; - case WL_SHELL_RESIZE_BOTTOM: + case WL_SHELL_SURFACE_RESIZE_BOTTOM: pointer = WLSC_POINTER_BOTTOM; break; - case WL_SHELL_RESIZE_LEFT: + case WL_SHELL_SURFACE_RESIZE_LEFT: pointer = WLSC_POINTER_LEFT; break; - case WL_SHELL_RESIZE_TOP_LEFT: + case WL_SHELL_SURFACE_RESIZE_TOP_LEFT: pointer = WLSC_POINTER_TOP_LEFT; break; - case WL_SHELL_RESIZE_BOTTOM_LEFT: + case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT: pointer = WLSC_POINTER_BOTTOM_LEFT; break; - case WL_SHELL_RESIZE_RIGHT: + case WL_SHELL_SURFACE_RESIZE_RIGHT: pointer = WLSC_POINTER_RIGHT; break; - case WL_SHELL_RESIZE_TOP_RIGHT: + case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT: pointer = WLSC_POINTER_TOP_RIGHT; break; - case WL_SHELL_RESIZE_BOTTOM_RIGHT: + case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT: pointer = WLSC_POINTER_BOTTOM_RIGHT; break; } @@ -319,51 +280,46 @@ wlsc_surface_resize(struct wlsc_surface *es, } static void -shell_resize(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *surface_resource, - struct wl_resource *input_resource, uint32_t time, uint32_t edges) +shell_surface_resize(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *input_resource, uint32_t time, + uint32_t edges) { struct wlsc_input_device *wd = input_resource->data; - struct wlsc_surface *es = surface_resource->data; + struct shell_surface *shsurf = resource->data; /* FIXME: Reject if fullscreen */ - if (wlsc_surface_resize(es, wd, time, edges, resource) < 0) + if (wlsc_surface_resize(shsurf, wd, time, edges) < 0) wl_resource_post_no_memory(resource); } static void -shell_set_toplevel(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *surface_resource) +shell_surface_set_toplevel(struct wl_client *client, + struct wl_resource *resource) { - struct wlsc_surface *es = surface_resource->data; - struct shell_surface *priv; + struct shell_surface *shsurf = resource->data; + struct wlsc_surface *es = shsurf->surface; - priv = get_shell_surface(es); - if (priv->type == SHELL_SURFACE_FULLSCREEN) { - es->x = priv->saved_x; - es->y = priv->saved_y; + if (shsurf->type == SHELL_SURFACE_FULLSCREEN) { + es->x = shsurf->saved_x; + es->y = shsurf->saved_y; } wlsc_surface_damage(es); - priv->type = SHELL_SURFACE_TOPLEVEL; + shsurf->type = SHELL_SURFACE_TOPLEVEL; es->fullscreen_output = NULL; } static void -shell_set_transient(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *surface_resource, - struct wl_resource *parent_resource, - int x, int y, uint32_t flags) +shell_surface_set_transient(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *parent_resource, + int x, int y, uint32_t flags) { - struct wlsc_surface *es = surface_resource->data; + struct shell_surface *shsurf = resource->data; + struct wlsc_surface *es = shsurf->surface; struct wlsc_surface *pes = parent_resource->data; - struct shell_surface *priv; - - priv = get_shell_surface(es); /* assign to parents output */ es->output = pes->output; @@ -372,20 +328,17 @@ shell_set_transient(struct wl_client *client, es->y = pes->y + y; wlsc_surface_damage(es); - priv->type = SHELL_SURFACE_TRANSIENT; + shsurf->type = SHELL_SURFACE_TRANSIENT; } static void -shell_set_fullscreen(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *surface_resource) +shell_surface_set_fullscreen(struct wl_client *client, + struct wl_resource *resource) { - struct wlsc_surface *es = surface_resource->data; + struct shell_surface *shsurf = resource->data; + struct wlsc_surface *es = shsurf->surface; struct wlsc_output *output; - struct shell_surface *priv; - - priv = get_shell_surface(es); /* FIXME: Fullscreen on first output */ /* FIXME: Handle output going away */ @@ -393,21 +346,87 @@ shell_set_fullscreen(struct wl_client *client, struct wlsc_output, link); es->output = output; - priv->saved_x = es->x; - priv->saved_y = es->y; + shsurf->saved_x = es->x; + shsurf->saved_y = es->y; es->x = (output->current->width - es->width) / 2; es->y = (output->current->height - es->height) / 2; es->fullscreen_output = output; wlsc_surface_damage(es); - priv->type = SHELL_SURFACE_FULLSCREEN; + shsurf->type = SHELL_SURFACE_FULLSCREEN; } -static const struct wl_shell_interface shell_interface = { - shell_move, - shell_resize, - shell_set_toplevel, - shell_set_transient, - shell_set_fullscreen +static const struct wl_shell_surface_interface shell_surface_implementation = { + shell_surface_move, + shell_surface_resize, + shell_surface_set_toplevel, + shell_surface_set_transient, + shell_surface_set_fullscreen +}; + +static void +destroy_shell_surface(struct wl_resource *resource) +{ + struct shell_surface *shsurf = resource->data; + + /* in case cleaning up a dead client destroys shell_surface first */ + if (shsurf->surface) + wl_list_remove(&shsurf->surface_destroy_listener.link); + + wl_list_remove(&shsurf->link); + free(shsurf); +} + +static void +shell_handle_surface_destroy(struct wl_listener *listener, + struct wl_resource *resource, uint32_t time) +{ + struct shell_surface *shsurf = container_of(listener, + struct shell_surface, + surface_destroy_listener); + + shsurf->surface = NULL; + wl_resource_destroy(&shsurf->resource, time); +} + +static void +shell_create_shell_surface(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *surface_resource) +{ + struct wlsc_surface *surface = surface_resource->data; + struct shell_surface *shsurf; + + shsurf = calloc(1, sizeof *shsurf); + if (!shsurf) { + wl_resource_post_no_memory(resource); + return; + } + + shsurf->resource.destroy = destroy_shell_surface; + shsurf->resource.object.id = id; + shsurf->resource.object.interface = &wl_shell_surface_interface; + shsurf->resource.object.implementation = + (void (**)(void)) &shell_surface_implementation; + shsurf->resource.data = shsurf; + + shsurf->surface = surface; + shsurf->surface_destroy_listener.func = shell_handle_surface_destroy; + wl_list_insert(surface->surface.resource.destroy_listener_list.prev, + &shsurf->surface_destroy_listener.link); + + /* init link so its safe to always remove it in destroy_shell_surface */ + wl_list_init(&shsurf->link); + + shsurf->type = SHELL_SURFACE_NORMAL; + + surface->shell_priv = shsurf; + + wl_client_add_resource(client, &shsurf->resource); +} + +static const struct wl_shell_interface shell_implementation = { + shell_create_shell_surface }; static void @@ -567,13 +586,13 @@ move_binding(struct wl_input_device *device, uint32_t time, { struct wlsc_surface *surface = (struct wlsc_surface *) device->pointer_focus; - struct shell_surface *priv; + struct shell_surface *shsurf; if (surface == NULL) return; - priv = get_shell_surface(surface); - switch (priv->type) { + shsurf = get_shell_surface(surface); + switch (shsurf->type) { case SHELL_SURFACE_PANEL: case SHELL_SURFACE_BACKGROUND: case SHELL_SURFACE_FULLSCREEN: @@ -591,16 +610,15 @@ resize_binding(struct wl_input_device *device, uint32_t time, { struct wlsc_surface *surface = (struct wlsc_surface *) device->pointer_focus; - struct wl_resource *resource; uint32_t edges = 0; int32_t x, y; - struct shell_surface *priv; + struct shell_surface *shsurf; if (surface == NULL) return; - priv = get_shell_surface(surface); - switch (priv->type) { + shsurf = get_shell_surface(surface); + switch (shsurf->type) { case SHELL_SURFACE_PANEL: case SHELL_SURFACE_BACKGROUND: case SHELL_SURFACE_FULLSCREEN: @@ -613,25 +631,21 @@ resize_binding(struct wl_input_device *device, uint32_t time, y = device->grab_y - surface->y; if (x < surface->width / 3) - edges |= WL_SHELL_RESIZE_LEFT; + edges |= WL_SHELL_SURFACE_RESIZE_LEFT; else if (x < 2 * surface->width / 3) edges |= 0; else - edges |= WL_SHELL_RESIZE_RIGHT; + edges |= WL_SHELL_SURFACE_RESIZE_RIGHT; if (y < surface->height / 3) - edges |= WL_SHELL_RESIZE_TOP; + edges |= WL_SHELL_SURFACE_RESIZE_TOP; else if (y < 2 * surface->height / 3) edges |= 0; else - edges |= WL_SHELL_RESIZE_BOTTOM; - - resource = /* Find shell resource for surface client */ 0; - - /* ... or use wl_shell_surface */ + edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM; - wlsc_surface_resize(surface, (struct wlsc_input_device *) device, - time, edges, resource); + wlsc_surface_resize(shsurf, (struct wlsc_input_device *) device, + time, edges); } static void @@ -889,7 +903,7 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id) struct wl_shell *shell = data; wl_client_add_object(client, &wl_shell_interface, - &shell_interface, id, shell); + &shell_implementation, id, shell); } static void