diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 870a3f22..245d762f 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -1,6 +1,7 @@ #define _POSIX_C_SOURCE 199309L #include #include +#include #include #include #include @@ -28,7 +29,7 @@ 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 output = UINT32_MAX; static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; static uint32_t anchor = 0; static uint32_t width = 256, height = 256; @@ -283,11 +284,13 @@ static void handle_global(void *data, struct wl_registry *registry, 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, - &wl_output_interface, 1); - } else { - output--; + if (output != UINT32_MAX) { + if (!wl_output) { + wl_output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + } else { + output--; + } } } else if (strcmp(interface, wl_seat_interface.name) == 0) { seat = wl_registry_bind(registry, name, @@ -426,10 +429,6 @@ int main(int argc, char **argv) { fprintf(stderr, "layer_shell not available\n"); return 1; } - if (wl_output == NULL) { - fprintf(stderr, "wl_output not available\n"); - return 1; - } cursor_theme = wl_cursor_theme_load(NULL, 16, shm); assert(cursor_theme); diff --git a/include/rootston/input.h b/include/rootston/input.h index 4395a0f7..ef46fab2 100644 --- a/include/rootston/input.h +++ b/include/rootston/input.h @@ -30,4 +30,6 @@ bool input_view_has_focus(struct roots_input *input, struct roots_view *view); struct roots_seat *input_get_seat(struct roots_input *input, char *name); +struct roots_seat *input_last_active_seat(struct roots_input *input); + #endif diff --git a/include/wlr/types/wlr_layer_shell.h b/include/wlr/types/wlr_layer_shell.h index 1312e568..79b3a4ea 100644 --- a/include/wlr/types/wlr_layer_shell.h +++ b/include/wlr/types/wlr_layer_shell.h @@ -27,6 +27,9 @@ struct wlr_layer_shell { struct wl_listener display_destroy; struct { + // struct wlr_layer_surface * + // Note: the output may be NULL. In this case, it is your + // responsibility to assign an output before returning. struct wl_signal new_surface; } events; diff --git a/protocol/wlr-layer-shell-unstable-v1.xml b/protocol/wlr-layer-shell-unstable-v1.xml index 3181c0bb..6a5d5d35 100644 --- a/protocol/wlr-layer-shell-unstable-v1.xml +++ b/protocol/wlr-layer-shell-unstable-v1.xml @@ -47,12 +47,16 @@ or manipulate a buffer prior to the first layer_surface.configure call must also be treated as errors. + You may pass NULL for output to allow the compositor to decide which + output to use. Generally this will be the one that the user most + recently interacted with. + Clients can specify a namespace that defines the purpose of the layer surface. - + diff --git a/rootston/desktop.c b/rootston/desktop.c index 6ddf56b8..0949b5db 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -326,13 +326,7 @@ bool view_center(struct roots_view *view) { struct roots_desktop *desktop = view->desktop; struct roots_input *input = desktop->server->input; - struct roots_seat *seat = NULL, *_seat; - wl_list_for_each(_seat, &input->seats, link) { - if (!seat || (seat->seat->last_event.tv_sec > _seat->seat->last_event.tv_sec && - seat->seat->last_event.tv_nsec > _seat->seat->last_event.tv_nsec)) { - seat = _seat; - } - } + struct roots_seat *seat = input_last_active_seat(input); if (!seat) { return false; } diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 895b0385..b6f7ba4c 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -312,6 +312,18 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { return; } + if (!layer_surface->output) { + struct roots_input *input = desktop->server->input; + struct roots_seat *seat = input_last_active_seat(input); + assert(seat); // Technically speaking we should handle this case + struct wlr_output *output = + wlr_output_layout_output_at(desktop->layout, + seat->cursor->cursor->x, + seat->cursor->cursor->y); + assert(output); // And this one + layer_surface->output = output; + } + roots_surface->surface_commit.notify = handle_surface_commit; wl_signal_add(&layer_surface->surface->events.commit, &roots_surface->surface_commit); diff --git a/rootston/seat.c b/rootston/seat.c index e12df7d6..44673c75 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -999,3 +999,14 @@ void roots_seat_end_compositor_grab(struct roots_seat *seat) { cursor->mode = ROOTS_CURSOR_PASSTHROUGH; } + +struct roots_seat *input_last_active_seat(struct roots_input *input) { + struct roots_seat *seat = NULL, *_seat; + wl_list_for_each(_seat, &input->seats, link) { + if (!seat || (seat->seat->last_event.tv_sec > _seat->seat->last_event.tv_sec && + seat->seat->last_event.tv_nsec > _seat->seat->last_event.tv_nsec)) { + seat = _seat; + } + } + return seat; +} diff --git a/types/wlr_layer_shell.c b/types/wlr_layer_shell.c index c4e39a17..a567b8bc 100644 --- a/types/wlr_layer_shell.c +++ b/types/wlr_layer_shell.c @@ -276,6 +276,7 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface, surface->added = true; wlr_signal_emit_safe(&surface->shell->events.new_surface, surface); + assert(surface->output); } if (surface->configured && wlr_surface_has_buffer(surface->surface) && !surface->mapped) { @@ -319,7 +320,9 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, surface->shell = shell; surface->surface = wlr_surface; - surface->output = wlr_output_from_resource(output_resource); + if (output_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),