layer-shell: initial layer shell v1 implementation

This commit is contained in:
Moon Sungjoon 2024-07-22 20:30:16 +09:00 committed by Sungjoon Moon
parent c82ec0585b
commit b43b55b361
3 changed files with 117 additions and 1 deletions

View file

@ -8,15 +8,63 @@
#include "layer_shell_v1.h" #include "layer_shell_v1.h"
#include "output.h" #include "output.h"
#include "seat.h"
#include "server.h" #include "server.h"
#include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <complex.h> #include <complex.h>
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wayland-util.h> #include <wayland-util.h>
#include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#define NUM_LAYERS (4)
static void
arrange_surface(struct cg_output *output, const struct wlr_box *full_area, struct wlr_box *usable_area,
struct wlr_scene_tree *tree)
{
struct wlr_scene_node *node;
wl_list_for_each (node, &tree->children, link) {
struct cg_view *view = node->data;
if (!view) {
continue;
}
struct cg_layer_surface *surface = (struct cg_layer_surface *) view;
if (!surface->scene->layer_surface->initialized) {
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, output->layers.shell_background);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay);
if (!wlr_box_equal(&usable_area, &output->usable_area)) {
wlr_log(WLR_DEBUG, "Usable area changed, rearranging output");
output->usable_area = usable_area;
// arrange_output(output);
} else {
// arrange_popups(root->layers.popup);
// FIXME: popup is not implemented
}
}
static struct wlr_scene_tree * static struct wlr_scene_tree *
cg_layer_get_scene(struct cg_output *output, enum zwlr_layer_shell_v1_layer layer_type) cg_layer_get_scene(struct cg_output *output, enum zwlr_layer_shell_v1_layer layer_type)
{ {
@ -34,6 +82,57 @@ cg_layer_get_scene(struct cg_output *output, enum zwlr_layer_shell_v1_layer laye
return NULL; return NULL;
} }
static void
handle_map(struct wl_listener *listener, void *data)
{
struct cg_layer_surface *surface = wl_container_of(listener, surface, map);
struct wlr_layer_surface_v1 *layer_surface = surface->scene->layer_surface;
struct cg_server *server = surface->server;
// focus on new surface
if (layer_surface->current.keyboard_interactive &&
(layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY ||
layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP)) {
struct cg_seat *seat = server->seat;
if (!seat->focused_layer || seat->focused_layer->current.layer >= layer_surface->current.layer) {
// seat_set_focus_layer(seat, layer_surface);
}
arrange_layers(surface->output);
}
}
static void
handle_unmap(struct wl_listener *listener, void *data)
{
}
static void
handle_surface_commit(struct wl_listener *listener, void *data)
{
struct cg_layer_surface *surface = wl_container_of(listener, surface, surface_commit);
struct wlr_layer_surface_v1 *layer_surface = surface->scene->layer_surface;
if (!layer_surface->initialized) {
return;
}
uint32_t committed = layer_surface->current.committed;
if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
struct wlr_scene_tree *output_layer = cg_layer_get_scene(surface->output, layer_type);
wlr_scene_node_reparent(&surface->scene->tree->node, output_layer);
}
if (layer_surface->initial_commit || committed || layer_surface->surface->mapped != surface->mapped) {
surface->mapped = layer_surface->surface->mapped;
arrange_layers(surface->output);
}
}
static void
handle_output_destroy(struct wl_listener *listener, void *data)
{
}
void void
handle_layer_shell_v1_surface_new(struct wl_listener *listener, void *data) handle_layer_shell_v1_surface_new(struct wl_listener *listener, void *data)
{ {
@ -49,6 +148,7 @@ handle_layer_shell_v1_surface_new(struct wl_listener *listener, void *data)
layer_surface->pending.margin.top, layer_surface->pending.margin.right, layer_surface->pending.margin.top, layer_surface->pending.margin.right,
layer_surface->pending.margin.bottom, layer_surface->pending.margin.left); layer_surface->pending.margin.bottom, layer_surface->pending.margin.left);
/*
if (layer_surface->output) { if (layer_surface->output) {
struct wlr_output *wlr_output = struct wlr_output *wlr_output =
wlr_output_layout_output_at(server->output_layout, seat->cursor->x, seat->cursor->y); wlr_output_layout_output_at(server->output_layout, seat->cursor->x, seat->cursor->y);
@ -60,6 +160,16 @@ handle_layer_shell_v1_surface_new(struct wl_listener *listener, void *data)
} }
} }
struct cg_output *output = layer_surface->output->data; struct cg_output *output = layer_surface->output->data;
*/
struct cg_output *output;
if (layer_surface->output) {
output = layer_surface->output->data;
} else {
struct wlr_output *wlr_output =
wlr_output_layout_output_at(server->output_layout, seat->cursor->x, seat->cursor->y);
layer_surface->output = wlr_output;
output = wlr_output->data;
}
enum zwlr_layer_shell_v1_layer layer_type = layer_surface->pending.layer; enum zwlr_layer_shell_v1_layer layer_type = layer_surface->pending.layer;
struct wlr_scene_tree *output_layer = cg_layer_get_scene(output, layer_type); struct wlr_scene_tree *output_layer = cg_layer_get_scene(output, layer_type);
@ -81,6 +191,7 @@ handle_layer_shell_v1_surface_new(struct wl_listener *listener, void *data)
cg_surface->layer_surface = scene->layer_surface; cg_surface->layer_surface = scene->layer_surface;
cg_surface->scene = scene; cg_surface->scene = scene;
cg_surface->tree = scene->tree; cg_surface->tree = scene->tree;
cg_surface->tree->node.data =cg_surface;
cg_surface->layer_surface->data = cg_surface; cg_surface->layer_surface->data = cg_surface;
cg_surface->output = output; cg_surface->output = output;
@ -92,5 +203,5 @@ handle_layer_shell_v1_surface_new(struct wl_listener *listener, void *data)
wl_signal_add(&layer_surface->surface->events.commit, &cg_surface->surface_commit); wl_signal_add(&layer_surface->surface->events.commit, &cg_surface->surface_commit);
cg_surface->output_destroy.notify = handle_output_destroy; cg_surface->output_destroy.notify = handle_output_destroy;
wl_signal_add(&output->events.disable, &surface->output_destroy); wl_signal_add(&layer_surface->surface->events.destroy, &cg_surface->output_destroy);
} }

View file

@ -18,6 +18,8 @@ struct cg_layer_surface {
struct wl_listener output_destroy; struct wl_listener output_destroy;
bool mapped;
struct cg_output *output; struct cg_output *output;
struct wlr_scene_tree *tree; struct wlr_scene_tree *tree;
struct wlr_scene_layer_surface_v1 *scene; struct wlr_scene_layer_surface_v1 *scene;

3
seat.h
View file

@ -5,6 +5,7 @@
#include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_device.h> #include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_input_device.h> #include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_seat.h> #include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_xcursor_manager.h>
@ -48,6 +49,8 @@ struct cg_seat {
struct wl_listener request_set_cursor; struct wl_listener request_set_cursor;
struct wl_listener request_set_selection; struct wl_listener request_set_selection;
struct wl_listener request_set_primary_selection; struct wl_listener request_set_primary_selection;
struct wlr_layer_surface_v1 *focused_layer;
}; };
struct cg_keyboard_group { struct cg_keyboard_group {