From f29d8b55aec7c19fd12b81b39e6806d6b996fadc Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 17 Mar 2018 15:07:48 -0400 Subject: Initial scaffolding of layer shell --- rootston/desktop.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'rootston/desktop.c') diff --git a/rootston/desktop.c b/rootston/desktop.c index 65d9a280..dcf0b7b2 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -9,9 +9,10 @@ #include #include #include +#include +#include #include #include -#include #include #include #include @@ -714,6 +715,9 @@ struct roots_desktop *desktop_create(struct roots_server *server, &desktop->wl_shell_surface); desktop->wl_shell_surface.notify = handle_wl_shell_surface; + desktop->layer_shell = wlr_layer_shell_create(server->wl_display); + // TODO: Pick up new surfaces + #ifdef WLR_HAS_XWAYLAND const char *cursor_theme = NULL; const char *cursor_default = ROOTS_XCURSOR_DEFAULT; -- cgit v1.2.3 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 --- examples/layer-shell.c | 211 +++++++++++++++++++++++++++++++ examples/meson.build | 6 + include/rootston/desktop.h | 5 + include/rootston/layers.h | 19 +++ include/rootston/view.h | 1 - protocol/meson.build | 1 + protocol/wlr-layer-shell-unstable-v1.xml | 5 +- rootston/desktop.c | 4 +- rootston/layer_shell.c | 54 ++++++++ rootston/meson.build | 1 + 10 files changed, 302 insertions(+), 5 deletions(-) create mode 100644 examples/layer-shell.c create mode 100644 include/rootston/layers.h create mode 100644 rootston/layer_shell.c (limited to 'rootston/desktop.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c new file mode 100644 index 00000000..285bec5a --- /dev/null +++ b/examples/layer-shell.c @@ -0,0 +1,211 @@ +#define _POSIX_C_SOURCE 2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wlr-layer-shell-unstable-v1-client-protocol.h" + +static struct wl_compositor *compositor = NULL; +static struct zwlr_layer_shell_v1 *layer_shell = NULL; +static struct wl_output *wl_output = NULL; + +struct wl_surface *wl_surface; +struct wlr_egl egl; +struct wl_egl_window *egl_window; +struct wlr_egl_surface *egl_surface; +struct wl_callback *frame_callback; + +static uint32_t output = 0; +static uint32_t layer = -1; +static uint32_t anchor = 0; +static uint32_t width = 256, height = 256; + +static void draw(void); + +static void surface_frame_callback( + void *data, struct wl_callback *cb, uint32_t time) { + wl_callback_destroy(cb); + frame_callback = NULL; + draw(); +} + +static struct wl_callback_listener frame_listener = { + .done = surface_frame_callback +}; + +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}; + glViewport(0, 0, width, height); + glClearColor(color[0], color[1], 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); +} + +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t w, uint32_t h) { + width = w; + height = h; + zwlr_layer_surface_v1_ack_configure(surface, serial); +} + +struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, +}; + +static void handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + if (strcmp(interface, "wl_compositor") == 0) { + compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, "wl_output") == 0) { + if (output == 0) { + wl_output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + } else { + output--; + } + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); + } +} + +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares +} + +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; + +int main(int argc, char **argv) { + wlr_log_init(L_DEBUG, NULL); + char *namespace = "wlroots"; + bool found; + int c; + while ((c = getopt(argc, argv, "w:h:o:"))) { + switch (c) { + case 'o': + output = atoi(optarg); + break; + case 'w': + width = atoi(optarg); + break; + case 'h': + height = atoi(optarg); + break; + case 'l': { + struct { + char *name; + enum zwlr_layer_shell_v1_layer value; + } layers[] = { + { "background", ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND }, + { "bottom", ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM }, + { "top", ZWLR_LAYER_SHELL_V1_LAYER_TOP }, + { "overlay", ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY }, + }; + found = false; + for (size_t i = 0; i < sizeof(layers) / sizeof(layers[0]); ++i) { + if (strcmp(optarg, layers[i].name)) { + layer = layers[i].value; + found = true; + break; + } + } + if (!found) { + fprintf(stderr, "invalid layer %s\n", optarg); + return 1; + } + break; + } + case 'a': { + struct { + char *name; + uint32_t value; + } anchors[] = { + { "top", ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP }, + { "bottom", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM }, + { "left", ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT }, + { "right", ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT }, + }; + found = false; + for (size_t i = 0; i < sizeof(anchors) / sizeof(anchors[0]); ++i) { + if (strcmp(optarg, anchors[i].name)) { + anchor |= anchors[i].value; + found = true; + break; + } + } + if (!found) { + fprintf(stderr, "invalid anchor %s\n", optarg); + return 1; + } + } + default: + break; + } + } + + struct wl_display *display = wl_display_connect(NULL); + if (display == NULL) { + fprintf(stderr, "Failed to create display\n"); + return 1; + } + + struct wl_registry *registry = wl_display_get_registry(display); + wl_registry_add_listener(registry, ®istry_listener, NULL); + wl_display_dispatch(display); + wl_display_roundtrip(display); + + if (compositor == NULL) { + fprintf(stderr, "wl-compositor not available\n"); + return 1; + } + if (layer_shell == NULL) { + fprintf(stderr, "layer-shell not available\n"); + return 1; + } + if (wl_output == NULL) { + fprintf(stderr, "wl_output not available\n"); + return 1; + } + + wlr_egl_init(&egl, EGL_PLATFORM_WAYLAND_EXT, display, NULL, + WL_SHM_FORMAT_ARGB8888); + + wl_surface = wl_compositor_create_surface(compositor); + + 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_anchor(layer_surface, anchor); + // TODO: margin, interactivity, exclusive zone + + wl_surface_commit(wl_surface); + + egl_window = wl_egl_window_create(wl_surface, width, height); + egl_surface = wlr_egl_create_surface(&egl, egl_window); + + wl_display_roundtrip(display); + draw(); + + while (wl_display_dispatch(display) != -1) { + // This space intentionally left blank + } + return 0; +} diff --git a/examples/meson.build b/examples/meson.build index a83def8f..558af4ac 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -48,3 +48,9 @@ executable( dependencies: [wayland_client, wlr_protos, wlroots, threads], link_with: lib_shared, ) + +executable( + 'layer-shell', + 'layer-shell.c', + dependencies: [wayland_client, wlr_protos, wlroots] +) diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 5ff9f5e2..ad7654a1 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,8 @@ 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; @@ -55,6 +58,7 @@ struct roots_desktop { struct wl_listener xdg_shell_v6_surface; struct wl_listener xdg_shell_surface; struct wl_listener wl_shell_surface; + struct wl_listener layer_shell_surface; struct wl_listener decoration_new; #ifdef WLR_HAS_XWAYLAND @@ -88,6 +92,7 @@ void view_unmap(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); void handle_wl_shell_surface(struct wl_listener *listener, void *data); +void handle_layer_shell_surface(struct wl_listener *listener, void *data); void handle_xwayland_surface(struct wl_listener *listener, void *data); #endif diff --git a/include/rootston/layers.h b/include/rootston/layers.h new file mode 100644 index 00000000..269056ea --- /dev/null +++ b/include/rootston/layers.h @@ -0,0 +1,19 @@ +#ifndef ROOTSTON_LAYERS_H +#define ROOTSTON_LAYERS_H +#include +#include +#include +#include +#include + +struct roots_layer_surface { + struct wlr_layer_surface *layer_surface; + struct wl_list link; + + struct wl_listener destroy; + struct wl_listener map; + struct wl_listener unmap; + struct wl_listener surface_commit; +}; + +#endif diff --git a/include/rootston/view.h b/include/rootston/view.h index 1397a8d2..6e746e8c 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -1,6 +1,5 @@ #ifndef ROOTSTON_VIEW_H #define ROOTSTON_VIEW_H - #include #include #include diff --git a/protocol/meson.build b/protocol/meson.build index 8c8a7c0e..a41fdec3 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -39,6 +39,7 @@ client_protocols = [ [wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], 'idle.xml', 'screenshooter.xml', + 'wlr-layer-shell-unstable-v1.xml', ] wl_protos_src = [] diff --git a/protocol/wlr-layer-shell-unstable-v1.xml b/protocol/wlr-layer-shell-unstable-v1.xml index 285c9b8f..c4f2a7e3 100644 --- a/protocol/wlr-layer-shell-unstable-v1.xml +++ b/protocol/wlr-layer-shell-unstable-v1.xml @@ -222,9 +222,8 @@ - - - + diff --git a/rootston/desktop.c b/rootston/desktop.c index dcf0b7b2..015a8215 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -716,7 +716,9 @@ struct roots_desktop *desktop_create(struct roots_server *server, desktop->wl_shell_surface.notify = handle_wl_shell_surface; desktop->layer_shell = wlr_layer_shell_create(server->wl_display); - // TODO: Pick up new surfaces + wl_signal_add(&desktop->layer_shell->events.new_surface, + &desktop->layer_shell_surface); + desktop->layer_shell_surface.notify = handle_layer_shell_surface; #ifdef WLR_HAS_XWAYLAND const char *cursor_theme = NULL; 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); +} diff --git a/rootston/meson.build b/rootston/meson.build index 9dbe37c2..1b78c7c8 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -5,6 +5,7 @@ sources = [ 'ini.c', 'input.c', 'keyboard.c', + 'layer_shell.c', 'main.c', 'output.c', 'seat.c', -- cgit v1.2.3 From fcf8c6c8a29e3ce0a17bcf7ce1ca92fed8493502 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 19 Mar 2018 20:24:16 -0400 Subject: Fix issues preventing layer from getting allocated Now all of the steps to get rootston a reference to the layer surface are correctly wired up. --- examples/layer-shell.c | 13 +++++++------ rootston/desktop.c | 4 ++++ types/wlr_layer_shell.c | 25 ++++++++++++++++++------- 3 files changed, 29 insertions(+), 13 deletions(-) (limited to 'rootston/desktop.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 9b26386d..d2e07a90 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -21,7 +21,7 @@ struct wlr_egl_surface *egl_surface; struct wl_callback *frame_callback; static uint32_t output = 0; -static uint32_t layer = -1; +static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; static uint32_t anchor = 0; static uint32_t width = 256, height = 256; @@ -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:"))) { + while ((c = getopt(argc, argv, "w:h:o:")) != -1) { switch (c) { case 'o': output = atoi(optarg); @@ -185,9 +185,6 @@ 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); struct zwlr_layer_surface_v1 *layer_surface = @@ -195,8 +192,12 @@ int main(int argc, char **argv) { wl_surface, wl_output, layer, namespace); zwlr_layer_surface_v1_set_anchor(layer_surface, anchor); // 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, + WL_SHM_FORMAT_ARGB8888); egl_window = wl_egl_window_create(wl_surface, width, height); egl_surface = wlr_egl_create_surface(&egl, egl_window); diff --git a/rootston/desktop.c b/rootston/desktop.c index 015a8215..f00fc63f 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -719,6 +719,10 @@ 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/types/wlr_layer_shell.c b/types/wlr_layer_shell.c index 8063b219..aaf9ee84 100644 --- a/types/wlr_layer_shell.c +++ b/types/wlr_layer_shell.c @@ -14,20 +14,20 @@ static void resource_handle_destroy(struct wl_client *client, wl_resource_destroy(resource); } -static struct zwlr_layer_shell_v1_interface layer_shell_impl; -static struct zwlr_layer_surface_v1_interface layer_surface_impl; +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( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &zwlr_layer_shell_v1_interface, - &layer_shell_impl)); + &layer_shell_implementation)); return wl_resource_get_user_data(resource); } static struct wlr_layer_surface *layer_surface_from_resource( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &zwlr_layer_surface_v1_interface, - &layer_surface_impl)); + &layer_surface_implementation)); return wl_resource_get_user_data(resource); } @@ -291,11 +291,22 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, wl_client_post_no_memory(wl_client); return; } + if (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) { + wl_resource_post_error(surface->resource, + ZWLR_LAYER_SHELL_V1_ERROR_INVALID_LAYER, + "Invalid layer %d", layer); + free(surface); + return; + } + + wl_list_init(&surface->configure_list); wl_signal_init(&surface->events.destroy); wl_signal_add(&surface->surface->events.destroy, &surface->surface_destroy_listener); surface->surface_destroy_listener.notify = handle_wlr_surface_destroyed; + wl_signal_init(&surface->events.map); + wl_signal_init(&surface->events.unmap); wlr_surface_set_role_committed(surface->surface, handle_wlr_surface_committed, surface); @@ -307,7 +318,7 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, wl_list_insert(&client->surfaces, &surface->link); } -static struct zwlr_layer_shell_v1_interface layer_shell_impl = { +static const struct zwlr_layer_shell_v1_interface layer_shell_implementation = { .get_layer_surface = layer_shell_handle_get_layer_surface, }; @@ -347,8 +358,8 @@ static void layer_shell_bind(struct wl_client *wl_client, void *data, client->client = wl_client; client->shell = layer_shell; - wl_resource_set_implementation(client->resource, &layer_shell_impl, client, - wlr_layer_client_destroy); + wl_resource_set_implementation(client->resource, + &layer_shell_implementation, client, wlr_layer_client_destroy); wl_list_insert(&layer_shell->clients, &client->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/desktop.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 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/desktop.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 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/desktop.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 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/desktop.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 662f40b8ae2ccb449b13074317b59f0e53c1ccc5 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 15:19:33 -0400 Subject: Refactor cursor event passhtrough --- include/rootston/desktop.h | 4 ++ rootston/cursor.c | 117 ++++++++++++++++++++++----------------------- rootston/desktop.c | 19 ++++++++ 3 files changed, 80 insertions(+), 60 deletions(-) (limited to 'rootston/desktop.c') diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 5714aa0a..5816df48 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -73,8 +73,12 @@ struct roots_desktop *desktop_create(struct roots_server *server, void desktop_destroy(struct roots_desktop *desktop); struct roots_output *desktop_output_from_wlr_output( struct roots_desktop *desktop, struct wlr_output *output); + struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); +struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, + double lx, double ly, double *sx, double *sy, + struct roots_view **view); struct roots_view *view_create(struct roots_desktop *desktop); void view_destroy(struct roots_view *view); diff --git a/rootston/cursor.c b/rootston/cursor.c index c794cbce..1a7526d1 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -10,6 +10,7 @@ #include #endif #include "rootston/cursor.h" +#include "rootston/desktop.h" #include "rootston/xcursor.h" struct roots_cursor *roots_cursor_create(struct roots_seat *seat) { @@ -98,51 +99,56 @@ static void seat_view_deco_button(struct roots_seat_view *view, double sx, } } -static void roots_cursor_update_position(struct roots_cursor *cursor, +static void roots_passthrough_cursor(struct roots_cursor *cursor, uint32_t time) { - struct roots_desktop *desktop = cursor->seat->input->server->desktop; - struct roots_seat *seat = cursor->seat; struct roots_view *view; - struct wlr_surface *surface = NULL; double sx, sy; - switch (cursor->mode) { - case ROOTS_CURSOR_PASSTHROUGH: - view = desktop_view_at(desktop, cursor->cursor->x, cursor->cursor->y, - &surface, &sx, &sy); + + struct roots_seat *seat = cursor->seat; + struct roots_desktop *desktop = seat->input->server->desktop; + struct wlr_surface *surface = desktop_surface_at(desktop, + cursor->cursor->x, cursor->cursor->y, &sx, &sy, &view); + + if (!surface && cursor->cursor_client) { + wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, + cursor->default_xcursor, cursor->cursor); + cursor->cursor_client = NULL; + } + + if (view) { struct roots_seat_view *seat_view = roots_seat_view_from_view(seat, view); - if (cursor->pointer_view && (surface || seat_view != cursor->pointer_view)) { + if (cursor->pointer_view && (surface || + seat_view != cursor->pointer_view)) { seat_view_deco_leave(cursor->pointer_view); cursor->pointer_view = NULL; } - bool set_compositor_cursor = !view && !surface && cursor->cursor_client; - if (view && surface) { - struct wl_client *view_client = - wl_resource_get_client(view->wlr_surface->resource); - set_compositor_cursor = view_client != cursor->cursor_client; - } - if (set_compositor_cursor) { - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, - cursor->default_xcursor, cursor->cursor); - cursor->cursor_client = NULL; - } - if (view && !surface) { - if (seat_view) { - cursor->pointer_view = seat_view; - seat_view_deco_motion(seat_view, sx, sy); - } - } if (view && surface) { - // motion over a view surface - wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy); - } else { - wlr_seat_pointer_clear_focus(seat->seat); + if (!surface) { + cursor->pointer_view = seat_view; + seat_view_deco_motion(seat_view, sx, sy); } + } - struct roots_drag_icon *drag_icon; - wl_list_for_each(drag_icon, &seat->drag_icons, link) { - roots_drag_icon_update_position(drag_icon); - } + if (surface) { + wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy); + wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy); + } else { + wlr_seat_pointer_clear_focus(seat->seat); + } + + struct roots_drag_icon *drag_icon; + wl_list_for_each(drag_icon, &seat->drag_icons, link) { + roots_drag_icon_update_position(drag_icon); + } +} + +static void roots_cursor_update_position( + struct roots_cursor *cursor, uint32_t time) { + struct roots_seat *seat = cursor->seat; + struct roots_view *view; + switch (cursor->mode) { + case ROOTS_CURSOR_PASSTHROUGH: + roots_passthrough_cursor(cursor, time); break; case ROOTS_CURSOR_MOVE: view = roots_seat_get_focus(seat); @@ -180,15 +186,9 @@ static void roots_cursor_update_position(struct roots_cursor *cursor, } else if (cursor->resize_edges & WLR_EDGE_RIGHT) { width += dx; } - - if (width < 1) { - width = 1; - } - if (height < 1) { - height = 1; - } - - view_move_resize(view, x, y, width, height); + view_move_resize(view, x, y, + width < 1 ? 1 : width, + height < 1 ? 1 : height); } break; case ROOTS_CURSOR_ROTATE: @@ -214,15 +214,15 @@ static void roots_cursor_press_button(struct roots_cursor *cursor, uint32_t state, double lx, double ly) { struct roots_seat *seat = cursor->seat; struct roots_desktop *desktop = seat->input->server->desktop; + bool is_touch = device->type == WLR_INPUT_DEVICE_TOUCH; - struct wlr_surface *surface = NULL; double sx, sy; - struct roots_view *view = - desktop_view_at(desktop, lx, ly, &surface, &sx, &sy); + struct roots_view *view; + struct wlr_surface *surface = desktop_surface_at(desktop, + lx, ly, &sx, &sy, &view); - if (state == WLR_BUTTON_PRESSED && - view && + if (state == WLR_BUTTON_PRESSED && view && roots_seat_has_meta_pressed(seat)) { roots_seat_set_focus(seat, view); @@ -250,11 +250,9 @@ static void roots_cursor_press_button(struct roots_cursor *cursor, break; } } else { - - if (view && !surface) { - if (cursor->pointer_view) { - seat_view_deco_button(cursor->pointer_view, sx, sy, button, state); - } + if (view && !surface && cursor->pointer_view) { + seat_view_deco_button(cursor->pointer_view, + sx, sy, button, state); } if (state == WLR_BUTTON_RELEASED && @@ -308,7 +306,6 @@ void roots_cursor_handle_axis(struct roots_cursor *cursor, void roots_cursor_handle_touch_down(struct roots_cursor *cursor, struct wlr_event_touch_down *event) { struct roots_desktop *desktop = cursor->seat->input->server->desktop; - struct wlr_surface *surface = NULL; double lx, ly; bool result = wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, event->x, event->y, &lx, &ly); @@ -316,7 +313,8 @@ void roots_cursor_handle_touch_down(struct roots_cursor *cursor, return; } double sx, sy; - desktop_view_at(desktop, lx, ly, &surface, &sx, &sy); + struct wlr_surface *surface = desktop_surface_at( + desktop, lx, ly, &sx, &sy, NULL); uint32_t serial = 0; if (surface) { @@ -359,17 +357,16 @@ void roots_cursor_handle_touch_motion(struct roots_cursor *cursor, return; } - struct wlr_surface *surface = NULL; double lx, ly; - bool result = - wlr_cursor_absolute_to_layout_coords(cursor->cursor, + bool result = wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, event->x, event->y, &lx, &ly); if (!result) { return; } double sx, sy; - desktop_view_at(desktop, lx, ly, &surface, &sx, &sy); + struct wlr_surface *surface = desktop_surface_at( + desktop, lx, ly, &sx, &sy, NULL); if (surface) { wlr_seat_touch_point_focus(cursor->seat->seat, surface, diff --git a/rootston/desktop.c b/rootston/desktop.c index 15e0e336..532e720b 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -657,6 +657,25 @@ struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx, return NULL; } +struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, + double lx, double ly, double *sx, double *sy, + struct roots_view **view) { + //struct wlr_output *wlr_output = + // wlr_output_layout_output_at(desktop->layout, lx, ly); + // TODO: Iterate over layers + *view = NULL; + struct roots_view *_view; + struct wlr_surface *surface = NULL; + if ((_view = desktop_view_at(desktop, lx, ly, &surface, sx, sy))) { + if (view) { + *view = _view; + } + return surface; + } + // TODO: Iterate over layers + return NULL; +} + static void handle_layout_change(struct wl_listener *listener, void *data) { struct roots_desktop *desktop = wl_container_of(listener, desktop, layout_change); -- cgit v1.2.3 From dc412c514b88d253dc86cf72a574530e12b7dcb7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 16:54:37 -0400 Subject: Find layer surfaces for input events --- include/rootston/desktop.h | 3 -- include/rootston/output.h | 1 - rootston/desktop.c | 71 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 11 deletions(-) (limited to 'rootston/desktop.c') diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 5816df48..c1dcad56 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -1,6 +1,5 @@ #ifndef ROOTSTON_DESKTOP_H #define ROOTSTON_DESKTOP_H - #include #include #include @@ -74,8 +73,6 @@ void desktop_destroy(struct roots_desktop *desktop); struct roots_output *desktop_output_from_wlr_output( struct roots_desktop *desktop, struct wlr_output *output); -struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx, - double ly, struct wlr_surface **surface, double *sx, double *sy); struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, double lx, double ly, double *sx, double *sy, struct roots_view **view); diff --git a/include/rootston/output.h b/include/rootston/output.h index bf152038..f78ee81d 100644 --- a/include/rootston/output.h +++ b/include/rootston/output.h @@ -1,6 +1,5 @@ #ifndef ROOTSTON_OUTPUT_H #define ROOTSTON_OUTPUT_H - #include #include #include diff --git a/rootston/desktop.c b/rootston/desktop.c index 532e720b..aa06000c 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -20,10 +20,12 @@ #include #include #include +#include "rootston/layers.h" #include "rootston/seat.h" #include "rootston/server.h" #include "rootston/view.h" #include "rootston/xcursor.h" +#include "wlr-layer-shell-unstable-v1-protocol.h" struct roots_view *view_create(struct roots_desktop *desktop) { struct roots_view *view = calloc(1, sizeof(struct roots_view)); @@ -632,8 +634,9 @@ static bool view_at(struct roots_view *view, double lx, double ly, return false; } -struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx, - double ly, struct wlr_surface **surface, double *sx, double *sy) { +static struct roots_view *desktop_view_at(struct roots_desktop *desktop, + double lx, double ly, struct wlr_surface **surface, + double *sx, double *sy) { struct wlr_output *wlr_output = wlr_output_layout_output_at(desktop->layout, lx, ly); if (wlr_output != NULL) { @@ -657,22 +660,76 @@ struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx, return NULL; } +static struct wlr_surface *layer_surface_at(struct roots_output *output, + struct wl_list *layer, double ox, double oy, double *sx, double *sy) { + struct roots_layer_surface *roots_surface; + wl_list_for_each_reverse(roots_surface, layer, link) { + struct wlr_surface *wlr_surface = + roots_surface->layer_surface->surface; + double _sx = ox - roots_surface->geo.x; + double _sy = oy - roots_surface->geo.y; + struct wlr_box box = { + .x = 0, .y = 0, + .width = roots_surface->geo.width, + .height = roots_surface->geo.height, + }; + // TODO: Test popups/subsurfaces + if (wlr_box_contains_point(&box, _sx, _sy) && + pixman_region32_contains_point(&wlr_surface->current->input, + _sx, _sy, NULL)) { + *sx = _sx; + *sy = _sy; + return wlr_surface; + } + } + return NULL; +} + struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, double lx, double ly, double *sx, double *sy, struct roots_view **view) { - //struct wlr_output *wlr_output = - // wlr_output_layout_output_at(desktop->layout, lx, ly); - // TODO: Iterate over layers + struct wlr_surface *surface = NULL; + struct wlr_output *wlr_output = + wlr_output_layout_output_at(desktop->layout, lx, ly); + struct roots_output *roots_output; + double ox, oy; + if (wlr_output) { + roots_output = wlr_output->data; + wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); + + if ((surface = layer_surface_at(roots_output, + &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + ox, oy, sx, sy))) { + return surface; + } + if ((surface = layer_surface_at(roots_output, + &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + ox, oy, sx, sy))) { + return surface; + } + } + *view = NULL; struct roots_view *_view; - struct wlr_surface *surface = NULL; if ((_view = desktop_view_at(desktop, lx, ly, &surface, sx, sy))) { if (view) { *view = _view; } return surface; } - // TODO: Iterate over layers + + if (wlr_output) { + if ((surface = layer_surface_at(roots_output, + &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + ox, oy, sx, sy))) { + return surface; + } + if ((surface = layer_surface_at(roots_output, + &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + ox, oy, sx, sy))) { + return surface; + } + } return NULL; } -- cgit v1.2.3 From e3eb487dc2c3ed51b974212ddb15ce839289eba2 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 17:26:58 -0400 Subject: Add pointer support to layer shell example --- examples/layer-shell.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++--- examples/meson.build | 3 +- rootston/desktop.c | 11 ++-- 3 files changed, 148 insertions(+), 15 deletions(-) (limited to 'rootston/desktop.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 70407888..6e293f55 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -7,12 +7,17 @@ #include #include #include +#include #include #include #include #include "wlr-layer-shell-unstable-v1-client-protocol.h" static struct wl_compositor *compositor = NULL; +static struct wl_seat *seat = NULL; +static struct wl_shm *shm = NULL; +static struct wl_pointer *pointer = NULL; +//static struct wl_keyboard *keyboard = NULL; static struct zwlr_layer_shell_v1 *layer_shell = NULL; struct zwlr_layer_surface_v1 *layer_surface; static struct wl_output *wl_output = NULL; @@ -32,6 +37,12 @@ static double alpha = 1.0; static bool run_display = true; static bool animate = false; static double frame = 0; +static int cur_x = -1, cur_y = -1; +static int buttons = 0; + +struct wl_cursor_theme *cursor_theme; +struct wl_cursor_image *cursor_image; +struct wl_surface *cursor_surface; static struct { struct timespec last_frame; @@ -62,13 +73,15 @@ static void draw(void) { (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 (!buttons) { + 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; + if (demo.color[demo.dec] < 0.0f) { + demo.color[inc] = 1.0f; + demo.color[demo.dec] = 0.0f; + demo.dec = inc; + } } if (animate) { @@ -83,9 +96,21 @@ static void draw(void) { } glViewport(0, 0, width, height); - glClearColor(demo.color[0], demo.color[1], demo.color[2], alpha); + if (buttons) { + glClearColor(1, 1, 1, alpha); + } else { + glClearColor(demo.color[0], demo.color[1], demo.color[2], alpha); + } glClear(GL_COLOR_BUFFER_BIT); + if (cur_x != -1 && cur_y != -1) { + glEnable(GL_SCISSOR_TEST); + glScissor(cur_x, height - cur_y, 5, 5); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + } + frame_callback = wl_surface_frame(wl_surface); wl_callback_add_listener(frame_callback, &frame_listener, NULL); @@ -119,11 +144,101 @@ struct zwlr_layer_surface_v1_listener layer_surface_listener = { .closed = layer_surface_closed, }; +static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + wl_surface_attach(cursor_surface, + wl_cursor_image_get_buffer(cursor_image), 0, 0); + wl_pointer_set_cursor(wl_pointer, serial, cursor_surface, + cursor_image->hotspot_x, cursor_image->hotspot_y); + wl_surface_commit(cursor_surface); +} + +static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) { + cur_x = cur_y = -1; +} + +static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { + cur_x = (int)wl_fixed_to_double(surface_x); + cur_y = (int)wl_fixed_to_double(surface_y); +} + +static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + if (state == WL_POINTER_BUTTON_STATE_PRESSED) { + buttons++; + } else { + buttons--; + } +} + +static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { + // Who cares +} + +static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { + // Who cares +} + +static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) { + // Who cares +} + +static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) { + // Who cares +} + +static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) { + // Who cares +} + +struct wl_pointer_listener pointer_listener = { + .enter = wl_pointer_enter, + .leave = wl_pointer_leave, + .motion = wl_pointer_motion, + .button = wl_pointer_button, + .axis = wl_pointer_axis, + .frame = wl_pointer_frame, + .axis_source = wl_pointer_axis_source, + .axis_stop = wl_pointer_axis_stop, + .axis_discrete = wl_pointer_axis_discrete, +}; + +static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) { + if ((caps & WL_SEAT_CAPABILITY_POINTER)) { + pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(pointer, &pointer_listener, NULL); + } + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { + // TODO + } +} + +static void seat_handle_name(void *data, struct wl_seat *wl_seat, + const char *name) { + // Who cares +} + +const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { if (strcmp(interface, "wl_compositor") == 0) { compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); } else if (strcmp(interface, "wl_output") == 0) { if (output == 0 && !wl_output) { wl_output = wl_registry_bind(registry, name, @@ -131,6 +246,10 @@ static void handle_global(void *data, struct wl_registry *registry, } else { output--; } + } else if (strcmp(interface, wl_seat_interface.name) == 0) { + seat = wl_registry_bind(registry, name, + &wl_seat_interface, 1); + wl_seat_add_listener(seat, &seat_listener, NULL); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); @@ -250,11 +369,15 @@ int main(int argc, char **argv) { wl_display_roundtrip(display); if (compositor == NULL) { - fprintf(stderr, "wl-compositor not available\n"); + fprintf(stderr, "wl_compositor not available\n"); + return 1; + } + if (shm == NULL) { + fprintf(stderr, "wl_shm not available\n"); return 1; } if (layer_shell == NULL) { - fprintf(stderr, "layer-shell not available\n"); + fprintf(stderr, "layer_shell not available\n"); return 1; } if (wl_output == NULL) { @@ -262,6 +385,12 @@ int main(int argc, char **argv) { return 1; } + assert(cursor_theme = wl_cursor_theme_load(NULL, 16, shm)); + struct wl_cursor *cursor; + assert(cursor = wl_cursor_theme_get_cursor(cursor_theme, "left_ptr")); + cursor_image = cursor->images[0]; + assert(cursor_surface = wl_compositor_create_surface(compositor)); + EGLint attribs[] = { EGL_ALPHA_SIZE, 8, EGL_NONE }; wlr_egl_init(&egl, EGL_PLATFORM_WAYLAND_EXT, display, attribs, WL_SHM_FORMAT_ARGB8888); @@ -294,5 +423,7 @@ int main(int argc, char **argv) { while (wl_display_dispatch(display) != -1 && run_display) { // This space intentionally left blank } + + wl_cursor_theme_destroy(cursor_theme); return 0; } diff --git a/examples/meson.build b/examples/meson.build index 558af4ac..9e60c37a 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -6,6 +6,7 @@ lib_shared = static_library( ) threads = dependency('threads') +wayland_cursor = dependency('wayland-cursor') executable('simple', 'simple.c', dependencies: wlroots, link_with: lib_shared) executable('pointer', 'pointer.c', dependencies: wlroots, link_with: lib_shared) @@ -52,5 +53,5 @@ executable( executable( 'layer-shell', 'layer-shell.c', - dependencies: [wayland_client, wlr_protos, wlroots] + dependencies: [wayland_cursor, wayland_client, wlr_protos, wlroots] ) diff --git a/rootston/desktop.c b/rootston/desktop.c index aa06000c..45bf8105 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -669,12 +669,13 @@ static struct wlr_surface *layer_surface_at(struct roots_output *output, double _sx = ox - roots_surface->geo.x; double _sy = oy - roots_surface->geo.y; struct wlr_box box = { - .x = 0, .y = 0, - .width = roots_surface->geo.width, - .height = roots_surface->geo.height, + .x = roots_surface->geo.x, + .y = roots_surface->geo.y, + .width = wlr_surface->current->width, + .height = wlr_surface->current->height, }; // TODO: Test popups/subsurfaces - if (wlr_box_contains_point(&box, _sx, _sy) && + if (wlr_box_contains_point(&box, ox, oy) && pixman_region32_contains_point(&wlr_surface->current->input, _sx, _sy, NULL)) { *sx = _sx; @@ -692,7 +693,7 @@ struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, struct wlr_output *wlr_output = wlr_output_layout_output_at(desktop->layout, lx, ly); struct roots_output *roots_output; - double ox, oy; + double ox = lx, oy = ly; if (wlr_output) { roots_output = wlr_output->data; wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); -- cgit v1.2.3 From 168f65fb7a336c7f7067bfd56413b2d19556c8bf Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 18:28:21 -0400 Subject: Minor bugfixes --- examples/layer-shell.c | 1 + rootston/desktop.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'rootston/desktop.c') diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 6e293f55..3f955be4 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -157,6 +157,7 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { cur_x = cur_y = -1; + buttons = 0; } static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, diff --git a/rootston/desktop.c b/rootston/desktop.c index 45bf8105..7ee2c69a 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -694,6 +694,8 @@ struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, wlr_output_layout_output_at(desktop->layout, lx, ly); struct roots_output *roots_output; double ox = lx, oy = ly; + *view = NULL; + if (wlr_output) { roots_output = wlr_output->data; wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); @@ -710,7 +712,6 @@ struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, } } - *view = NULL; struct roots_view *_view; if ((_view = desktop_view_at(desktop, lx, ly, &surface, sx, sy))) { if (view) { -- cgit v1.2.3 From e19ee6d469a98d2957e614243ea30674be1977f7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 22:19:33 -0400 Subject: Add wlr_surface_point_accepts_input Ref https://github.com/swaywm/sway/pull/1674 --- include/wlr/types/wlr_surface.h | 3 +++ rootston/desktop.c | 14 ++------------ types/wlr_surface.c | 7 +++++++ 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'rootston/desktop.c') diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index 5c5b012f..4d03df73 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -134,6 +134,9 @@ struct wlr_surface *wlr_surface_get_main_surface(struct wlr_surface *surface); struct wlr_subsurface *wlr_surface_subsurface_at(struct wlr_surface *surface, double sx, double sy, double *sub_x, double *sub_y); +bool wlr_surface_point_accepts_input( + struct wlr_surface *surface, double sx, double sy); + void wlr_surface_send_enter(struct wlr_surface *surface, struct wlr_output *output); diff --git a/rootston/desktop.c b/rootston/desktop.c index 7ee2c69a..1d2e9549 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -622,9 +622,7 @@ static bool view_at(struct roots_view *view, double lx, double ly, return true; } - if (wlr_box_contains_point(&box, view_sx, view_sy) && - pixman_region32_contains_point(&view->wlr_surface->current->input, - view_sx, view_sy, NULL)) { + if (wlr_surface_point_accepts_input(view->wlr_surface, view_sx, view_sy)) { *sx = view_sx; *sy = view_sy; *surface = view->wlr_surface; @@ -668,16 +666,8 @@ static struct wlr_surface *layer_surface_at(struct roots_output *output, roots_surface->layer_surface->surface; double _sx = ox - roots_surface->geo.x; double _sy = oy - roots_surface->geo.y; - struct wlr_box box = { - .x = roots_surface->geo.x, - .y = roots_surface->geo.y, - .width = wlr_surface->current->width, - .height = wlr_surface->current->height, - }; // TODO: Test popups/subsurfaces - if (wlr_box_contains_point(&box, ox, oy) && - pixman_region32_contains_point(&wlr_surface->current->input, - _sx, _sy, NULL)) { + if (wlr_surface_point_accepts_input(wlr_surface, _sx, _sy)) { *sx = _sx; *sy = _sy; return wlr_surface; diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 672e6fea..e9bd6a66 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -952,3 +952,10 @@ void wlr_surface_set_role_committed(struct wlr_surface *surface, surface->role_committed = role_committed; surface->role_data = role_data; } + +bool wlr_surface_point_accepts_input( + struct wlr_surface *surface, double sx, double sy) { + return sx >= 0 && sx <= surface->current->width && + sy >= 0 && sy <= surface->current->height && + pixman_region32_contains_point(&surface->current->input, sx, sy, NULL); +} -- cgit v1.2.3 From 692f1746cff0377393011f698484dc4f6cf030b8 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 00:22:58 -0400 Subject: xwayland: specify xwm cursor stride in bytes --- rootston/desktop.c | 2 +- xwayland/xwm.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'rootston/desktop.c') diff --git a/rootston/desktop.c b/rootston/desktop.c index 1d2e9549..0668d8cb 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -834,7 +834,7 @@ struct roots_desktop *desktop_create(struct roots_server *server, if (xcursor != NULL) { struct wlr_xcursor_image *image = xcursor->images[0]; wlr_xwayland_set_cursor(desktop->xwayland, image->buffer, - image->width, image->width, image->height, image->hotspot_x, + image->width * 4, image->width, image->height, image->hotspot_x, image->hotspot_y); } } diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 2743cc53..6702c3c9 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -1378,7 +1378,6 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, xcb_free_cursor(xwm->xcb_conn, xwm->cursor); } - stride *= 4; int depth = 32; xcb_pixmap_t pix = xcb_generate_id(xwm->xcb_conn); -- cgit v1.2.3 From 3f6823092ad9bfa1def3c33e5d3c2d3cdbc676fa Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Sat, 31 Mar 2018 12:55:36 +0300 Subject: Initialize roots_output to fix -Wmaybe-uninitialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With -O2: ../rootston/desktop.c: In function ‘desktop_surface_at’: ../rootston/desktop.c:714:18: error: ‘roots_output’ may be used uninitialized in this function [-Werror=maybe-uninitialized] if ((surface = layer_surface_at(roots_output, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ox, oy, sx, sy))) { ~~~~~~~~~~~~~~~ --- rootston/desktop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rootston/desktop.c') diff --git a/rootston/desktop.c b/rootston/desktop.c index 0668d8cb..c2e424cf 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -682,7 +682,7 @@ struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, struct wlr_surface *surface = NULL; struct wlr_output *wlr_output = wlr_output_layout_output_at(desktop->layout, lx, ly); - struct roots_output *roots_output; + struct roots_output *roots_output = NULL; double ox = lx, oy = ly; *view = NULL; -- cgit v1.2.3 From 937362b5521fe501d3fb060c5c73e6ae18cc0826 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 09:55:41 -0400 Subject: FIx crash on touch down --- rootston/desktop.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'rootston/desktop.c') diff --git a/rootston/desktop.c b/rootston/desktop.c index c2e424cf..ab16ed3d 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -684,7 +684,9 @@ struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop, wlr_output_layout_output_at(desktop->layout, lx, ly); struct roots_output *roots_output = NULL; double ox = lx, oy = ly; - *view = NULL; + if (view) { + *view = NULL; + } if (wlr_output) { roots_output = wlr_output->data; -- cgit v1.2.3