feat: add support layershell protocol
This commit is contained in:
117
output.c
117
output.c
@ -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;
|
||||
}
|
Reference in New Issue
Block a user