feat: add support layershell protocol

This commit is contained in:
DanyLE
2024-03-31 16:09:01 +02:00
parent c1960f0438
commit 55719d6dba
15 changed files with 1404 additions and 534 deletions

117
output.c
View File

@ -1,11 +1,13 @@
#define _POSIX_C_SOURCE 200112L
#include <time.h>
#include <stdlib.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_output_layout.h>
#include <stdbool.h>
#include "output.h"
static void output_frame(struct wl_listener *listener, void *data) {
#include "layer.h"
#include "node.h"
#include "desktop.h"
static void output_frame(struct wl_listener *listener, void *data)
{
/* This function is called every time an output is ready to display a frame,
* generally at the output's refresh rate (e.g. 60Hz). */
struct diyac_output *output = wl_container_of(listener, output, frame);
@ -22,7 +24,8 @@ static void output_frame(struct wl_listener *listener, void *data) {
wlr_scene_output_send_frame_done(scene_output, &now);
}
static void output_request_state(struct wl_listener *listener, void *data) {
static void output_request_state(struct wl_listener *listener, void *data)
{
/* This function is called when the backend requests a new state for
* the output. For example, Wayland and X11 backends request a new mode
* when the output window is resized. */
@ -31,7 +34,8 @@ static void output_request_state(struct wl_listener *listener, void *data) {
wlr_output_commit_state(output->wlr_output, event->state);
}
static void output_destroy(struct wl_listener *listener, void *data) {
static void output_destroy(struct wl_listener *listener, void *data)
{
struct diyac_output *output = wl_container_of(listener, output, destroy);
wl_list_remove(&output->frame.link);
@ -41,7 +45,8 @@ static void output_destroy(struct wl_listener *listener, void *data) {
free(output);
}
void diyac_server_new_output(struct wl_listener *listener, void *data) {
void diyac_server_new_output(struct wl_listener *listener, void *data)
{
/* This event is raised by the backend when a new output (aka a display or
* monitor) becomes available. */
struct diyac_server *server =
@ -63,7 +68,8 @@ void diyac_server_new_output(struct wl_listener *listener, void *data) {
* just pick the monitor's preferred mode, a more sophisticated compositor
* would let the user configure it. */
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
if (mode != NULL) {
if (mode != NULL)
{
wlr_output_state_set_mode(&state, mode);
}
@ -75,7 +81,11 @@ void diyac_server_new_output(struct wl_listener *listener, void *data) {
struct diyac_output *output = calloc(1, sizeof(*output));
output->wlr_output = wlr_output;
output->server = server;
wlr_output->data = output;
output->usable_area.x = 0;
output->usable_area.y = 0;
output->usable_area.width = wlr_output->width;
output->usable_area.height = wlr_output->height;
/* Sets up a listener for the frame event. */
output->frame.notify = output_frame;
wl_signal_add(&wlr_output->events.frame, &output->frame);
@ -90,6 +100,46 @@ void diyac_server_new_output(struct wl_listener *listener, void *data) {
wl_list_insert(&server->outputs, &output->link);
/*
* Create layer-trees (background, bottom, top and overlay) and
* a layer-popup-tree.
*/
output->scenes.background = wlr_scene_tree_create(&server->scene->tree);
output->scenes.bottom = wlr_scene_tree_create(&server->scene->tree);
output->scenes.top = wlr_scene_tree_create(&server->scene->tree);
output->scenes.popup = wlr_scene_tree_create(&server->scene->tree);
output->scenes.overlay = wlr_scene_tree_create(&server->scene->tree);
output->scenes.session = wlr_scene_tree_create(&server->scene->tree);
diyac_node_descriptor_create(&output->scenes.background->node, DIYAC_NODE_TREE, NULL);
diyac_node_descriptor_create(&output->scenes.bottom->node, DIYAC_NODE_TREE, NULL);
diyac_node_descriptor_create(&output->scenes.top->node, DIYAC_NODE_TREE, NULL);
diyac_node_descriptor_create(&output->scenes.popup->node, DIYAC_NODE_TREE, NULL);
diyac_node_descriptor_create(&output->scenes.overlay->node, DIYAC_NODE_TREE, NULL);
diyac_node_descriptor_create(&output->scenes.session->node, DIYAC_NODE_TREE, NULL);
output->layer_tree[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND] = output->scenes.background;
output->layer_tree[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM] = output->scenes.bottom;
output->layer_tree[ZWLR_LAYER_SHELL_V1_LAYER_TOP] = output->scenes.top;
output->layer_tree[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY] = output->scenes.overlay;
/*
* Set the z-positions to achieve the following order (from top to
* bottom):
* - session lock layer
* - layer-shell popups
* - overlay layer
* - top layer
* - views
* - bottom layer
* - background layer
*/
wlr_scene_node_lower_to_bottom(&output->scenes.bottom->node);
wlr_scene_node_lower_to_bottom(&output->scenes.background->node);
wlr_scene_node_raise_to_top(&output->scenes.top->node);
wlr_scene_node_raise_to_top(&output->scenes.overlay->node);
wlr_scene_node_raise_to_top(&output->scenes.popup->node);
wlr_scene_node_raise_to_top(&output->scenes.session->node);
/* Adds this to the output layout. The add_auto function arranges outputs
* from left-to-right in the order they appear. A more sophisticated
* compositor would let the user configure the arrangement of outputs in the
@ -100,7 +150,54 @@ void diyac_server_new_output(struct wl_listener *listener, void *data) {
* output (such as DPI, scale factor, manufacturer, etc).
*/
struct wlr_output_layout_output *l_output = wlr_output_layout_add_auto(server->output_layout,
wlr_output);
wlr_output);
struct wlr_scene_output *scene_output = wlr_scene_output_create(server->scene, wlr_output);
wlr_scene_output_layout_add_output(server->scene_layout, l_output, scene_output);
}
/* returns true if usable area changed */
static bool update_usable_area(struct diyac_output *output)
{
struct wlr_box old = output->usable_area;
diyac_layers_arrange(output);
return !wlr_box_equal(&old, &output->usable_area);
}
void diyac_output_update_usable_area(struct diyac_output *output)
{
if (update_usable_area(output))
{
// regions_update_geometry(output);
diyac_arrange_all_views(output->server);
// desktop_arrange_all_views(output->server);
}
}
struct diyac_output *diyac_output_from_cursor(struct diyac_server *server)
{
double closest_x, closest_y;
wlr_output_layout_closest_point(server->output_layout, NULL, server->seat.cursor->x, server->seat.cursor->y,
&closest_x, &closest_y);
struct wlr_output *output = wlr_output_layout_output_at(server->output_layout,
closest_x, closest_y);
if (!output)
return NULL;
return output->data;
}
struct wlr_box diyac_output_usable_area(struct diyac_output *output)
{
if (!output)
{
return (struct wlr_box){0};
}
struct wlr_box box = output->usable_area;
double ox = 0, oy = 0;
wlr_output_layout_output_coords(output->server->output_layout,
output->wlr_output, &ox, &oy);
box.x -= ox;
box.y -= oy;
return box;
}