From b31ce4220cea6acede2ae2af1b19a3a7d4b81fc6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 18 Mar 2018 15:09:37 -0400 Subject: Add broken test client and rootston stubs --- rootston/layer_shell.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 rootston/layer_shell.c (limited to 'rootston/layer_shell.c') diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c new file mode 100644 index 00000000..50bf6466 --- /dev/null +++ b/rootston/layer_shell.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "rootston/desktop.h" +#include "rootston/layers.h" +#include "rootston/server.h" + +static void handle_destroy(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_surface_commit(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_map(struct wl_listener *listener, void *data) { + // TODO +} + +static void handle_unmap(struct wl_listener *listener, void *data) { + // TODO +} + +void handle_layer_shell_surface(struct wl_listener *listener, void *data) { + struct wlr_layer_surface *layer_surface = data; + struct roots_desktop *desktop = + wl_container_of(listener, desktop, layer_shell_surface); + wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d", + layer_surface->namespace, layer_surface->layer); + + struct roots_layer_surface *roots_surface = + calloc(1, sizeof(struct roots_layer_surface)); + if (!roots_surface) { + return; + } + roots_surface->surface_commit.notify = handle_surface_commit; + wl_signal_add(&layer_surface->surface->events.commit, + &roots_surface->surface_commit); + roots_surface->destroy.notify = handle_destroy; + wl_signal_add(&layer_surface->events.destroy, &roots_surface->destroy); + roots_surface->map.notify = handle_map; + wl_signal_add(&layer_surface->events.map, &roots_surface->map); + roots_surface->unmap.notify = handle_unmap; + wl_signal_add(&layer_surface->events.unmap, &roots_surface->unmap); + + roots_surface->layer_surface = layer_surface; + + wl_list_insert(&desktop->layers[layer_surface->layer], &roots_surface->link); +} -- cgit v1.2.3 From 4bf936360d42fb5b96a44fd17028ae66fc462362 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 19 Mar 2018 23:11:37 -0400 Subject: Arrange & render layer surfaces --- examples/layer-shell.c | 7 +- include/rootston/desktop.h | 2 - include/rootston/layers.h | 3 + include/rootston/output.h | 3 + include/wlr/types/wlr_layer_shell.h | 3 +- protocol/wlr-layer-shell-unstable-v1.xml | 28 +++++-- render/egl.c | 2 +- rootston/desktop.c | 4 - rootston/layer_shell.c | 135 ++++++++++++++++++++++++++++++- rootston/output.c | 57 ++++++++++--- types/wlr_layer_shell.c | 26 +++++- 11 files changed, 235 insertions(+), 35 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index d2e07a90..b5542f7a 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -23,7 +23,7 @@ struct wl_callback *frame_callback; static uint32_t output = 0; static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; static uint32_t anchor = 0; -static uint32_t width = 256, height = 256; +static int32_t width = 256, height = 256; static void draw(void); @@ -98,7 +98,7 @@ int main(int argc, char **argv) { char *namespace = "wlroots"; bool found; int c; - while ((c = getopt(argc, argv, "w:h:o:")) != -1) { + while ((c = getopt(argc, argv, "w:h:o:l:a:")) != -1) { switch (c) { case 'o': output = atoi(optarg); @@ -190,7 +190,10 @@ int main(int argc, char **argv) { struct zwlr_layer_surface_v1 *layer_surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, wl_surface, wl_output, layer, namespace); + zwlr_layer_surface_v1_set_size(layer_surface, width, height); zwlr_layer_surface_v1_set_anchor(layer_surface, anchor); + zwlr_layer_surface_v1_add_listener(layer_surface, + &layer_surface_listener, layer_surface); // TODO: margin, interactivity, exclusive zone wl_surface_commit(wl_surface); wl_display_dispatch(display); diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index ad7654a1..92cc6d9d 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -29,8 +29,6 @@ struct roots_desktop { struct wl_list views; // roots_view::link - struct wl_list layers[4]; // layer_surface::link - struct wl_list outputs; // roots_output::link struct timespec last_frame; diff --git a/include/rootston/layers.h b/include/rootston/layers.h index 269056ea..f432d53d 100644 --- a/include/rootston/layers.h +++ b/include/rootston/layers.h @@ -14,6 +14,9 @@ struct roots_layer_surface { struct wl_listener map; struct wl_listener unmap; struct wl_listener surface_commit; + + bool configured; + struct wlr_box geo; }; #endif diff --git a/include/rootston/output.h b/include/rootston/output.h index a852a204..5545d76a 100644 --- a/include/rootston/output.h +++ b/include/rootston/output.h @@ -14,6 +14,7 @@ struct roots_output { struct wl_list link; // roots_desktop:outputs struct roots_view *fullscreen_view; + struct wl_list layers[4]; // layer_surface::link struct timespec last_frame; struct wlr_output_damage *damage; @@ -35,5 +36,7 @@ void output_damage_from_view(struct roots_output *output, struct roots_view *view); void output_damage_whole_drag_icon(struct roots_output *output, struct roots_drag_icon *icon); +void output_damage_whole_surface(struct wlr_surface *surface, + double lx, double ly, float rotation, void *data); #endif diff --git a/include/wlr/types/wlr_layer_shell.h b/include/wlr/types/wlr_layer_shell.h index 0807fe8d..3002345d 100644 --- a/include/wlr/types/wlr_layer_shell.h +++ b/include/wlr/types/wlr_layer_shell.h @@ -42,14 +42,12 @@ struct wlr_layer_client { }; struct wlr_layer_surface_state { - // Client uint32_t anchor; uint32_t exclusive_zone; struct { uint32_t top, right, bottom, left; } margin; bool keyboard_interactive; - // Server uint32_t width, height; }; @@ -61,6 +59,7 @@ struct wlr_layer_surface_configure { struct wlr_layer_surface { struct wlr_surface *surface; + struct wlr_output *output; struct wlr_layer_client *client; struct wl_resource *resource; struct wl_list link; // wlr_layer_client:surfaces diff --git a/protocol/wlr-layer-shell-unstable-v1.xml b/protocol/wlr-layer-shell-unstable-v1.xml index c4f2a7e3..d6de59ab 100644 --- a/protocol/wlr-layer-shell-unstable-v1.xml +++ b/protocol/wlr-layer-shell-unstable-v1.xml @@ -86,11 +86,27 @@ are designed to be rendered as a layer of a stacked desktop-like environment. - Layer surface state (anchor, exclusive zone, margin, interactivity) is - double-buffered, and will be applied at the time wl_surface.commit of the - corresponding wl_surface is called. + Layer surface state (size, anchor, exclusive zone, margin, interactivity) + is double-buffered, and will be applied at the time wl_surface.commit of + the corresponding wl_surface is called. + + + Sets the size of the surface in pixels. The compositor will display the + surface centered with respect to its anchors. + + If you pass -1 for either value, the compositor will assign it and + inform you of the assignment in the configure event. You must set your + anchor to opposite edges in the dimensions you omit; not doing so is a + protocol error. Both values are -1 by default. + + Size is double-buffered, see wl_surface.commit. + + + + + Requests that the compositor anchor the surface to the specified edges @@ -222,9 +238,9 @@ - - + + + diff --git a/render/egl.c b/render/egl.c index f2966774..d230f589 100644 --- a/render/egl.c +++ b/render/egl.c @@ -426,7 +426,7 @@ int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, int **formats) { if (!egl->egl_exts.dmabuf_import || !egl->egl_exts.dmabuf_import_modifiers) { - wlr_log(L_ERROR, "dmabuf extension not present"); + wlr_log(L_DEBUG, "dmabuf extension not present"); return -1; } diff --git a/rootston/desktop.c b/rootston/desktop.c index f00fc63f..015a8215 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -719,10 +719,6 @@ struct roots_desktop *desktop_create(struct roots_server *server, wl_signal_add(&desktop->layer_shell->events.new_surface, &desktop->layer_shell_surface); desktop->layer_shell_surface.notify = handle_layer_shell_surface; - for (size_t i = 0; - i < sizeof(desktop->layers) / sizeof(desktop->layers[0]); ++i) { - wl_list_init(&desktop->layers[i]); - } #ifdef WLR_HAS_XWAYLAND const char *cursor_theme = NULL; diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 50bf6466..25e683fe 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -8,8 +8,112 @@ #include #include "rootston/desktop.h" #include "rootston/layers.h" +#include "rootston/output.h" #include "rootston/server.h" +static void apply_exclusive(struct wlr_box *output_area, + uint32_t anchor, uint32_t exclusive) { + struct { + uint32_t anchors; + int *value; + int multiplier; + } edges[] = { + { + .anchors = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, + .value = &output_area->y, + .multiplier = 1, + }, + { + .anchors = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .value = &output_area->height, + .multiplier = -1, + }, + { + .anchors = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .value = &output_area->x, + .multiplier = 1, + }, + { + .anchors = + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .value = &output_area->width, + .multiplier = -1, + }, + }; + for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { + if ((anchor & edges[i].anchors)) { + edges[i].value += exclusive * edges[i].multiplier; + } + } +} + +static void arrange_layer(struct wlr_output *output, struct wl_list *list) { + struct wlr_box output_area = { .x = 0, .y = 0 }; + wlr_output_effective_resolution(output, + &output_area.width, &output_area.height); + struct roots_layer_surface *roots_surface; + wl_list_for_each(roots_surface, list, link) { + struct wlr_layer_surface *layer = roots_surface->layer_surface; + struct wlr_layer_surface_state *state = &layer->current; + struct wlr_box box = { .width = state->width, .height = state->height }; + // Horizontal axis + const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + if ((state->anchor & both_horiz) && box.width == -1) { + box.x = 0; + box.width = output_area.width; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + box.x = output_area.x; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + box.x = output_area.width - box.width; + } else { + box.x = (output_area.width / 2) - (box.width / 2); + } + // Vertical axis + const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + if ((state->anchor & both_vert) && box.height == -1) { + box.y = 0; + box.height = output_area.height; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + box.y = output_area.y; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + box.y = output_area.height - box.height; + } else { + box.y = (output_area.height / 2) - (box.height / 2); + } + wlr_log(L_DEBUG, "arranged layer at %dx%d@%d,%d", + box.width, box.height, box.x, box.y); + roots_surface->geo = box; + apply_exclusive(&output_area, state->anchor, state->exclusive_zone); + if (box.width != (int)state->width + || box.height != (int)state->height + || !roots_surface->configured) { + wlr_layer_surface_configure(layer, box.width, box.height); + roots_surface->configured = true; + } + } +} + +static void arrange_layers(struct wlr_output *_output) { + struct roots_output *output = _output->data; + size_t layers = sizeof(output->layers) / sizeof(output->layers[0]); + for (size_t i = 0; i < layers; ++i) { + arrange_layer(output->wlr_output, &output->layers[i]); + } +} + static void handle_destroy(struct wl_listener *listener, void *data) { // TODO } @@ -19,7 +123,13 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { } static void handle_map(struct wl_listener *listener, void *data) { - // TODO + struct wlr_layer_surface *layer_surface = data; + struct roots_layer_surface *layer = layer_surface->data; + struct wlr_output *wlr_output = layer_surface->output; + struct roots_output *output = wlr_output->data; + // TODO: This doesn't play right with output layouts and is also stupid + output_damage_whole_surface(layer_surface->surface, layer->geo.x, + layer->geo.y, 0, output); } static void handle_unmap(struct wl_listener *listener, void *data) { @@ -30,8 +140,14 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { struct wlr_layer_surface *layer_surface = data; struct roots_desktop *desktop = wl_container_of(listener, desktop, layer_shell_surface); - wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d", - layer_surface->namespace, layer_surface->layer); + wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d anchor %d %dx%d %d,%d,%d,%d", + layer_surface->namespace, layer_surface->layer, layer_surface->layer, + layer_surface->client_pending.width, + layer_surface->client_pending.height, + layer_surface->client_pending.margin.top, + layer_surface->client_pending.margin.right, + layer_surface->client_pending.margin.bottom, + layer_surface->client_pending.margin.left); struct roots_layer_surface *roots_surface = calloc(1, sizeof(struct roots_layer_surface)); @@ -49,6 +165,17 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&layer_surface->events.unmap, &roots_surface->unmap); roots_surface->layer_surface = layer_surface; + layer_surface->data = roots_surface; + + struct roots_output *output = layer_surface->output->data; + wl_list_insert(&output->layers[layer_surface->layer], &roots_surface->link); + + // Temporarily set the layer's current state to client_pending + // So that we can easily arrange it + struct wlr_layer_surface_state old_state = layer_surface->current; + layer_surface->current = layer_surface->client_pending; + + arrange_layers(output->wlr_output); - wl_list_insert(&desktop->layers[layer_surface->layer], &roots_surface->link); + layer_surface->current = old_state; } diff --git a/rootston/output.c b/rootston/output.c index 52ece54d..71497608 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -13,6 +13,7 @@ #include #include #include "rootston/config.h" +#include "rootston/layers.h" #include "rootston/output.h" #include "rootston/server.h" @@ -417,6 +418,21 @@ static void surface_send_frame_done(struct wlr_surface *surface, double lx, wlr_surface_send_frame_done(surface, when); } +static void render_layer( + struct roots_output *output, + const struct wlr_box *output_layout_box, + struct render_data *data, + struct wl_list *layer) { + struct roots_layer_surface *roots_surface; + wl_list_for_each(roots_surface, layer, link) { + struct wlr_layer_surface *layer = roots_surface->layer_surface; + render_surface(layer->surface, + roots_surface->geo.x + output_layout_box->x, + roots_surface->geo.y + output_layout_box->y, + 0, data); + } +} + static void render_output(struct roots_output *output) { struct wlr_output *wlr_output = output->wlr_output; struct roots_desktop *desktop = output->desktop; @@ -433,14 +449,15 @@ static void render_output(struct roots_output *output) { float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; + const struct wlr_box *output_box = + wlr_output_layout_get_box(desktop->layout, wlr_output); + // Check if we can delegate the fullscreen surface to the output if (output->fullscreen_view != NULL && output->fullscreen_view->wlr_surface != NULL) { struct roots_view *view = output->fullscreen_view; // Make sure the view is centered on screen - const struct wlr_box *output_box = - wlr_output_layout_get_box(desktop->layout, wlr_output); struct wlr_box view_box; view_get_box(view, &view_box); double view_x = (double)(output_box->width - view_box.width) / 2 + @@ -498,6 +515,11 @@ static void render_output(struct roots_output *output) { wlr_renderer_clear(renderer, clear_color); } + render_layer(output, output_box, &data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); + render_layer(output, output_box, &data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + // If a view is fullscreen on this output, render it if (output->fullscreen_view != NULL) { struct roots_view *view = output->fullscreen_view; @@ -520,20 +542,23 @@ static void render_output(struct roots_output *output) { render_surface, &data); } #endif - - goto renderer_end; - } - - // Render all views - struct roots_view *view; - wl_list_for_each_reverse(view, &desktop->views, link) { - render_view(view, &data); + } else { + // Render all views + struct roots_view *view; + wl_list_for_each_reverse(view, &desktop->views, link) { + render_view(view, &data); + } } // Render drag icons data.alpha = 1.0; drag_icons_for_each_surface(server->input, render_surface, &data); + render_layer(output, output_box, &data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); + render_layer(output, output_box, &data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); + renderer_end: wlr_renderer_scissor(renderer, NULL); wlr_renderer_end(renderer); @@ -603,7 +628,7 @@ static bool view_accept_damage(struct roots_output *output, return false; } -static void damage_whole_surface(struct wlr_surface *surface, +void output_damage_whole_surface(struct wlr_surface *surface, double lx, double ly, float rotation, void *data) { struct roots_output *output = data; @@ -647,13 +672,13 @@ void output_damage_whole_view(struct roots_output *output, } damage_whole_decoration(view, output); - view_for_each_surface(view, damage_whole_surface, output); + view_for_each_surface(view, output_damage_whole_surface, output); } void output_damage_whole_drag_icon(struct roots_output *output, struct roots_drag_icon *icon) { surface_for_each_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, 0, - damage_whole_surface, output); + output_damage_whole_surface, output); } static void damage_from_surface(struct wlr_surface *surface, @@ -781,6 +806,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { clock_gettime(CLOCK_MONOTONIC, &output->last_frame); output->desktop = desktop; output->wlr_output = wlr_output; + wlr_output->data = output; wl_list_insert(&desktop->outputs, &output->link); output->damage = wlr_output_damage_create(wlr_output); @@ -792,6 +818,11 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->damage_destroy.notify = output_damage_handle_destroy; wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); + size_t len = sizeof(output->layers) / sizeof(output->layers[0]); + for (size_t i = 0; i < len; ++i) { + wl_list_init(&output->layers[i]); + } + struct roots_output_config *output_config = roots_config_get_output(config, wlr_output); if (output_config) { diff --git a/types/wlr_layer_shell.c b/types/wlr_layer_shell.c index aaf9ee84..631b7009 100644 --- a/types/wlr_layer_shell.c +++ b/types/wlr_layer_shell.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include "util/signal.h" @@ -69,12 +70,31 @@ static void layer_surface_handle_ack_configure(struct wl_client *client, surface->current.anchor = configure->state.anchor; surface->current.exclusive_zone = configure->state.exclusive_zone; surface->current.margin = configure->state.margin; + surface->current.width = configure->state.width; + surface->current.height = configure->state.height; layer_surface_configure_destroy(configure); } +static void layer_surface_handle_set_size(struct wl_client *client, + struct wl_resource *resource, int32_t width, int32_t height) { + struct wlr_layer_surface *surface = layer_surface_from_resource(resource); + surface->client_pending.width = width; + surface->client_pending.height = height; +} + static void layer_surface_handle_set_anchor(struct wl_client *client, struct wl_resource *resource, uint32_t anchor) { + const uint32_t max_anchor = + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + if (anchor > max_anchor) { + wl_resource_post_error(resource, + ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_ANCHOR, + "invalid anchor %d", anchor); + } struct wlr_layer_surface *surface = layer_surface_from_resource(resource); surface->client_pending.anchor = anchor; } @@ -110,6 +130,7 @@ static void layer_surface_handle_get_popup(struct wl_client *client, static const struct zwlr_layer_surface_v1_interface layer_surface_implementation = { .destroy = resource_handle_destroy, .ack_configure = layer_surface_handle_ack_configure, + .set_size = layer_surface_handle_set_size, .set_anchor = layer_surface_handle_set_anchor, .set_exclusive_zone = layer_surface_handle_set_exclusive_zone, .set_margin = layer_surface_handle_set_margin, @@ -155,7 +176,7 @@ static void layer_surface_resource_destroy(struct wl_resource *resource) { static bool wlr_layer_surface_state_changed(struct wlr_layer_surface *surface) { if (!surface->configured) { - return false; + return true; } struct wlr_layer_surface_state *state; @@ -239,6 +260,8 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface, surface->current.margin = surface->client_pending.margin; surface->current.keyboard_interactive = surface->client_pending.keyboard_interactive; + surface->current.width = surface->client_pending.width; + surface->current.height = surface->client_pending.height; if (!surface->added) { surface->added = true; @@ -280,6 +303,7 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, surface->client = client; surface->surface = wlr_surface_from_resource(surface_resource); + surface->output = wlr_output_from_resource(output_resource); surface->resource = wl_resource_create(wl_client, &zwlr_layer_surface_v1_interface, wl_resource_get_version(client_resource), -- cgit v1.2.3 From f444a0d14c046b7df5a63f34a6f958cb175eb851 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 20 Mar 2018 21:13:39 -0400 Subject: Implement layer surface damage --- examples/layer-shell.c | 36 +++++++++++++++++++++++++++++------- include/rootston/output.h | 4 ++-- render/egl.c | 2 +- rootston/layer_shell.c | 32 ++++++++++++++++++++++++++------ rootston/output.c | 27 ++++++++++++++++++++++++--- 5 files changed, 82 insertions(+), 19 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index b5542f7a..91c509f6 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -1,8 +1,9 @@ -#define _POSIX_C_SOURCE 2 +#define _POSIX_C_SOURCE 199309L #include #include #include #include +#include #include #include #include @@ -25,6 +26,12 @@ static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; static uint32_t anchor = 0; static int32_t width = 256, height = 256; +static struct { + struct timespec last_frame; + float color[3]; + int dec; +} demo; + static void draw(void); static void surface_frame_callback( @@ -40,17 +47,33 @@ static struct wl_callback_listener frame_listener = { static void draw(void) { eglMakeCurrent(egl.display, egl_surface, egl_surface, egl.context); - wlr_log(L_DEBUG, "Drawing frame"); - float color[] = {1.0, 0.0, 0.0, 1.0}; + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + long ms = (ts.tv_sec - demo.last_frame.tv_sec) * 1000 + + (ts.tv_nsec - demo.last_frame.tv_nsec) / 1000000; + int inc = (demo.dec + 1) % 3; + + demo.color[inc] += ms / 2000.0f; + demo.color[demo.dec] -= ms / 2000.0f; + + if (demo.color[demo.dec] < 0.0f) { + demo.color[inc] = 1.0f; + demo.color[demo.dec] = 0.0f; + demo.dec = inc; + } + glViewport(0, 0, width, height); - glClearColor(color[0], color[1], color[2], 1.0); + glClearColor(demo.color[0], demo.color[1], demo.color[2], 1.0); glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(egl.display, egl_surface); - frame_callback = wl_surface_frame(wl_surface); wl_callback_add_listener(frame_callback, &frame_listener, NULL); + + eglSwapBuffers(egl.display, egl_surface); + + demo.last_frame = ts; } static void layer_surface_configure(void *data, @@ -196,7 +219,6 @@ int main(int argc, char **argv) { &layer_surface_listener, layer_surface); // TODO: margin, interactivity, exclusive zone wl_surface_commit(wl_surface); - wl_display_dispatch(display); wl_display_roundtrip(display); wlr_egl_init(&egl, EGL_PLATFORM_WAYLAND_EXT, display, NULL, diff --git a/include/rootston/output.h b/include/rootston/output.h index 5545d76a..5cdbcb32 100644 --- a/include/rootston/output.h +++ b/include/rootston/output.h @@ -36,7 +36,7 @@ void output_damage_from_view(struct roots_output *output, struct roots_view *view); void output_damage_whole_drag_icon(struct roots_output *output, struct roots_drag_icon *icon); -void output_damage_whole_surface(struct wlr_surface *surface, - double lx, double ly, float rotation, void *data); +void output_damage_from_local_surface(struct roots_output *output, + struct wlr_surface *surface, double ox, double oy, float rotation); #endif diff --git a/render/egl.c b/render/egl.c index d230f589..315eb098 100644 --- a/render/egl.c +++ b/render/egl.c @@ -95,7 +95,7 @@ static void print_dmabuf_formats(struct wlr_egl *egl) { for (int i = 0; i < num; i++) { snprintf(&str_formats[i*5], (num - i) * 5 + 1, "%.4s ", (char*)&formats[i]); } - wlr_log(L_INFO, "Supported dmabuf buffer formats: %s", str_formats); + wlr_log(L_DEBUG, "Supported dmabuf buffer formats: %s", str_formats); free(formats); } diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 25e683fe..73addb7a 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -114,12 +114,32 @@ static void arrange_layers(struct wlr_output *_output) { } } +static void unmap(struct wlr_layer_surface *layer_surface) { + struct roots_layer_surface *layer = layer_surface->data; + wl_list_remove(&layer->link); + + struct wlr_output *wlr_output = layer_surface->output; + struct roots_output *output = wlr_output->data; + wlr_output_damage_add_box(output->damage, &layer->geo); +} + static void handle_destroy(struct wl_listener *listener, void *data) { - // TODO + struct roots_layer_surface *layer = wl_container_of( + listener, layer, destroy); + if (layer->layer_surface->mapped) { + unmap(layer->layer_surface); + } + free(layer); } static void handle_surface_commit(struct wl_listener *listener, void *data) { - // TODO + struct roots_layer_surface *layer = + wl_container_of(listener, layer, surface_commit); + struct wlr_layer_surface *layer_surface = layer->layer_surface; + struct wlr_output *wlr_output = layer_surface->output; + struct roots_output *output = wlr_output->data; + output_damage_from_local_surface(output, layer_surface->surface, + layer->geo.x, layer->geo.y, 0); } static void handle_map(struct wl_listener *listener, void *data) { @@ -127,13 +147,13 @@ static void handle_map(struct wl_listener *listener, void *data) { struct roots_layer_surface *layer = layer_surface->data; struct wlr_output *wlr_output = layer_surface->output; struct roots_output *output = wlr_output->data; - // TODO: This doesn't play right with output layouts and is also stupid - output_damage_whole_surface(layer_surface->surface, layer->geo.x, - layer->geo.y, 0, output); + wlr_output_damage_add_box(output->damage, &layer->geo); } static void handle_unmap(struct wl_listener *listener, void *data) { - // TODO + struct roots_layer_surface *layer = wl_container_of( + listener, layer, unmap); + unmap(layer->layer_surface); } void handle_layer_shell_surface(struct wl_listener *listener, void *data) { diff --git a/rootston/output.c b/rootston/output.c index 71497608..7c2c6d44 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -433,6 +433,18 @@ static void render_layer( } } +static void layers_send_done( + struct roots_output *output, struct timespec *when) { + size_t len = sizeof(output->layers) / sizeof(output->layers[0]); + for (size_t i = 0; i < len; ++i) { + struct roots_layer_surface *roots_surface; + wl_list_for_each(roots_surface, &output->layers[i], link) { + struct wlr_layer_surface *layer = roots_surface->layer_surface; + wlr_surface_send_frame_done(layer->surface, when); + } + } +} + static void render_output(struct roots_output *output) { struct wlr_output *wlr_output = output->wlr_output; struct roots_desktop *desktop = output->desktop; @@ -595,6 +607,7 @@ damage_finish: drag_icons_for_each_surface(server->input, surface_send_frame_done, &data); } + layers_send_done(output, data.when); } void output_damage_whole(struct roots_output *output) { @@ -628,7 +641,7 @@ static bool view_accept_damage(struct roots_output *output, return false; } -void output_damage_whole_surface(struct wlr_surface *surface, +static void damage_whole_surface(struct wlr_surface *surface, double lx, double ly, float rotation, void *data) { struct roots_output *output = data; @@ -672,13 +685,13 @@ void output_damage_whole_view(struct roots_output *output, } damage_whole_decoration(view, output); - view_for_each_surface(view, output_damage_whole_surface, output); + view_for_each_surface(view, damage_whole_surface, output); } void output_damage_whole_drag_icon(struct roots_output *output, struct roots_drag_icon *icon) { surface_for_each_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, 0, - output_damage_whole_surface, output); + damage_whole_surface, output); } static void damage_from_surface(struct wlr_surface *surface, @@ -716,6 +729,14 @@ static void damage_from_surface(struct wlr_surface *surface, pixman_region32_fini(&damage); } +void output_damage_from_local_surface(struct roots_output *output, + struct wlr_surface *surface, double ox, double oy, float rotation) { + struct wlr_output_layout_output *layout = wlr_output_layout_get( + output->desktop->layout, output->wlr_output); + damage_from_surface(surface, ox + layout->x, oy + layout->y, + rotation, output); +} + void output_damage_from_view(struct roots_output *output, struct roots_view *view) { if (!view_accept_damage(output, view)) { -- cgit v1.2.3 From 8c98c188808e16f18349a89eb534e2bbf7ea65d8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 20 Mar 2018 21:41:18 -0400 Subject: Gracefully deal with outputs being removed --- include/rootston/layers.h | 1 + rootston/layer_shell.c | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 12 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/include/rootston/layers.h b/include/rootston/layers.h index f432d53d..43041786 100644 --- a/include/rootston/layers.h +++ b/include/rootston/layers.h @@ -14,6 +14,7 @@ struct roots_layer_surface { struct wl_listener map; struct wl_listener unmap; struct wl_listener surface_commit; + struct wl_listener output_destroy; bool configured; struct wlr_box geo; diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 73addb7a..c0dff85a 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -114,13 +114,34 @@ static void arrange_layers(struct wlr_output *_output) { } } +static void handle_output_destroy(struct wl_listener *listener, void *data) { + struct roots_layer_surface *layer = + wl_container_of(listener, layer, output_destroy); + layer->layer_surface->output = NULL; + wl_resource_destroy(layer->layer_surface->resource); +} + +static void handle_surface_commit(struct wl_listener *listener, void *data) { + struct roots_layer_surface *layer = + wl_container_of(listener, layer, surface_commit); + struct wlr_layer_surface *layer_surface = layer->layer_surface; + struct wlr_output *wlr_output = layer_surface->output; + if (wlr_output != NULL) { + struct roots_output *output = wlr_output->data; + output_damage_from_local_surface(output, layer_surface->surface, + layer->geo.x, layer->geo.y, 0); + } +} + static void unmap(struct wlr_layer_surface *layer_surface) { struct roots_layer_surface *layer = layer_surface->data; wl_list_remove(&layer->link); struct wlr_output *wlr_output = layer_surface->output; - struct roots_output *output = wlr_output->data; - wlr_output_damage_add_box(output->damage, &layer->geo); + if (wlr_output != NULL) { + struct roots_output *output = wlr_output->data; + wlr_output_damage_add_box(output->damage, &layer->geo); + } } static void handle_destroy(struct wl_listener *listener, void *data) { @@ -129,19 +150,10 @@ static void handle_destroy(struct wl_listener *listener, void *data) { if (layer->layer_surface->mapped) { unmap(layer->layer_surface); } + wl_list_remove(&layer->output_destroy.link); free(layer); } -static void handle_surface_commit(struct wl_listener *listener, void *data) { - struct roots_layer_surface *layer = - wl_container_of(listener, layer, surface_commit); - struct wlr_layer_surface *layer_surface = layer->layer_surface; - struct wlr_output *wlr_output = layer_surface->output; - struct roots_output *output = wlr_output->data; - output_damage_from_local_surface(output, layer_surface->surface, - layer->geo.x, layer->geo.y, 0); -} - static void handle_map(struct wl_listener *listener, void *data) { struct wlr_layer_surface *layer_surface = data; struct roots_layer_surface *layer = layer_surface->data; @@ -174,9 +186,15 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { if (!roots_surface) { return; } + roots_surface->surface_commit.notify = handle_surface_commit; wl_signal_add(&layer_surface->surface->events.commit, &roots_surface->surface_commit); + + roots_surface->output_destroy.notify = handle_output_destroy; + wl_signal_add(&layer_surface->output->events.destroy, + &roots_surface->output_destroy); + roots_surface->destroy.notify = handle_destroy; wl_signal_add(&layer_surface->events.destroy, &roots_surface->destroy); roots_surface->map.notify = handle_map; -- cgit v1.2.3 From b73c4f48c10ae79a33d1611fb641d22b8b619c39 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 20 Mar 2018 21:57:16 -0400 Subject: Fix exclusive zone among other layers --- examples/layer-shell.c | 9 +++++++-- rootston/layer_shell.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index f006a1b7..f3b9d3a0 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -119,9 +119,10 @@ static const struct wl_registry_listener registry_listener = { int main(int argc, char **argv) { wlr_log_init(L_DEBUG, NULL); char *namespace = "wlroots"; + int exclusive_zone = 0; bool found; int c; - while ((c = getopt(argc, argv, "w:h:o:l:a:")) != -1) { + while ((c = getopt(argc, argv, "w:h:o:l:a:x:")) != -1) { switch (c) { case 'o': output = atoi(optarg); @@ -132,6 +133,9 @@ int main(int argc, char **argv) { case 'h': height = atoi(optarg); break; + case 'x': + exclusive_zone = atoi(optarg); + break; case 'l': { struct { char *name; @@ -215,9 +219,10 @@ int main(int argc, char **argv) { wl_surface, wl_output, layer, namespace); zwlr_layer_surface_v1_set_size(layer_surface, width, height); zwlr_layer_surface_v1_set_anchor(layer_surface, anchor); + zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, exclusive_zone); zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, layer_surface); - // TODO: margin, interactivity, exclusive zone + // TODO: margin, interactivity wl_surface_commit(wl_surface); wl_display_roundtrip(display); diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index c0dff85a..ac7b2b20 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -53,7 +53,7 @@ static void apply_exclusive(struct wlr_box *output_area, }; for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { if ((anchor & edges[i].anchors)) { - edges[i].value += exclusive * edges[i].multiplier; + *edges[i].value += exclusive * edges[i].multiplier; } } } -- cgit v1.2.3 From d1c0e6fe2c21b4c7f651a82fb7342b54a4989c39 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 24 Mar 2018 18:00:01 -0400 Subject: Add layer_surface.close --- examples/layer-shell.c | 13 ++++++++++++- include/wlr/types/wlr_layer_shell.h | 7 ++++++- protocol/wlr-layer-shell-unstable-v1.xml | 10 ++++++++++ rootston/layer_shell.c | 6 ++++-- types/wlr_layer_shell.c | 11 +++++++++++ 5 files changed, 43 insertions(+), 4 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index f3b9d3a0..08826251 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -25,6 +25,7 @@ static uint32_t output = 0; static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; static uint32_t anchor = 0; static int32_t width = 256, height = 256; +static bool run_display = true; static struct { struct timespec last_frame; @@ -84,8 +85,18 @@ static void layer_surface_configure(void *data, zwlr_layer_surface_v1_ack_configure(surface, serial); } +static void layer_surface_closed(void *data, + struct zwlr_layer_surface_v1 *surface) { + eglDestroySurface(egl.display, egl_surface); + wl_egl_window_destroy(egl_window); + zwlr_layer_surface_v1_destroy(surface); + wl_surface_destroy(wl_surface); + run_display = false; +} + struct zwlr_layer_surface_v1_listener layer_surface_listener = { .configure = layer_surface_configure, + .closed = layer_surface_closed, }; static void handle_global(void *data, struct wl_registry *registry, @@ -235,7 +246,7 @@ int main(int argc, char **argv) { wl_display_roundtrip(display); draw(); - while (wl_display_dispatch(display) != -1) { + while (wl_display_dispatch(display) != -1 && run_display) { // This space intentionally left blank } return 0; diff --git a/include/wlr/types/wlr_layer_shell.h b/include/wlr/types/wlr_layer_shell.h index 3002345d..5d9feb27 100644 --- a/include/wlr/types/wlr_layer_shell.h +++ b/include/wlr/types/wlr_layer_shell.h @@ -67,7 +67,7 @@ struct wlr_layer_surface { const char *namespace; enum zwlr_layer_shell_v1_layer layer; - bool added, configured, mapped; + bool added, configured, mapped, closed; uint32_t configure_serial; struct wl_event_source *configure_idle; uint32_t configure_next_serial; @@ -99,4 +99,9 @@ void wlr_layer_shell_destroy(struct wlr_layer_shell *layer_shell); void wlr_layer_surface_configure(struct wlr_layer_surface *surface, uint32_t width, uint32_t height); +/** + * Unmaps this layer surface and notifies the client that it has been closed. + */ +void wlr_layer_surface_close(struct wlr_layer_surface *surface); + #endif diff --git a/protocol/wlr-layer-shell-unstable-v1.xml b/protocol/wlr-layer-shell-unstable-v1.xml index d6de59ab..b5cb3d3a 100644 --- a/protocol/wlr-layer-shell-unstable-v1.xml +++ b/protocol/wlr-layer-shell-unstable-v1.xml @@ -237,6 +237,16 @@ + + + The closed event is sent by the compositor when the surface will no + longer be shown. The output may have been destroyed or the user may have + asked for it to be removed. Further changes to the surface will be ignored. + The client should destroy the resource after receiving this event, and + create a new surface if they so choose. + + + diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index ac7b2b20..114a5f29 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -118,7 +118,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { struct roots_layer_surface *layer = wl_container_of(listener, layer, output_destroy); layer->layer_surface->output = NULL; - wl_resource_destroy(layer->layer_surface->resource); + wlr_layer_surface_close(layer->layer_surface); } static void handle_surface_commit(struct wl_listener *listener, void *data) { @@ -135,7 +135,9 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { static void unmap(struct wlr_layer_surface *layer_surface) { struct roots_layer_surface *layer = layer_surface->data; - wl_list_remove(&layer->link); + if (layer->link.prev) { + wl_list_remove(&layer->link); + } struct wlr_output *wlr_output = layer_surface->output; if (wlr_output != NULL) { diff --git a/types/wlr_layer_shell.c b/types/wlr_layer_shell.c index 631b7009..59f8d568 100644 --- a/types/wlr_layer_shell.c +++ b/types/wlr_layer_shell.c @@ -244,6 +244,12 @@ void wlr_layer_surface_configure(struct wlr_layer_surface *surface, wlr_layer_surface_schedule_configure(surface); } +void wlr_layer_surface_close(struct wlr_layer_surface *surface) { + surface->closed = true; + layer_surface_unmap(surface); + zwlr_layer_surface_v1_send_closed(surface->resource); +} + static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface, void *role_data) { struct wlr_layer_surface *surface = role_data; @@ -255,6 +261,11 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface, return; } + if (surface->closed) { + // Ignore commits after the compositor has closed it + return; + } + surface->current.anchor = surface->client_pending.anchor; surface->current.exclusive_zone = surface->client_pending.exclusive_zone; surface->current.margin = surface->client_pending.margin; -- cgit v1.2.3 From 11c57d22b0d7c24ee69d4c43cb08f03c7f35f0d4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 24 Mar 2018 18:02:42 -0400 Subject: Use 0 for default width/height (rather than -1) --- rootston/layer_shell.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 114a5f29..c4e82535 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -70,7 +70,7 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list) { // Horizontal axis const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - if ((state->anchor & both_horiz) && box.width == -1) { + if ((state->anchor & both_horiz) && box.width == 0) { box.x = 0; box.width = output_area.width; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { @@ -83,7 +83,7 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list) { // Vertical axis const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; - if ((state->anchor & both_vert) && box.height == -1) { + if ((state->anchor & both_vert) && box.height == 0) { box.y = 0; box.height = output_area.height; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { @@ -97,9 +97,9 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list) { box.width, box.height, box.x, box.y); roots_surface->geo = box; apply_exclusive(&output_area, state->anchor, state->exclusive_zone); - if (box.width != (int)state->width - || box.height != (int)state->height - || !roots_surface->configured) { + if (!roots_surface->configured || + box.width != (int)state->width || + box.height != (int)state->height) { wlr_layer_surface_configure(layer, box.width, box.height); roots_surface->configured = true; } -- cgit v1.2.3 From df9dbf31706254887652b54214e2c9ee2346f0e8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 26 Mar 2018 12:01:13 -0400 Subject: Fix rebase issues; rearrange layers on destroy --- examples/layer-shell.c | 16 ++++++++++++---- rootston/layer_shell.c | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 08826251..999d948f 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 199309L +#include #include #include #include @@ -24,7 +25,7 @@ struct wl_callback *frame_callback; static uint32_t output = 0; static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; static uint32_t anchor = 0; -static int32_t width = 256, height = 256; +static uint32_t width = 256, height = 256; static bool run_display = true; static struct { @@ -82,6 +83,9 @@ static void layer_surface_configure(void *data, uint32_t serial, uint32_t w, uint32_t h) { width = w; height = h; + if (egl_window) { + wl_egl_window_resize(egl_window, width, height, 0, 0); + } zwlr_layer_surface_v1_ack_configure(surface, serial); } @@ -223,11 +227,16 @@ int main(int argc, char **argv) { return 1; } + wlr_egl_init(&egl, EGL_PLATFORM_WAYLAND_EXT, display, NULL, + WL_SHM_FORMAT_ARGB8888); + wl_surface = wl_compositor_create_surface(compositor); + assert(wl_surface); struct zwlr_layer_surface_v1 *layer_surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, wl_surface, wl_output, layer, namespace); + assert(layer_surface); zwlr_layer_surface_v1_set_size(layer_surface, width, height); zwlr_layer_surface_v1_set_anchor(layer_surface, anchor); zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, exclusive_zone); @@ -237,11 +246,10 @@ int main(int argc, char **argv) { wl_surface_commit(wl_surface); wl_display_roundtrip(display); - wlr_egl_init(&egl, EGL_PLATFORM_WAYLAND_EXT, display, NULL, - WL_SHM_FORMAT_ARGB8888); - egl_window = wl_egl_window_create(wl_surface, width, height); + assert(egl_window); egl_surface = wlr_egl_create_surface(&egl, egl_window); + assert(egl_surface); wl_display_roundtrip(display); draw(); diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index c4e82535..ccea4f8d 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -153,6 +153,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { unmap(layer->layer_surface); } wl_list_remove(&layer->output_destroy.link); + arrange_layers(layer->layer_surface->output); free(layer); } -- cgit v1.2.3 From ab6c2bf5849a83cea0b6cb0e78d17d054ff07b19 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 26 Mar 2018 12:22:17 -0400 Subject: Reset exclusivity after shell layer Also fixes an issue which was applying exclusivity to all edges --- include/rootston/output.h | 3 +++ rootston/layer_shell.c | 63 ++++++++++++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 23 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/include/rootston/output.h b/include/rootston/output.h index 5cdbcb32..535c07d8 100644 --- a/include/rootston/output.h +++ b/include/rootston/output.h @@ -4,6 +4,7 @@ #include #include #include +#include #include struct roots_desktop; @@ -19,6 +20,8 @@ struct roots_output { struct timespec last_frame; struct wlr_output_damage *damage; + struct wlr_box usable_area; + struct wl_listener destroy; struct wl_listener damage_frame; struct wl_listener damage_destroy; diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index ccea4f8d..38ddda23 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -11,7 +11,7 @@ #include "rootston/output.h" #include "rootston/server.h" -static void apply_exclusive(struct wlr_box *output_area, +static void apply_exclusive(struct wlr_box *usable_area, uint32_t anchor, uint32_t exclusive) { struct { uint32_t anchors; @@ -23,7 +23,7 @@ static void apply_exclusive(struct wlr_box *output_area, ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, - .value = &output_area->y, + .value = &usable_area->y, .multiplier = 1, }, { @@ -31,7 +31,7 @@ static void apply_exclusive(struct wlr_box *output_area, ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, - .value = &output_area->height, + .value = &usable_area->height, .multiplier = -1, }, { @@ -39,7 +39,7 @@ static void apply_exclusive(struct wlr_box *output_area, ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, - .value = &output_area->x, + .value = &usable_area->x, .multiplier = 1, }, { @@ -47,21 +47,19 @@ static void apply_exclusive(struct wlr_box *output_area, ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, - .value = &output_area->width, + .value = &usable_area->width, .multiplier = -1, }, }; for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { - if ((anchor & edges[i].anchors)) { + if ((anchor & edges[i].anchors) == edges[i].anchors) { *edges[i].value += exclusive * edges[i].multiplier; } } } -static void arrange_layer(struct wlr_output *output, struct wl_list *list) { - struct wlr_box output_area = { .x = 0, .y = 0 }; - wlr_output_effective_resolution(output, - &output_area.width, &output_area.height); +static void arrange_layer(struct wlr_output *output, struct wl_list *list, + struct wlr_box *usable_area) { struct roots_layer_surface *roots_surface; wl_list_for_each(roots_surface, list, link) { struct wlr_layer_surface *layer = roots_surface->layer_surface; @@ -72,31 +70,31 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list) { | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; if ((state->anchor & both_horiz) && box.width == 0) { box.x = 0; - box.width = output_area.width; + box.width = usable_area->width; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { - box.x = output_area.x; + box.x = usable_area->x; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { - box.x = output_area.width - box.width; + box.x = usable_area->width - box.width; } else { - box.x = (output_area.width / 2) - (box.width / 2); + box.x = (usable_area->width / 2) - (box.width / 2); } // Vertical axis const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; if ((state->anchor & both_vert) && box.height == 0) { box.y = 0; - box.height = output_area.height; + box.height = usable_area->height; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { - box.y = output_area.y; + box.y = usable_area->y; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { - box.y = output_area.height - box.height; + box.y = usable_area->height - box.height; } else { - box.y = (output_area.height / 2) - (box.height / 2); + box.y = (usable_area->height / 2) - (box.height / 2); } wlr_log(L_DEBUG, "arranged layer at %dx%d@%d,%d", box.width, box.height, box.x, box.y); roots_surface->geo = box; - apply_exclusive(&output_area, state->anchor, state->exclusive_zone); + apply_exclusive(usable_area, state->anchor, state->exclusive_zone); if (!roots_surface->configured || box.width != (int)state->width || box.height != (int)state->height) { @@ -108,10 +106,29 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list) { static void arrange_layers(struct wlr_output *_output) { struct roots_output *output = _output->data; - size_t layers = sizeof(output->layers) / sizeof(output->layers[0]); - for (size_t i = 0; i < layers; ++i) { - arrange_layer(output->wlr_output, &output->layers[i]); - } + + struct wlr_box usable_area = { 0 }; + wlr_output_effective_resolution(output->wlr_output, + &usable_area.width, &usable_area.height); + + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + &usable_area); + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + &usable_area); + memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); + + memset(&usable_area, 0, sizeof(struct wlr_box)); + wlr_output_effective_resolution(output->wlr_output, + &usable_area.width, &usable_area.height); + + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + &usable_area); + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + &usable_area); } static void handle_output_destroy(struct wl_listener *listener, void *data) { -- cgit v1.2.3 From 097e87ca9ff34e0d17dced154ee8a860b6d86060 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 26 Mar 2018 14:14:23 -0400 Subject: Handle usable area for maximized windows Also fixes some bugs --- include/rootston/desktop.h | 1 + rootston/desktop.c | 50 ++++++++++++++++++++++++++++++---------------- rootston/layer_shell.c | 49 ++++++++++++++++++++++++++++----------------- 3 files changed, 65 insertions(+), 35 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 92cc6d9d..5714aa0a 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -86,6 +86,7 @@ void view_update_size(struct roots_view *view, uint32_t width, uint32_t height); void view_initial_focus(struct roots_view *view); void view_map(struct roots_view *view, struct wlr_surface *surface); void view_unmap(struct roots_view *view); +void view_arrange_maximized(struct roots_view *view); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); void handle_xdg_shell_surface(struct wl_listener *listener, void *data); diff --git a/rootston/desktop.c b/rootston/desktop.c index 015a8215..a0659250 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -188,6 +188,38 @@ static struct wlr_output *view_get_output(struct roots_view *view) { output_y); } +void view_arrange_maximized(struct roots_view *view) { + struct wlr_box view_box; + view_get_box(view, &view_box); + + view->maximized = true; + view->saved.x = view->x; + view->saved.y = view->y; + view->saved.rotation = view->rotation; + view->saved.width = view_box.width; + view->saved.height = view_box.height; + + struct wlr_output *output = view_get_output(view); + struct roots_output *roots_output = output->data; + struct wlr_box *output_box = + wlr_output_layout_get_box(view->desktop->layout, output); + struct wlr_box usable_area; + memcpy(&usable_area, &roots_output->usable_area, + sizeof(struct wlr_box)); + usable_area.x += output_box->x; + usable_area.y += output_box->y; + + wlr_log(L_DEBUG, "output area: %dx%d@%d,%d", + output_box->width, output_box->height, + output_box->x, output_box->y); + wlr_log(L_DEBUG, "usable area: %dx%d@%d,%d", + usable_area.width, usable_area.height, + usable_area.x, usable_area.y); + view_move_resize(view, usable_area.x, usable_area.y, + usable_area.width, usable_area.height); + view_rotate(view, 0); +} + void view_maximize(struct roots_view *view, bool maximized) { if (view->maximized == maximized) { return; @@ -198,23 +230,7 @@ void view_maximize(struct roots_view *view, bool maximized) { } if (!view->maximized && maximized) { - struct wlr_box view_box; - view_get_box(view, &view_box); - - view->maximized = true; - view->saved.x = view->x; - view->saved.y = view->y; - view->saved.rotation = view->rotation; - view->saved.width = view_box.width; - view->saved.height = view_box.height; - - struct wlr_output *output = view_get_output(view); - struct wlr_box *output_box = - wlr_output_layout_get_box(view->desktop->layout, output); - - view_move_resize(view, output_box->x, output_box->y, output_box->width, - output_box->height); - view_rotate(view, 0); + view_arrange_maximized(view); } if (view->maximized && !maximized) { diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 38ddda23..e7604ec5 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -15,45 +15,50 @@ static void apply_exclusive(struct wlr_box *usable_area, uint32_t anchor, uint32_t exclusive) { struct { uint32_t anchors; - int *value; - int multiplier; + int *positive_axis; + int *negative_axis; } edges[] = { { .anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, - .value = &usable_area->y, - .multiplier = 1, + .positive_axis = &usable_area->y, + .negative_axis = &usable_area->height, }, { .anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, - .value = &usable_area->height, - .multiplier = -1, + .positive_axis = NULL, + .negative_axis = &usable_area->height, }, { .anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, - .value = &usable_area->x, - .multiplier = 1, + .positive_axis = &usable_area->x, + .negative_axis = &usable_area->width, }, { .anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, - .value = &usable_area->width, - .multiplier = -1, + .positive_axis = NULL, + .negative_axis = &usable_area->width, }, }; for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { if ((anchor & edges[i].anchors) == edges[i].anchors) { - *edges[i].value += exclusive * edges[i].multiplier; + if (edges[i].positive_axis) { + *edges[i].positive_axis += exclusive; + } + if (edges[i].negative_axis) { + *edges[i].negative_axis -= exclusive; + } } } } @@ -74,9 +79,9 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { box.x = usable_area->x; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { - box.x = usable_area->width - box.width; + box.x = usable_area->x + (usable_area->width - box.width); } else { - box.x = (usable_area->width / 2) - (box.width / 2); + box.x = usable_area->x + ((usable_area->width / 2) - (box.width / 2)); } // Vertical axis const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP @@ -87,9 +92,9 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { box.y = usable_area->y; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { - box.y = usable_area->height - box.height; + box.y = usable_area->y + (usable_area->height - box.height); } else { - box.y = (usable_area->height / 2) - (box.height / 2); + box.y = usable_area->y + ((usable_area->height / 2) - (box.height / 2)); } wlr_log(L_DEBUG, "arranged layer at %dx%d@%d,%d", box.width, box.height, box.x, box.y); @@ -119,16 +124,24 @@ static void arrange_layers(struct wlr_output *_output) { &usable_area); memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + &usable_area); + memset(&usable_area, 0, sizeof(struct wlr_box)); wlr_output_effective_resolution(output->wlr_output, &usable_area.width, &usable_area.height); - arrange_layer(output->wlr_output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], - &usable_area); arrange_layer(output->wlr_output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &usable_area); + + struct roots_view *view; + wl_list_for_each(view, &output->desktop->views, link) { + if (view->maximized) { + view_arrange_maximized(view); + } + } } static void handle_output_destroy(struct wl_listener *listener, void *data) { -- cgit v1.2.3 From 86ca4bea6de9b3494235201f5587cb7e00aed84e Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 26 Mar 2018 18:12:31 -0400 Subject: Fix layer rendering/layout bugs --- examples/layer-shell.c | 32 ++++++-- include/rootston/layers.h | 1 + include/wlr/types/wlr_layer_shell.h | 5 +- protocol/wlr-layer-shell-unstable-v1.xml | 31 +++++-- rootston/layer_shell.c | 136 ++++++++++++++++++++++--------- types/wlr_layer_shell.c | 35 ++++---- types/wlr_seat.c | 5 +- 7 files changed, 171 insertions(+), 74 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 999d948f..3518a56f 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -26,6 +26,7 @@ static uint32_t output = 0; static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; static uint32_t anchor = 0; static uint32_t width = 256, height = 256; +static double alpha = 1.0; static bool run_display = true; static struct { @@ -67,7 +68,7 @@ static void draw(void) { } glViewport(0, 0, width, height); - glClearColor(demo.color[0], demo.color[1], demo.color[2], 1.0); + glClearColor(demo.color[0], demo.color[1], demo.color[2], alpha); glClear(GL_COLOR_BUFFER_BIT); frame_callback = wl_surface_frame(wl_surface); @@ -135,9 +136,11 @@ int main(int argc, char **argv) { wlr_log_init(L_DEBUG, NULL); char *namespace = "wlroots"; int exclusive_zone = 0; + int32_t margin_top = 0, margin_right = 0, + margin_bottom = 0, margin_left = 0; bool found; int c; - while ((c = getopt(argc, argv, "w:h:o:l:a:x:")) != -1) { + while ((c = getopt(argc, argv, "w:h:o:l:a:x:m:t:")) != -1) { switch (c) { case 'o': output = atoi(optarg); @@ -197,6 +200,22 @@ int main(int argc, char **argv) { fprintf(stderr, "invalid anchor %s\n", optarg); return 1; } + break; + } + case 't': + alpha = atof(optarg); + break; + case 'm': { + char *endptr = optarg; + margin_top = strtol(endptr, &endptr, 10); + assert(*endptr == ','); + margin_right = strtol(endptr + 1, &endptr, 10); + assert(*endptr == ','); + margin_bottom = strtol(endptr + 1, &endptr, 10); + assert(*endptr == ','); + margin_left = strtol(endptr + 1, &endptr, 10); + assert(!*endptr); + break; } default: break; @@ -227,8 +246,9 @@ int main(int argc, char **argv) { return 1; } - wlr_egl_init(&egl, EGL_PLATFORM_WAYLAND_EXT, display, NULL, - WL_SHM_FORMAT_ARGB8888); + EGLint attribs[] = { EGL_ALPHA_SIZE, 8, EGL_NONE }; + wlr_egl_init(&egl, EGL_PLATFORM_WAYLAND_EXT, display, + attribs, WL_SHM_FORMAT_ARGB8888); wl_surface = wl_compositor_create_surface(compositor); assert(wl_surface); @@ -240,9 +260,11 @@ int main(int argc, char **argv) { zwlr_layer_surface_v1_set_size(layer_surface, width, height); zwlr_layer_surface_v1_set_anchor(layer_surface, anchor); zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, exclusive_zone); + zwlr_layer_surface_v1_set_margin(layer_surface, + margin_top, margin_right, margin_bottom, margin_left); zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, layer_surface); - // TODO: margin, interactivity + // TODO: interactivity wl_surface_commit(wl_surface); wl_display_roundtrip(display); diff --git a/include/rootston/layers.h b/include/rootston/layers.h index 43041786..cc285fe7 100644 --- a/include/rootston/layers.h +++ b/include/rootston/layers.h @@ -15,6 +15,7 @@ struct roots_layer_surface { struct wl_listener unmap; struct wl_listener surface_commit; struct wl_listener output_destroy; + struct wl_listener output_mode; bool configured; struct wlr_box geo; diff --git a/include/wlr/types/wlr_layer_shell.h b/include/wlr/types/wlr_layer_shell.h index 5d9feb27..c24b391e 100644 --- a/include/wlr/types/wlr_layer_shell.h +++ b/include/wlr/types/wlr_layer_shell.h @@ -43,12 +43,13 @@ struct wlr_layer_client { struct wlr_layer_surface_state { uint32_t anchor; - uint32_t exclusive_zone; + int32_t exclusive_zone; struct { uint32_t top, right, bottom, left; } margin; bool keyboard_interactive; - uint32_t width, height; + uint32_t desired_width, desired_height; + uint32_t actual_width, actual_height; }; struct wlr_layer_surface_configure { diff --git a/protocol/wlr-layer-shell-unstable-v1.xml b/protocol/wlr-layer-shell-unstable-v1.xml index b5cb3d3a..fe2c72cd 100644 --- a/protocol/wlr-layer-shell-unstable-v1.xml +++ b/protocol/wlr-layer-shell-unstable-v1.xml @@ -96,15 +96,15 @@ Sets the size of the surface in pixels. The compositor will display the surface centered with respect to its anchors. - If you pass -1 for either value, the compositor will assign it and + If you pass 0 for either value, the compositor will assign it and inform you of the assignment in the configure event. You must set your anchor to opposite edges in the dimensions you omit; not doing so is a - protocol error. Both values are -1 by default. + protocol error. Both values are 0 by default. Size is double-buffered, see wl_surface.commit. - - + + @@ -127,13 +127,28 @@ implementation-dependent - do not assume that this region will not actually be occluded. - This value is only meaningful if the surface is anchored to an edge, - rather than a corner. The zone is the number of pixels from the edge - that are considered exclusive. + A positive value is only meaningful if the surface is anchored to an + edge, rather than a corner. The zone is the number of pixels from the + edge that are considered exclusive. + + Surfaces that do not wish to have an exclusive zone may instead specify + how they should interact with surfaces that do. If set to zero, the + surface indicates that it would like to be moved to avoid occluding + surfaces with a positive excluzive zone. If set to -1, the surface + indicates that it would not like to be moved to accomodate for other + surfaces, and the compositor should extend it all the way to the edges + it is anchored to. + + For example, a panel might set its exclusive zone to 10 pixels, so that + maximized shell surfaces are not shown on top of it. A notification + might set its exclusive zone to zero, so that it is moved to avoid + occluding the panel, but shell surfaces are shown underneath it. A + wallpaper or lock screen might set their exclusive zone to -1, so that + they stretch below or over the panel. Exclusive zone is double-buffered, see wl_surface.commit. - + diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index e7604ec5..e2d5b9f0 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -12,7 +12,10 @@ #include "rootston/server.h" static void apply_exclusive(struct wlr_box *usable_area, - uint32_t anchor, uint32_t exclusive) { + uint32_t anchor, int32_t exclusive) { + if (exclusive <= 0) { + return; + } struct { uint32_t anchors; int *positive_axis; @@ -64,48 +67,80 @@ static void apply_exclusive(struct wlr_box *usable_area, } static void arrange_layer(struct wlr_output *output, struct wl_list *list, - struct wlr_box *usable_area) { + struct wlr_box *usable_area, bool exclusive) { struct roots_layer_surface *roots_surface; + struct wlr_box full_area = { 0 }; + wlr_output_effective_resolution(output, + &full_area.width, &full_area.height); wl_list_for_each(roots_surface, list, link) { struct wlr_layer_surface *layer = roots_surface->layer_surface; struct wlr_layer_surface_state *state = &layer->current; - struct wlr_box box = { .width = state->width, .height = state->height }; + if (exclusive) { + if (state->exclusive_zone <= 0) { + continue; + } + } else { + if (state->exclusive_zone > 0) { + continue; + } + } + struct wlr_box bounds; + if (state->exclusive_zone == -1) { + bounds = full_area; + } else { + bounds = *usable_area; + } + struct wlr_box box = { + .width = state->desired_width, + .height = state->desired_height + }; // Horizontal axis const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; if ((state->anchor & both_horiz) && box.width == 0) { - box.x = 0; - box.width = usable_area->width; + box.x = bounds.x; + box.width = bounds.width; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { - box.x = usable_area->x; + box.x = bounds.x; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { - box.x = usable_area->x + (usable_area->width - box.width); + box.x = bounds.x + (bounds.width - box.width); } else { - box.x = usable_area->x + ((usable_area->width / 2) - (box.width / 2)); + box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); } // Vertical axis const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; if ((state->anchor & both_vert) && box.height == 0) { - box.y = 0; - box.height = usable_area->height; + box.y = bounds.y; + box.height = bounds.height; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { - box.y = usable_area->y; + box.y = bounds.y; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { - box.y = usable_area->y + (usable_area->height - box.height); + box.y = bounds.y + (bounds.height - box.height); } else { - box.y = usable_area->y + ((usable_area->height / 2) - (box.height / 2)); + box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); + } + // Margin + if ((state->anchor & both_horiz)) { + box.x += state->margin.left; + box.width -= state->margin.left + state->margin.right; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + box.x += state->margin.bottom; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + box.x -= state->margin.right; } - wlr_log(L_DEBUG, "arranged layer at %dx%d@%d,%d", - box.width, box.height, box.x, box.y); + if ((state->anchor & both_vert)) { + box.y += state->margin.top; + box.height -= state->margin.top + state->margin.bottom; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + box.y += state->margin.top; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + box.y -= state->margin.bottom; + } + // Apply roots_surface->geo = box; apply_exclusive(usable_area, state->anchor, state->exclusive_zone); - if (!roots_surface->configured || - box.width != (int)state->width || - box.height != (int)state->height) { - wlr_layer_surface_configure(layer, box.width, box.height); - roots_surface->configured = true; - } + wlr_layer_surface_configure(layer, box.width, box.height); } } @@ -116,25 +151,20 @@ static void arrange_layers(struct wlr_output *_output) { wlr_output_effective_resolution(output->wlr_output, &usable_area.width, &usable_area.height); + // Arrange exclusive surfaces from top->bottom arrange_layer(output->wlr_output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], - &usable_area); - arrange_layer(output->wlr_output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], - &usable_area); - memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); - + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + &usable_area, true); arrange_layer(output->wlr_output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], - &usable_area); - - memset(&usable_area, 0, sizeof(struct wlr_box)); - wlr_output_effective_resolution(output->wlr_output, - &usable_area.width, &usable_area.height); - + &usable_area, true); arrange_layer(output->wlr_output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], - &usable_area); + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + &usable_area, true); + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + &usable_area, true); + memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); struct roots_view *view; wl_list_for_each(view, &output->desktop->views, link) { @@ -142,15 +172,37 @@ static void arrange_layers(struct wlr_output *_output) { view_arrange_maximized(view); } } + + // Arrange non-exlusive surfaces from top->bottom + wlr_output_effective_resolution(output->wlr_output, + &usable_area.width, &usable_area.height); + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + &usable_area, false); + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + &usable_area, false); + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + &usable_area, false); + arrange_layer(output->wlr_output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + &usable_area, false); } static void handle_output_destroy(struct wl_listener *listener, void *data) { struct roots_layer_surface *layer = wl_container_of(listener, layer, output_destroy); layer->layer_surface->output = NULL; + wl_list_remove(&layer->output_destroy.link); + wl_list_remove(&layer->output_mode.link); wlr_layer_surface_close(layer->layer_surface); } +static void handle_output_mode(struct wl_listener *listener, void *data) { + arrange_layers((struct wlr_output *)data); +} + static void handle_surface_commit(struct wl_listener *listener, void *data) { struct roots_layer_surface *layer = wl_container_of(listener, layer, surface_commit); @@ -183,6 +235,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { unmap(layer->layer_surface); } wl_list_remove(&layer->output_destroy.link); + wl_list_remove(&layer->output_mode.link); arrange_layers(layer->layer_surface->output); free(layer); } @@ -205,10 +258,11 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { struct wlr_layer_surface *layer_surface = data; struct roots_desktop *desktop = wl_container_of(listener, desktop, layer_shell_surface); - wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d anchor %d %dx%d %d,%d,%d,%d", + wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d anchor %d " + "size %dx%d margin %d,%d,%d,%d", layer_surface->namespace, layer_surface->layer, layer_surface->layer, - layer_surface->client_pending.width, - layer_surface->client_pending.height, + layer_surface->client_pending.desired_width, + layer_surface->client_pending.desired_height, layer_surface->client_pending.margin.top, layer_surface->client_pending.margin.right, layer_surface->client_pending.margin.bottom, @@ -228,6 +282,10 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&layer_surface->output->events.destroy, &roots_surface->output_destroy); + roots_surface->output_mode.notify = handle_output_mode; + wl_signal_add(&layer_surface->output->events.mode, + &roots_surface->output_mode); + roots_surface->destroy.notify = handle_destroy; wl_signal_add(&layer_surface->events.destroy, &roots_surface->destroy); roots_surface->map.notify = handle_map; diff --git a/types/wlr_layer_shell.c b/types/wlr_layer_shell.c index 59f8d568..04c8fbd5 100644 --- a/types/wlr_layer_shell.c +++ b/types/wlr_layer_shell.c @@ -66,21 +66,17 @@ static void layer_surface_handle_ack_configure(struct wl_client *client, surface->configured = true; surface->configure_serial = serial; - - surface->current.anchor = configure->state.anchor; - surface->current.exclusive_zone = configure->state.exclusive_zone; - surface->current.margin = configure->state.margin; - surface->current.width = configure->state.width; - surface->current.height = configure->state.height; + surface->current.actual_width = configure->state.actual_width; + surface->current.actual_height = configure->state.actual_height; layer_surface_configure_destroy(configure); } static void layer_surface_handle_set_size(struct wl_client *client, - struct wl_resource *resource, int32_t width, int32_t height) { + struct wl_resource *resource, uint32_t width, uint32_t height) { struct wlr_layer_surface *surface = layer_surface_from_resource(resource); - surface->client_pending.width = width; - surface->client_pending.height = height; + surface->client_pending.desired_width = width; + surface->client_pending.desired_height = height; } static void layer_surface_handle_set_anchor(struct wl_client *client, @@ -100,7 +96,7 @@ static void layer_surface_handle_set_anchor(struct wl_client *client, } static void layer_surface_handle_set_exclusive_zone(struct wl_client *client, - struct wl_resource *resource, uint32_t zone) { + struct wl_resource *resource, int32_t zone) { struct wlr_layer_surface *surface = layer_surface_from_resource(resource); surface->client_pending.exclusive_zone = zone; } @@ -188,8 +184,9 @@ static bool wlr_layer_surface_state_changed(struct wlr_layer_surface *surface) { state = &configure->state; } - return !memcmp(state, &surface->server_pending, - sizeof(struct wlr_layer_surface_state)); + bool changed = state->actual_width != surface->server_pending.actual_width + || state->actual_height != surface->server_pending.actual_height; + return changed; } static void wlr_layer_surface_send_configure(void *user_data) { @@ -204,10 +201,12 @@ static void wlr_layer_surface_send_configure(void *user_data) { wl_list_insert(surface->configure_list.prev, &configure->link); configure->serial = surface->configure_next_serial; - configure->state = surface->server_pending; + configure->state.actual_width = surface->server_pending.actual_width; + configure->state.actual_height = surface->server_pending.actual_height; zwlr_layer_surface_v1_send_configure(surface->resource, - configure->serial, configure->state.width, configure->state.height); + configure->serial, configure->state.actual_width, + configure->state.actual_height); } static uint32_t wlr_layer_surface_schedule_configure( @@ -239,8 +238,8 @@ static uint32_t wlr_layer_surface_schedule_configure( void wlr_layer_surface_configure(struct wlr_layer_surface *surface, uint32_t width, uint32_t height) { - surface->server_pending.width = width; - surface->server_pending.height = height; + surface->server_pending.actual_width = width; + surface->server_pending.actual_height = height; wlr_layer_surface_schedule_configure(surface); } @@ -271,8 +270,8 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface, surface->current.margin = surface->client_pending.margin; surface->current.keyboard_interactive = surface->client_pending.keyboard_interactive; - surface->current.width = surface->client_pending.width; - surface->current.height = surface->client_pending.height; + surface->current.desired_width = surface->client_pending.desired_width; + surface->current.desired_height = surface->client_pending.desired_height; if (!surface->added) { surface->added = true; diff --git a/types/wlr_seat.c b/types/wlr_seat.c index 93f6d872..9793df74 100644 --- a/types/wlr_seat.c +++ b/types/wlr_seat.c @@ -1257,8 +1257,9 @@ bool wlr_seat_touch_has_grab(struct wlr_seat *seat) { } bool wlr_seat_validate_grab_serial(struct wlr_seat *seat, uint32_t serial) { - return serial == seat->pointer_state.grab_serial || - serial == seat->touch_state.grab_serial; + return true; + //return serial == seat->pointer_state.grab_serial || + // serial == seat->touch_state.grab_serial; } struct wlr_seat_client *wlr_seat_client_from_resource( -- cgit v1.2.3 From 0e318df13d4d98ffc69f2390562fc03aeca36f3b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 26 Mar 2018 18:44:36 -0400 Subject: Add margin animation to the example demo --- examples/layer-shell.c | 27 ++++++++++++++++++++++----- rootston/layer_shell.c | 28 +++++++++++++++++++++------- 2 files changed, 43 insertions(+), 12 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 3518a56f..4c501d3d 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -14,6 +14,7 @@ static struct wl_compositor *compositor = NULL; static struct zwlr_layer_shell_v1 *layer_shell = NULL; +struct zwlr_layer_surface_v1 *layer_surface; static struct wl_output *wl_output = NULL; struct wl_surface *wl_surface; @@ -26,8 +27,11 @@ static uint32_t output = 0; static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; static uint32_t anchor = 0; static uint32_t width = 256, height = 256; +static int32_t margin_top = 0; static double alpha = 1.0; static bool run_display = true; +static bool animate = false; +static double frame = 0; static struct { struct timespec last_frame; @@ -67,6 +71,18 @@ static void draw(void) { demo.dec = inc; } + if (animate) { + frame += ms / 50.0; + int32_t old_top = margin_top; + margin_top = -(20 - ((int)frame % 20)); + if (old_top != margin_top) { + wlr_log(L_DEBUG, "setting margin to %d", margin_top); + zwlr_layer_surface_v1_set_margin(layer_surface, + margin_top, 0, 0, 0); + wl_surface_commit(wl_surface); + } + } + glViewport(0, 0, width, height); glClearColor(demo.color[0], demo.color[1], demo.color[2], alpha); glClear(GL_COLOR_BUFFER_BIT); @@ -136,11 +152,10 @@ int main(int argc, char **argv) { wlr_log_init(L_DEBUG, NULL); char *namespace = "wlroots"; int exclusive_zone = 0; - int32_t margin_top = 0, margin_right = 0, - margin_bottom = 0, margin_left = 0; + int32_t margin_right = 0, margin_bottom = 0, margin_left = 0; bool found; int c; - while ((c = getopt(argc, argv, "w:h:o:l:a:x:m:t:")) != -1) { + while ((c = getopt(argc, argv, "nw:h:o:l:a:x:m:t:")) != -1) { switch (c) { case 'o': output = atoi(optarg); @@ -217,6 +232,9 @@ int main(int argc, char **argv) { assert(!*endptr); break; } + case 'n': + animate = true; + break; default: break; } @@ -253,8 +271,7 @@ int main(int argc, char **argv) { wl_surface = wl_compositor_create_surface(compositor); assert(wl_surface); - struct zwlr_layer_surface_v1 *layer_surface = - zwlr_layer_shell_v1_get_layer_surface(layer_shell, + layer_surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, wl_surface, wl_output, layer, namespace); assert(layer_surface); zwlr_layer_surface_v1_set_size(layer_surface, width, height); diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index e2d5b9f0..35896228 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -12,7 +12,9 @@ #include "rootston/server.h" static void apply_exclusive(struct wlr_box *usable_area, - uint32_t anchor, int32_t exclusive) { + uint32_t anchor, int32_t exclusive, + int32_t margin_top, int32_t margin_right, + int32_t margin_bottom, int32_t margin_left) { if (exclusive <= 0) { return; } @@ -20,6 +22,7 @@ static void apply_exclusive(struct wlr_box *usable_area, uint32_t anchors; int *positive_axis; int *negative_axis; + int margin; } edges[] = { { .anchors = @@ -28,6 +31,7 @@ static void apply_exclusive(struct wlr_box *usable_area, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, .positive_axis = &usable_area->y, .negative_axis = &usable_area->height, + .margin = margin_top, }, { .anchors = @@ -36,6 +40,7 @@ static void apply_exclusive(struct wlr_box *usable_area, ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, .positive_axis = NULL, .negative_axis = &usable_area->height, + .margin = margin_bottom, }, { .anchors = @@ -44,6 +49,7 @@ static void apply_exclusive(struct wlr_box *usable_area, ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, .positive_axis = &usable_area->x, .negative_axis = &usable_area->width, + .margin = margin_left, }, { .anchors = @@ -52,15 +58,16 @@ static void apply_exclusive(struct wlr_box *usable_area, ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, .positive_axis = NULL, .negative_axis = &usable_area->width, + .margin = margin_right, }, }; for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { if ((anchor & edges[i].anchors) == edges[i].anchors) { if (edges[i].positive_axis) { - *edges[i].positive_axis += exclusive; + *edges[i].positive_axis += exclusive + edges[i].margin; } if (edges[i].negative_axis) { - *edges[i].negative_axis -= exclusive; + *edges[i].negative_axis -= exclusive + edges[i].margin; } } } @@ -121,15 +128,15 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); } // Margin - if ((state->anchor & both_horiz)) { + if ((state->anchor & both_horiz) == both_horiz) { box.x += state->margin.left; box.width -= state->margin.left + state->margin.right; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { - box.x += state->margin.bottom; + box.x += state->margin.left; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { box.x -= state->margin.right; } - if ((state->anchor & both_vert)) { + if ((state->anchor & both_vert) == both_vert) { box.y += state->margin.top; box.height -= state->margin.top + state->margin.bottom; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { @@ -139,7 +146,11 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, } // Apply roots_surface->geo = box; - apply_exclusive(usable_area, state->anchor, state->exclusive_zone); + apply_exclusive(usable_area, state->anchor, state->exclusive_zone, + state->margin.top, state->margin.right, + state->margin.bottom, state->margin.left); + wlr_log(L_DEBUG, "arranged layer at %dx%d@%d,%d", + box.width, box.height, box.x, box.y); wlr_layer_surface_configure(layer, box.width, box.height); } } @@ -212,6 +223,9 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { struct roots_output *output = wlr_output->data; output_damage_from_local_surface(output, layer_surface->surface, layer->geo.x, layer->geo.y, 0); + arrange_layers(wlr_output); + output_damage_from_local_surface(output, layer_surface->surface, + layer->geo.x, layer->geo.y, 0); } } -- cgit v1.2.3 From 776b81d499ae4430c0ebe5421b119c6b3355a1ce Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 26 Mar 2018 23:13:09 -0400 Subject: Fix surface layer damage tracking --- examples/layer-shell.c | 1 - include/rootston/output.h | 4 +++- rootston/layer_shell.c | 16 ++++++++++------ rootston/output.c | 8 ++++++++ 4 files changed, 21 insertions(+), 8 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 4c501d3d..e559121e 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -76,7 +76,6 @@ static void draw(void) { int32_t old_top = margin_top; margin_top = -(20 - ((int)frame % 20)); if (old_top != margin_top) { - wlr_log(L_DEBUG, "setting margin to %d", margin_top); zwlr_layer_surface_v1_set_margin(layer_surface, margin_top, 0, 0, 0); wl_surface_commit(wl_surface); diff --git a/include/rootston/output.h b/include/rootston/output.h index 535c07d8..e40ad776 100644 --- a/include/rootston/output.h +++ b/include/rootston/output.h @@ -40,6 +40,8 @@ void output_damage_from_view(struct roots_output *output, void output_damage_whole_drag_icon(struct roots_output *output, struct roots_drag_icon *icon); void output_damage_from_local_surface(struct roots_output *output, - struct wlr_surface *surface, double ox, double oy, float rotation); + struct wlr_surface *surface, double ox, double oy, float rotation); +void output_damage_whole_local_surface(struct roots_output *output, + struct wlr_surface *surface, double ox, double oy, float rotation); #endif diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 35896228..5efdf3c9 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -149,8 +149,6 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, apply_exclusive(usable_area, state->anchor, state->exclusive_zone, state->margin.top, state->margin.right, state->margin.bottom, state->margin.left); - wlr_log(L_DEBUG, "arranged layer at %dx%d@%d,%d", - box.width, box.height, box.x, box.y); wlr_layer_surface_configure(layer, box.width, box.height); } } @@ -221,11 +219,17 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = layer_surface->output; if (wlr_output != NULL) { struct roots_output *output = wlr_output->data; - output_damage_from_local_surface(output, layer_surface->surface, - layer->geo.x, layer->geo.y, 0); + struct wlr_box old_geo = layer->geo; arrange_layers(wlr_output); - output_damage_from_local_surface(output, layer_surface->surface, - layer->geo.x, layer->geo.y, 0); + if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { + output_damage_whole_local_surface(output, layer_surface->surface, + old_geo.x, old_geo.y, 0); + output_damage_whole_local_surface(output, layer_surface->surface, + layer->geo.x, layer->geo.y, 0); + } else { + output_damage_from_local_surface(output, layer_surface->surface, + layer->geo.x, layer->geo.y, 0); + } } } diff --git a/rootston/output.c b/rootston/output.c index 7c2c6d44..aa74c8d7 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -664,6 +664,14 @@ static void damage_whole_surface(struct wlr_surface *surface, wlr_output_damage_add_box(output->damage, &box); } +void output_damage_whole_local_surface(struct roots_output *output, + struct wlr_surface *surface, double ox, double oy, float rotation) { + struct wlr_output_layout_output *layout = wlr_output_layout_get( + output->desktop->layout, output->wlr_output); + damage_whole_surface(surface, ox + layout->x, oy + layout->y, + rotation, output); +} + static void damage_whole_decoration(struct roots_view *view, struct roots_output *output) { if (!view->decorated || view->wlr_surface == NULL) { -- cgit v1.2.3 From 52fe2688ea1068d5cd0801ead4fc078c3a37dea1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 17:18:16 -0400 Subject: Address @emersion's feedback --- include/rootston/layers.h | 1 + include/wlr/types/wlr_layer_shell.h | 14 ++------- rootston/desktop.c | 6 ---- rootston/layer_shell.c | 19 +++++++----- types/wlr_layer_shell.c | 60 +++++++++++++------------------------ 5 files changed, 35 insertions(+), 65 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/include/rootston/layers.h b/include/rootston/layers.h index cc285fe7..35f5399e 100644 --- a/include/rootston/layers.h +++ b/include/rootston/layers.h @@ -16,6 +16,7 @@ struct roots_layer_surface { struct wl_listener surface_commit; struct wl_listener output_destroy; struct wl_listener output_mode; + struct wl_listener output_transform; bool configured; struct wlr_box geo; diff --git a/include/wlr/types/wlr_layer_shell.h b/include/wlr/types/wlr_layer_shell.h index c24b391e..e8da8e0f 100644 --- a/include/wlr/types/wlr_layer_shell.h +++ b/include/wlr/types/wlr_layer_shell.h @@ -21,7 +21,7 @@ */ struct wlr_layer_shell { struct wl_global *wl_global; - struct wl_list clients; + struct wl_list client_resources; // wl_resource struct wl_listener display_destroy; @@ -32,15 +32,6 @@ struct wlr_layer_shell { void *data; }; -struct wlr_layer_client { - struct wlr_layer_shell *shell; - struct wl_resource *resource; - struct wl_client *client; - struct wl_list surfaces; - - struct wl_list link; // wlr_layer_shell::clients -}; - struct wlr_layer_surface_state { uint32_t anchor; int32_t exclusive_zone; @@ -61,9 +52,8 @@ struct wlr_layer_surface_configure { struct wlr_layer_surface { struct wlr_surface *surface; struct wlr_output *output; - struct wlr_layer_client *client; struct wl_resource *resource; - struct wl_list link; // wlr_layer_client:surfaces + struct wlr_layer_shell *shell; const char *namespace; enum zwlr_layer_shell_v1_layer layer; diff --git a/rootston/desktop.c b/rootston/desktop.c index a0659250..9ea392f6 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -209,12 +209,6 @@ void view_arrange_maximized(struct roots_view *view) { usable_area.x += output_box->x; usable_area.y += output_box->y; - wlr_log(L_DEBUG, "output area: %dx%d@%d,%d", - output_box->width, output_box->height, - output_box->x, output_box->y); - wlr_log(L_DEBUG, "usable area: %dx%d@%d,%d", - usable_area.width, usable_area.height, - usable_area.x, usable_area.y); view_move_resize(view, usable_area.x, usable_area.y, usable_area.width, usable_area.height); view_rotate(view, 0); diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 5efdf3c9..809ddbf3 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -82,14 +82,8 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, wl_list_for_each(roots_surface, list, link) { struct wlr_layer_surface *layer = roots_surface->layer_surface; struct wlr_layer_surface_state *state = &layer->current; - if (exclusive) { - if (state->exclusive_zone <= 0) { - continue; - } - } else { - if (state->exclusive_zone > 0) { - continue; - } + if (exclusive != (state->exclusive_zone >0)) { + continue; } struct wlr_box bounds; if (state->exclusive_zone == -1) { @@ -212,6 +206,10 @@ static void handle_output_mode(struct wl_listener *listener, void *data) { arrange_layers((struct wlr_output *)data); } +static void handle_output_transform(struct wl_listener *listener, void *data) { + arrange_layers((struct wlr_output *)data); +} + static void handle_surface_commit(struct wl_listener *listener, void *data) { struct roots_layer_surface *layer = wl_container_of(listener, layer, surface_commit); @@ -254,6 +252,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } wl_list_remove(&layer->output_destroy.link); wl_list_remove(&layer->output_mode.link); + wl_list_remove(&layer->output_transform.link); arrange_layers(layer->layer_surface->output); free(layer); } @@ -304,6 +303,10 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&layer_surface->output->events.mode, &roots_surface->output_mode); + roots_surface->output_transform.notify = handle_output_transform; + wl_signal_add(&layer_surface->output->events.transform, + &roots_surface->output_transform); + roots_surface->destroy.notify = handle_destroy; wl_signal_add(&layer_surface->events.destroy, &roots_surface->destroy); roots_surface->map.notify = handle_map; diff --git a/types/wlr_layer_shell.c b/types/wlr_layer_shell.c index 761d2413..532309a3 100644 --- a/types/wlr_layer_shell.c +++ b/types/wlr_layer_shell.c @@ -18,7 +18,7 @@ static void resource_handle_destroy(struct wl_client *client, static const struct zwlr_layer_shell_v1_interface layer_shell_implementation; static const struct zwlr_layer_surface_v1_interface layer_surface_implementation; -static struct wlr_layer_client *layer_client_from_resource( +static struct wlr_layer_shell *layer_shell_from_resource( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &zwlr_layer_shell_v1_interface, &layer_shell_implementation)); @@ -58,7 +58,7 @@ static void layer_surface_handle_ack_configure(struct wl_client *client, } } if (!found) { - wl_resource_post_error(surface->client->resource, + wl_resource_post_error(resource, ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SURFACE_STATE, "wrong configure serial: %u", serial); return; @@ -156,7 +156,6 @@ static void layer_surface_destroy(struct wlr_layer_surface *surface) { layer_surface_unmap(surface); wlr_signal_emit_safe(&surface->events.destroy, surface); wl_resource_set_user_data(surface->resource, NULL); - wl_list_remove(&surface->link); wl_list_remove(&surface->surface_destroy_listener.link); wlr_surface_set_role_committed(surface->surface, NULL, NULL); free(surface); @@ -195,11 +194,11 @@ void wlr_layer_surface_configure(struct wlr_layer_surface *surface, surface->server_pending.actual_height = height; if (wlr_layer_surface_state_changed(surface)) { struct wl_display *display = - wl_client_get_display(surface->client->client); + wl_client_get_display(wl_resource_get_client(surface->resource)); struct wlr_layer_surface_configure *configure = calloc(1, sizeof(struct wlr_layer_surface_configure)); if (configure == NULL) { - wl_client_post_no_memory(surface->client->client); + wl_client_post_no_memory(wl_resource_get_client(surface->resource)); return; } surface->configure_next_serial = wl_display_next_serial(display); @@ -248,7 +247,7 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface, if (!surface->added) { surface->added = true; - wlr_signal_emit_safe(&surface->client->shell->events.new_surface, + wlr_signal_emit_safe(&surface->shell->events.new_surface, surface); } if (surface->configured && wlr_surface_has_buffer(surface->surface) && @@ -274,8 +273,8 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, struct wl_resource *surface_resource, struct wl_resource *output_resource, uint32_t layer, const char *namespace) { - struct wlr_layer_client *client = - layer_client_from_resource(client_resource); + struct wlr_layer_shell *shell = + layer_shell_from_resource(client_resource); struct wlr_layer_surface *surface = calloc(1, sizeof(struct wlr_layer_surface)); @@ -284,7 +283,7 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, return; } - surface->client = client; + surface->shell = shell; surface->surface = wlr_surface_from_resource(surface_resource); surface->output = wlr_output_from_resource(output_resource); surface->resource = wl_resource_create(wl_client, @@ -322,23 +321,14 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, surface, surface->resource); wl_resource_set_implementation(surface->resource, &layer_surface_implementation, surface, layer_surface_resource_destroy); - wl_list_insert(&client->surfaces, &surface->link); } static const struct zwlr_layer_shell_v1_interface layer_shell_implementation = { .get_layer_surface = layer_shell_handle_get_layer_surface, }; -static void wlr_layer_client_destroy(struct wl_resource *resource) { - struct wlr_layer_client *client = layer_client_from_resource(resource); - - struct wlr_layer_surface *surface, *tmp = NULL; - wl_list_for_each_safe(surface, tmp, &client->surfaces, link) { - layer_surface_destroy(surface); - } - - wl_list_remove(&client->link); - free(client); +static void client_handle_destroy(struct wl_resource *resource) { + wl_list_remove(wl_resource_get_link(resource)); } static void layer_shell_bind(struct wl_client *wl_client, void *data, @@ -346,28 +336,16 @@ static void layer_shell_bind(struct wl_client *wl_client, void *data, struct wlr_layer_shell *layer_shell = data; assert(wl_client && layer_shell); - struct wlr_layer_client *client = - calloc(1, sizeof(struct wlr_layer_client)); - if (client == NULL) { - wl_client_post_no_memory(wl_client); - return; - } - - wl_list_init(&client->surfaces); - - client->resource = wl_resource_create( + struct wl_resource *resource = wl_resource_create( wl_client, &zwlr_layer_shell_v1_interface, version, id); - if (client->resource == NULL) { - free(client); + if (resource == NULL) { wl_client_post_no_memory(wl_client); return; } - client->client = wl_client; - client->shell = layer_shell; - - wl_resource_set_implementation(client->resource, - &layer_shell_implementation, client, wlr_layer_client_destroy); - wl_list_insert(&layer_shell->clients, &client->link); + wl_resource_set_implementation(resource, + &layer_shell_implementation, layer_shell, client_handle_destroy); + wl_list_insert(&layer_shell->client_resources, + wl_resource_get_link(resource)); } static void handle_display_destroy(struct wl_listener *listener, void *data) { @@ -383,7 +361,7 @@ struct wlr_layer_shell *wlr_layer_shell_create(struct wl_display *display) { return NULL; } - wl_list_init(&layer_shell->clients); + wl_list_init(&layer_shell->client_resources); struct wl_global *wl_global = wl_global_create(display, &zwlr_layer_shell_v1_interface, 1, layer_shell, layer_shell_bind); @@ -405,6 +383,10 @@ void wlr_layer_shell_destroy(struct wlr_layer_shell *layer_shell) { if (!layer_shell) { return; } + struct wl_resource *client, *tmp; + wl_resource_for_each_safe(client, tmp, &layer_shell->client_resources) { + wl_resource_destroy(client); + } wl_list_remove(&layer_shell->display_destroy.link); wl_global_destroy(layer_shell->wl_global); free(layer_shell); -- cgit v1.2.3 From a1d5d20914b25ef2d9820f04d885f22d6488d5e1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 17:36:35 -0400 Subject: Address some more feedback --- rootston/layer_shell.c | 7 +++++++ rootston/output.c | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 809ddbf3..d6428c51 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -138,6 +138,11 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { box.y -= state->margin.bottom; } + if (box.width < 0 || box.height < 0) { + // TODO: Bubble up a protocol error? + wlr_layer_surface_close(layer); + continue; + } // Apply roots_surface->geo = box; apply_exclusive(usable_area, state->anchor, state->exclusive_zone, @@ -177,6 +182,7 @@ static void arrange_layers(struct wlr_output *_output) { } // Arrange non-exlusive surfaces from top->bottom + usable_area.x = usable_area.y = 0; wlr_output_effective_resolution(output->wlr_output, &usable_area.width, &usable_area.height); arrange_layer(output->wlr_output, @@ -313,6 +319,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&layer_surface->events.map, &roots_surface->map); roots_surface->unmap.notify = handle_unmap; wl_signal_add(&layer_surface->events.unmap, &roots_surface->unmap); + // TODO: Listen for subsurfaces roots_surface->layer_surface = layer_surface; layer_surface->data = roots_surface; diff --git a/rootston/output.c b/rootston/output.c index aa74c8d7..d903963e 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -560,14 +560,15 @@ static void render_output(struct roots_output *output) { wl_list_for_each_reverse(view, &desktop->views, link) { render_view(view, &data); } + // Render top layer above shell views + render_layer(output, output_box, &data, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } // Render drag icons data.alpha = 1.0; drag_icons_for_each_surface(server->input, render_surface, &data); - render_layer(output, output_box, &data, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); render_layer(output, output_box, &data, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); @@ -670,6 +671,7 @@ void output_damage_whole_local_surface(struct roots_output *output, output->desktop->layout, output->wlr_output); damage_whole_surface(surface, ox + layout->x, oy + layout->y, rotation, output); + // TODO: subsurfaces } static void damage_whole_decoration(struct roots_view *view, @@ -743,6 +745,7 @@ void output_damage_from_local_surface(struct roots_output *output, output->desktop->layout, output->wlr_output); damage_from_surface(surface, ox + layout->x, oy + layout->y, rotation, output); + // TODO: Subsurfaces } void output_damage_from_view(struct roots_output *output, -- cgit v1.2.3 From 3e5131e664c605f406756bae51d1276a67b5fa38 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 21:25:40 -0400 Subject: Address further review feedback --- rootston/desktop.c | 14 +++++++------- rootston/layer_shell.c | 9 +++++---- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/rootston/desktop.c b/rootston/desktop.c index 9ea392f6..15e0e336 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -192,13 +192,6 @@ void view_arrange_maximized(struct roots_view *view) { struct wlr_box view_box; view_get_box(view, &view_box); - view->maximized = true; - view->saved.x = view->x; - view->saved.y = view->y; - view->saved.rotation = view->rotation; - view->saved.width = view_box.width; - view->saved.height = view_box.height; - struct wlr_output *output = view_get_output(view); struct roots_output *roots_output = output->data; struct wlr_box *output_box = @@ -224,6 +217,13 @@ void view_maximize(struct roots_view *view, bool maximized) { } if (!view->maximized && maximized) { + view->maximized = true; + view->saved.x = view->x; + view->saved.y = view->y; + view->saved.rotation = view->rotation; + view->saved.width = view->width; + view->saved.height = view->height; + view_arrange_maximized(view); } diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index d6428c51..06ab15c3 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -239,10 +239,6 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { static void unmap(struct wlr_layer_surface *layer_surface) { struct roots_layer_surface *layer = layer_surface->data; - if (layer->link.prev) { - wl_list_remove(&layer->link); - } - struct wlr_output *wlr_output = layer_surface->output; if (wlr_output != NULL) { struct roots_output *output = wlr_output->data; @@ -256,6 +252,11 @@ static void handle_destroy(struct wl_listener *listener, void *data) { if (layer->layer_surface->mapped) { unmap(layer->layer_surface); } + wl_list_remove(&layer->link); + wl_list_remove(&layer->destroy.link); + wl_list_remove(&layer->map.link); + wl_list_remove(&layer->unmap.link); + wl_list_remove(&layer->surface_commit.link); wl_list_remove(&layer->output_destroy.link); wl_list_remove(&layer->output_mode.link); wl_list_remove(&layer->output_transform.link); -- cgit v1.2.3 From b887af9a6013ea0466b6152e74f69659d7d45711 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 12:18:13 -0400 Subject: Fix maximized windows interaction with layer shell If there were no layer surfaces the usable area of the output would be an empty box. --- include/rootston/layers.h | 6 +++--- include/rootston/output.h | 2 ++ rootston/layer_shell.c | 31 +++++-------------------------- rootston/output.c | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 29 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/include/rootston/layers.h b/include/rootston/layers.h index 35f5399e..0e5164bb 100644 --- a/include/rootston/layers.h +++ b/include/rootston/layers.h @@ -1,7 +1,6 @@ #ifndef ROOTSTON_LAYERS_H #define ROOTSTON_LAYERS_H #include -#include #include #include #include @@ -15,11 +14,12 @@ struct roots_layer_surface { struct wl_listener unmap; struct wl_listener surface_commit; struct wl_listener output_destroy; - struct wl_listener output_mode; - struct wl_listener output_transform; bool configured; struct wlr_box geo; }; +struct roots_output; +void arrange_layers(struct roots_output *output); + #endif diff --git a/include/rootston/output.h b/include/rootston/output.h index e40ad776..bf152038 100644 --- a/include/rootston/output.h +++ b/include/rootston/output.h @@ -23,6 +23,8 @@ struct roots_output { struct wlr_box usable_area; struct wl_listener destroy; + struct wl_listener mode; + struct wl_listener transform; struct wl_listener damage_frame; struct wl_listener damage_destroy; }; diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 06ab15c3..edfaf5ea 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -82,7 +82,7 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, wl_list_for_each(roots_surface, list, link) { struct wlr_layer_surface *layer = roots_surface->layer_surface; struct wlr_layer_surface_state *state = &layer->current; - if (exclusive != (state->exclusive_zone >0)) { + if (exclusive != (state->exclusive_zone > 0)) { continue; } struct wlr_box bounds; @@ -152,9 +152,7 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, } } -static void arrange_layers(struct wlr_output *_output) { - struct roots_output *output = _output->data; - +void arrange_layers(struct roots_output *output) { struct wlr_box usable_area = { 0 }; wlr_output_effective_resolution(output->wlr_output, &usable_area.width, &usable_area.height); @@ -204,18 +202,9 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, layer, output_destroy); layer->layer_surface->output = NULL; wl_list_remove(&layer->output_destroy.link); - wl_list_remove(&layer->output_mode.link); wlr_layer_surface_close(layer->layer_surface); } -static void handle_output_mode(struct wl_listener *listener, void *data) { - arrange_layers((struct wlr_output *)data); -} - -static void handle_output_transform(struct wl_listener *listener, void *data) { - arrange_layers((struct wlr_output *)data); -} - static void handle_surface_commit(struct wl_listener *listener, void *data) { struct roots_layer_surface *layer = wl_container_of(listener, layer, surface_commit); @@ -224,7 +213,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { if (wlr_output != NULL) { struct roots_output *output = wlr_output->data; struct wlr_box old_geo = layer->geo; - arrange_layers(wlr_output); + arrange_layers(output); if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { output_damage_whole_local_surface(output, layer_surface->surface, old_geo.x, old_geo.y, 0); @@ -258,9 +247,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&layer->unmap.link); wl_list_remove(&layer->surface_commit.link); wl_list_remove(&layer->output_destroy.link); - wl_list_remove(&layer->output_mode.link); - wl_list_remove(&layer->output_transform.link); - arrange_layers(layer->layer_surface->output); + arrange_layers((struct roots_output *)layer->layer_surface->output->data); free(layer); } @@ -306,14 +293,6 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&layer_surface->output->events.destroy, &roots_surface->output_destroy); - roots_surface->output_mode.notify = handle_output_mode; - wl_signal_add(&layer_surface->output->events.mode, - &roots_surface->output_mode); - - roots_surface->output_transform.notify = handle_output_transform; - wl_signal_add(&layer_surface->output->events.transform, - &roots_surface->output_transform); - roots_surface->destroy.notify = handle_destroy; wl_signal_add(&layer_surface->events.destroy, &roots_surface->destroy); roots_surface->map.notify = handle_map; @@ -333,7 +312,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { struct wlr_layer_surface_state old_state = layer_surface->current; layer_surface->current = layer_surface->client_pending; - arrange_layers(output->wlr_output); + arrange_layers(output); layer_surface->current = old_state; } diff --git a/rootston/output.c b/rootston/output.c index d903963e..bf2bbdc2 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -816,6 +816,18 @@ static void output_damage_handle_destroy(struct wl_listener *listener, output_destroy(output); } +static void output_handle_mode(struct wl_listener *listener, void *data) { + struct roots_output *output = + wl_container_of(listener, output, mode); + arrange_layers(output); +} + +static void output_handle_transform(struct wl_listener *listener, void *data) { + struct roots_output *output = + wl_container_of(listener, output, transform); + arrange_layers(output); +} + void handle_new_output(struct wl_listener *listener, void *data) { struct roots_desktop *desktop = wl_container_of(listener, desktop, new_output); @@ -845,6 +857,11 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->destroy.notify = output_handle_destroy; wl_signal_add(&wlr_output->events.destroy, &output->destroy); + output->mode.notify = output_handle_mode; + wl_signal_add(&wlr_output->events.mode, &output->mode); + output->transform.notify = output_handle_transform; + wl_signal_add(&wlr_output->events.transform, &output->transform); + output->damage_frame.notify = output_damage_handle_frame; wl_signal_add(&output->damage->events.frame, &output->damage_frame); output->damage_destroy.notify = output_damage_handle_destroy; @@ -879,5 +896,6 @@ void handle_new_output(struct wl_listener *listener, void *data) { roots_seat_configure_xcursor(seat); } + arrange_layers(output); output_damage_whole(output); } -- cgit v1.2.3 From d466cc117f95d34e239049a5af701b7ba696d336 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 14:55:17 -0400 Subject: Don't reset exclusive between layer shell passes This is not the intended behavior of exclusive zones, the second pass is meant to respect the usable area. --- rootston/layer_shell.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'rootston/layer_shell.c') diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index edfaf5ea..d3a91659 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -180,9 +180,6 @@ void arrange_layers(struct roots_output *output) { } // Arrange non-exlusive surfaces from top->bottom - usable_area.x = usable_area.y = 0; - wlr_output_effective_resolution(output->wlr_output, - &usable_area.width, &usable_area.height); arrange_layer(output->wlr_output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &usable_area, false); -- cgit v1.2.3