mirror of
https://github.com/cage-kiosk/cage.git
synced 2026-03-01 01:40:36 -05:00
layer-shell: initial layer shell v1 implementation
This commit is contained in:
parent
0e946d5a4f
commit
8a11a66d87
8 changed files with 538 additions and 24 deletions
120
output.c
120
output.c
|
|
@ -21,6 +21,11 @@
|
|||
#if WLR_HAS_X11_BACKEND
|
||||
#include <wlr/backend/x11.h>
|
||||
#endif
|
||||
#include "layer_shell_v1.h"
|
||||
#include "output.h"
|
||||
#include "seat.h"
|
||||
#include "server.h"
|
||||
#include "view.h"
|
||||
#include <wlr/render/swapchain.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
|
|
@ -33,11 +38,6 @@
|
|||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/util/region.h>
|
||||
|
||||
#include "output.h"
|
||||
#include "seat.h"
|
||||
#include "server.h"
|
||||
#include "view.h"
|
||||
#if CAGE_HAS_XWAYLAND
|
||||
#include "xwayland.h"
|
||||
#endif
|
||||
|
|
@ -205,12 +205,23 @@ output_destroy(struct cg_output *output)
|
|||
|
||||
output->wlr_output->data = NULL;
|
||||
|
||||
struct cg_layer_surface *layer, *layer_tmp;
|
||||
wl_list_for_each_safe (layer, layer_tmp, &output->layer_surfaces, link) {
|
||||
layer->output = NULL;
|
||||
wlr_layer_surface_v1_destroy(layer->layer_surface);
|
||||
}
|
||||
|
||||
wl_list_remove(&output->destroy.link);
|
||||
wl_list_remove(&output->commit.link);
|
||||
wl_list_remove(&output->request_state.link);
|
||||
wl_list_remove(&output->frame.link);
|
||||
wl_list_remove(&output->link);
|
||||
|
||||
wlr_scene_node_destroy(&output->layers.shell_background->node);
|
||||
wlr_scene_node_destroy(&output->layers.shell_bottom->node);
|
||||
wlr_scene_node_destroy(&output->layers.shell_top->node);
|
||||
wlr_scene_node_destroy(&output->layers.shell_overlay->node);
|
||||
|
||||
output_layout_remove(output);
|
||||
|
||||
free(output);
|
||||
|
|
@ -231,6 +242,18 @@ handle_output_destroy(struct wl_listener *listener, void *data)
|
|||
output_destroy(output);
|
||||
}
|
||||
|
||||
static struct wlr_scene_tree *
|
||||
create_layer_for_output(struct cg_output *output)
|
||||
{
|
||||
struct cg_server *server = output->server;
|
||||
struct wlr_scene_tree *layer = wlr_scene_tree_create(&server->scene->tree);
|
||||
if (layer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
layer->node.data = output->wlr_output;
|
||||
return layer;
|
||||
}
|
||||
|
||||
void
|
||||
handle_new_output(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
|
@ -252,6 +275,7 @@ handle_new_output(struct wl_listener *listener, void *data)
|
|||
wlr_output->data = output;
|
||||
output->server = server;
|
||||
|
||||
wl_list_init(&output->layer_surfaces);
|
||||
wl_list_insert(&server->outputs, &output->link);
|
||||
|
||||
output->commit.notify = handle_output_commit;
|
||||
|
|
@ -296,6 +320,11 @@ handle_new_output(struct wl_listener *listener, void *data)
|
|||
output_disable(next);
|
||||
}
|
||||
|
||||
output->layers.shell_background = create_layer_for_output(output);
|
||||
output->layers.shell_bottom = create_layer_for_output(output);
|
||||
output->layers.shell_top = create_layer_for_output(output);
|
||||
output->layers.shell_overlay = create_layer_for_output(output);
|
||||
|
||||
if (!wlr_xcursor_manager_load(server->seat->xcursor_manager, wlr_output->scale)) {
|
||||
wlr_log(WLR_ERROR, "Cannot load XCursor theme for output '%s' with scale %f", wlr_output->name,
|
||||
wlr_output->scale);
|
||||
|
|
@ -391,6 +420,87 @@ out:
|
|||
return ok;
|
||||
}
|
||||
|
||||
static void
|
||||
arrange_surface(struct cg_output *output, const struct wlr_box *full_area, struct wlr_box *usable_area,
|
||||
enum zwlr_layer_shell_v1_layer layer, bool exclusive)
|
||||
{
|
||||
struct cg_layer_surface *surface;
|
||||
wl_list_for_each (surface, &output->layer_surfaces, link) {
|
||||
struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
|
||||
|
||||
if (layer_surface->current.layer != layer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!layer_surface->initialized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((layer_surface->current.exclusive_zone > 0) != exclusive) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wlr_scene_layer_surface_v1_configure(surface->scene, full_area, usable_area);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
arrange_layers(struct cg_output *output)
|
||||
{
|
||||
struct wlr_box usable_area = {0};
|
||||
wlr_output_effective_resolution(output->wlr_output, &usable_area.width, &usable_area.height);
|
||||
const struct wlr_box full_area = usable_area;
|
||||
|
||||
arrange_surface(output, &full_area, &usable_area, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, true);
|
||||
arrange_surface(output, &full_area, &usable_area, ZWLR_LAYER_SHELL_V1_LAYER_TOP, true);
|
||||
arrange_surface(output, &full_area, &usable_area, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, true);
|
||||
arrange_surface(output, &full_area, &usable_area, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, true);
|
||||
|
||||
arrange_surface(output, &full_area, &usable_area, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, false);
|
||||
arrange_surface(output, &full_area, &usable_area, ZWLR_LAYER_SHELL_V1_LAYER_TOP, false);
|
||||
arrange_surface(output, &full_area, &usable_area, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, false);
|
||||
arrange_surface(output, &full_area, &usable_area, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, false);
|
||||
|
||||
if (!wlr_box_equal(&usable_area, &output->usable_area)) {
|
||||
wlr_log(WLR_DEBUG, "Usable area changed, rearranging output");
|
||||
output->usable_area = usable_area;
|
||||
view_position_all(output->server);
|
||||
}
|
||||
|
||||
enum zwlr_layer_shell_v1_layer layers_above_shell[] = {
|
||||
ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
|
||||
ZWLR_LAYER_SHELL_V1_LAYER_TOP,
|
||||
};
|
||||
size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]);
|
||||
struct cg_layer_surface *topmost = NULL;
|
||||
for (size_t i = 0; i < nlayers; ++i) {
|
||||
struct cg_layer_surface *surface;
|
||||
wl_list_for_each_reverse (surface, &output->layer_surfaces, link) {
|
||||
struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
|
||||
if (layer_surface->current.layer != layers_above_shell[i]) {
|
||||
continue;
|
||||
}
|
||||
if (layer_surface->current.keyboard_interactive ==
|
||||
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE &&
|
||||
layer_surface->surface->mapped) {
|
||||
topmost = surface;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (topmost != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct cg_seat *seat = output->server->seat;
|
||||
if (topmost != NULL) {
|
||||
seat_set_focus_layer(seat, topmost->layer_surface);
|
||||
} else if (seat->focused_layer && seat->focused_layer->current.keyboard_interactive !=
|
||||
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
|
||||
seat_set_focus_layer(seat, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_output_manager_apply(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue