layers, tags and make

This commit is contained in:
2026-05-10 20:06:05 +07:00
parent 450234522d
commit afbd0c109c
17 changed files with 263 additions and 73 deletions
+13 -4
View File
@@ -6,6 +6,7 @@
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
#include <wlr/types/wlr_fractional_scale_v1.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output_management_v1.h>
#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_screencopy_v1.h>
@@ -17,6 +18,7 @@
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/util/log.h>
#include "config.h"
#include "output.h"
#include "seat.h"
#include "server.h"
@@ -56,6 +58,7 @@ setup(absn_server *server)
wlr_linux_dmabuf_v1_create_with_renderer(server->display, 5,
server->renderer));
}
server->bg = wlr_scene_rect_create(&server->scene->tree, 0, 0, bgcolor);
server->allocator = wlr_allocator_autocreate(server->backend,
server->renderer);
@@ -87,6 +90,10 @@ setup(absn_server *server)
LISTEN(server->new_xdg_deco, new_xdg_decoration,
server->xdg_deco_mgr->events.new_toplevel_decoration);
/* toplevels lists */
wl_list_init(&server->toplevels);
wl_list_init(&server->focus_stack);
/* output */
wl_list_init(&server->outputs);
LISTEN(server->new_output, new_output,
@@ -104,10 +111,6 @@ setup(absn_server *server)
server->scene_layout = wlr_scene_attach_output_layout(server->scene,
server->output_layout);
/* toplevels lists */
wl_list_init(&server->toplevels);
wl_list_init(&server->focus_stack);
/* xdg_shell */
server->xdg_shell = wlr_xdg_shell_create(server->display, 6);
LISTEN(server->new_xdg_toplevel, new_xdg_toplevel,
@@ -143,6 +146,10 @@ setup(absn_server *server)
LISTEN(server->request_set_selection, request_cursor,
server->seat->events.request_set_selection);
server->layer_shell = wlr_layer_shell_v1_create(server->display, 1);
for (int i = 0; i < LAYERS_COUNT; ++i)
server->layers[i] = wlr_scene_tree_create(&server->scene->tree);
unsetenv("DISPLAY");
#ifdef XWAYLAND
if ((server->xwayland = wlr_xwayland_create(server->display,
@@ -203,6 +210,8 @@ cleanup(absn_server *server)
wl_list_remove(&server->new_output.link);
wl_list_remove(&server->new_layer_surface.link);
wlr_scene_node_destroy(&server->scene->tree.node);
wlr_xcursor_manager_destroy(server->cursor_mgr);
wlr_cursor_destroy(server->cursor);
+4 -8
View File
@@ -34,10 +34,8 @@ process_cursor_move(absn_server *server)
new_y = server->cursor->y - server->grab_y + server->grab_geom.y;
toplevel_set_pos(toplevel, new_x, new_y);
if (toplevel->tiled) {
toplevel->tiled = false;
layout_arrange(toplevel->output);
}
if (!toplevel->floating)
toplevel_set_floating(toplevel, true);
}
static void
@@ -86,10 +84,8 @@ process_cursor_resize(absn_server *server)
if (toplevel->fullscreen)
toplevel_set_fullscreen(toplevel, false);
if (toplevel->tiled) {
toplevel->tiled = false;
layout_arrange(toplevel->output);
}
if (!toplevel->floating)
toplevel_set_floating(toplevel, true);
int32_t new_x, new_y, new_width, new_height;
new_x = server->grab_geom.x;
+20 -13
View File
@@ -25,13 +25,15 @@ kill_focus(absn_server *server, const absn_arg *arg)
if (!server->focused_output)
return;
absn_toplevel *focus = server->focused_toplevel;
#ifdef XWAYLAND
if (server->focused_toplevel->type == TOPLEVEL_X11) {
wlr_xwayland_surface_close(server->focused_toplevel->xw);
if (focus->type == TOPLEVEL_X11) {
wlr_xwayland_surface_close(focus->xw);
} else
#endif
{
wlr_xdg_toplevel_send_close(server->focused_toplevel->xdg);
wlr_xdg_toplevel_send_close(focus->xdg);
}
}
@@ -39,7 +41,7 @@ void
cycle_focus(absn_server *server, const absn_arg *arg)
{
absn_toplevel *toplevel = focus_get_topmost(server);
if (!toplevel)
if (!toplevel || toplevel->fullscreen)
return;
absn_toplevel *new_focus;
@@ -67,8 +69,9 @@ toggle_fullscreen(absn_server *server, const absn_arg *arg)
UNUSED(arg);
if (!server->focused_toplevel)
return;
toplevel_set_fullscreen(server->focused_toplevel,
!server->focused_toplevel->fullscreen);
absn_toplevel *focus = server->focused_toplevel;
toplevel_set_fullscreen(focus, !focus->fullscreen);
}
void
@@ -77,12 +80,14 @@ increase_master_width(absn_server *server, const absn_arg *arg)
if (!server->focused_output)
return;
if (server->focused_output->mstack_width + arg->f >= 1.0 ||
server->focused_output->mstack_width + arg->f <= 0.0)
absn_output *focus = server->focused_output;
if (focus->mstack_width + arg->f >= 1.0 ||
focus->mstack_width + arg->f <= 0.0)
return;
server->focused_output->mstack_width += arg->f;
layout_arrange(server->focused_output);
focus->mstack_width += arg->f;
layout_arrange(focus);
}
void
@@ -91,11 +96,13 @@ increase_master_count(absn_server *server, const absn_arg *arg)
if (!server->focused_output)
return;
if (server->focused_output->mstack_count + arg->i <= 0)
absn_output *focus = server->focused_output;
if (focus->mstack_count + arg->i <= 0)
return;
server->focused_output->mstack_count += arg->i;
layout_arrange(server->focused_output);
focus->mstack_count += arg->i;
layout_arrange(focus);
}
noreturn void
+19 -1
View File
@@ -22,8 +22,26 @@ layer_surface_commit(struct wl_listener *listener, void *data)
}
void
layer_surface_destroy(struct wl_listener *listener, void *data)
layer_surface_new_popup(struct wl_listener *listener, void *data)
{
UNUSED(listener);
UNUSED(data);
}
void
layer_surface_destroy(struct wl_listener *listener, void *data)
{
UNUSED(data);
absn_layer_surface *layer_surface = wl_container_of(listener,
layer_surface, destroy);
wl_list_remove(&layer_surface->link);
wl_list_remove(&layer_surface->map.link);
wl_list_remove(&layer_surface->unmap.link);
wl_list_remove(&layer_surface->commit.link);
wl_list_remove(&layer_surface->new_popup.link);
wl_list_remove(&layer_surface->destroy.link);
wlr_scene_node_destroy(&layer_surface->scene_tree->node);
free(layer_surface);
}
+40 -15
View File
@@ -12,7 +12,8 @@ layout_arrange(struct absn_output *output)
int toplevels_count = 0;
wl_list_for_each(toplevel, &output->server->toplevels, link)
{
if (toplevel->output == output && toplevel->tiled) {
if (toplevel->output == output && !toplevel->floating &&
!toplevel->fullscreen) {
toplevels_count++;
wlr_scene_node_set_enabled(&toplevel->scene_tree->node,
true);
@@ -28,7 +29,8 @@ layout_arrange(struct absn_output *output)
if (toplevels_count == 1) {
wl_list_for_each(toplevel, &output->server->toplevels, link)
{
if (toplevel->output == output && toplevel->tiled)
if (toplevel->output == output && !toplevel->floating &&
!toplevel->fullscreen)
break;
}
new_geom.x = output->geom.x + og,
@@ -41,31 +43,43 @@ layout_arrange(struct absn_output *output)
}
int32_t lg = LAYOUT_GAP;
int32_t total_lg;
int32_t main_stack_width = (toplevels_count <= output->mstack_count) ?
output->geom.width - 2 * og :
output->mstack_width * (output->geom.width - 2 * og);
int32_t w = output->geom.width - main_stack_width - 2 * og - lg;
int32_t pure_h;
int32_t h;
int32_t cur_h;
int32_t r;
int32_t dy = og;
int i = 0;
if (toplevels_count <= output->mstack_count) {
total_lg = (toplevels_count - 1) * lg;
pure_h = output->geom.height - 2 * og - total_lg;
h = pure_h / toplevels_count;
r = pure_h % toplevels_count;
wl_list_for_each(toplevel, &output->server->toplevels, link)
{
if (toplevel->output != output || !toplevel->tiled)
if (toplevel->output != output || toplevel->floating ||
toplevel->fullscreen)
continue;
h = (output->geom.height - dy - og) /
(toplevels_count - i);
cur_h = h + (i < r ? 1 : 0);
new_geom.x = output->geom.x + og;
new_geom.y = output->geom.y + dy;
new_geom.width = main_stack_width;
new_geom.height = h;
new_geom.height = cur_h;
toplevel_set_geom(toplevel, &new_geom);
dy += h + lg;
dy += cur_h + lg;
i++;
}
@@ -74,27 +88,38 @@ layout_arrange(struct absn_output *output)
wl_list_for_each(toplevel, &output->server->toplevels, link)
{
if (toplevel->output != output || !toplevel->tiled)
if (toplevel->output != output || toplevel->floating ||
toplevel->fullscreen)
continue;
if (i < output->mstack_count) {
h = (output->geom.height - dy - og) /
(output->mstack_count - i);
total_lg = (output->mstack_count - 1) * lg;
pure_h = output->geom.height - 2 * og - total_lg;
h = pure_h / output->mstack_count;
r = pure_h % output->mstack_count;
cur_h = h + (i < r ? 1 : 0);
new_geom.x = output->geom.x + og;
new_geom.y = output->geom.y + dy;
new_geom.width = main_stack_width;
new_geom.height = h;
new_geom.height = cur_h;
toplevel_set_geom(toplevel, &new_geom);
dy += h + lg;
dy += cur_h + lg;
} else {
if (i == output->mstack_count)
dy = og;
h = (output->geom.height - dy - og) /
(toplevels_count - i);
int32_t stack_count = toplevels_count -
output->mstack_count;
total_lg = (stack_count - 1) * lg;
pure_h = output->geom.height - 2 * og - total_lg;
h = pure_h / stack_count;
r = pure_h % stack_count;
cur_h = h + (i - output->mstack_count < r ? 1 : 0);
new_geom.x = output->geom.x + main_stack_width + lg +
og;
@@ -104,7 +129,7 @@ layout_arrange(struct absn_output *output)
toplevel_set_geom(toplevel, &new_geom);
dy += h + lg;
dy += cur_h + lg;
}
i++;
+9
View File
@@ -12,6 +12,7 @@ output_frame(struct wl_listener *listener, void *data)
UNUSED(data);
struct timespec now;
absn_output *output = wl_container_of(listener, output, frame);
struct wlr_scene *scene = output->server->scene;
struct wlr_scene_output *scene_output =
wlr_scene_get_scene_output(scene, output->wlr);
@@ -86,6 +87,14 @@ output_layout_change(struct wl_listener *listener, void *data)
toplevel->output->wlr);
}
struct wlr_box layout_geom;
wlr_output_layout_get_box(server->output_layout, NULL, &layout_geom);
wlr_scene_node_set_position(&server->bg->node, layout_geom.x,
layout_geom.y);
wlr_scene_rect_set_size(server->bg, layout_geom.width,
layout_geom.height);
wl_list_for_each(output, &server->outputs, link)
{
if (!output->wlr->enabled)
+32 -11
View File
@@ -53,6 +53,9 @@ new_output(struct wl_listener *listener, void *data)
wl_list_insert(&server->outputs, &output->link);
for (int i = 0; i < 4; ++i)
wl_list_init(&output->layers[i]);
struct wlr_output_layout_output *l_layout =
wlr_output_layout_add_auto(server->output_layout, output->wlr);
struct wlr_scene_output *scene_output =
@@ -142,21 +145,39 @@ new_layer_surface(struct wl_listener *listener, void *data)
{
absn_server *server = wl_container_of(listener, server,
new_layer_surface);
struct wlr_layer_surface_v1 *layer_surface = data;
struct wlr_layer_surface_v1 *surface = data;
if (!layer_surface->output &&
!(layer_surface->output = server->focused_output->wlr)) {
wlr_layer_surface_v1_destroy(layer_surface);
if (!surface->output &&
!(surface->output = server->focused_output->wlr)) {
wlr_layer_surface_v1_destroy(surface);
return;
}
absn_layer_surface *layer = calloc(1, sizeof(*layer));
LISTEN(layer->commit, layer_surface_commit,
layer_surface->surface->events.commit);
LISTEN(layer->unmap, layer_surface_unmap,
layer_surface->surface->events.unmap);
LISTEN(layer->destroy, layer_surface_destroy,
layer_surface->surface->events.destroy);
absn_layer_surface *layer_surface = calloc(1, sizeof(*layer_surface));
LISTEN(layer_surface->map, layer_surface_map,
surface->surface->events.map);
LISTEN(layer_surface->unmap, layer_surface_unmap,
surface->surface->events.unmap);
LISTEN(layer_surface->commit, layer_surface_commit,
surface->surface->events.commit);
LISTEN(layer_surface->new_popup, layer_surface_new_popup,
surface->events.new_popup);
LISTEN(layer_surface->destroy, layer_surface_destroy,
surface->surface->events.destroy);
layer_surface->wlr = surface;
layer_surface->output = surface->output->data;
struct wlr_scene_tree *scene_layer =
server->layers[layermap[surface->pending.layer]];
layer_surface->scene_layer =
wlr_scene_layer_surface_v1_create(scene_layer, surface);
layer_surface->scene_tree = layer_surface->scene_layer->tree;
wl_list_insert(&layer_surface->output->layers[surface->pending.layer],
&layer_surface->link);
wlr_surface_send_enter(surface->surface, surface->output);
}
#ifdef XWAYLAND
+2 -3
View File
@@ -12,15 +12,14 @@ toplevel_map(struct wl_listener *listener, void *data)
{
UNUSED(data);
absn_toplevel *toplevel = wl_container_of(listener, toplevel, map);
absn_server *server = toplevel->server;
toplevel->scene_tree = wlr_scene_tree_create(
&toplevel->server->scene->tree);
server->layers[LAYER_TILE]);
toplevel->scene_tree->node.data = toplevel;
wlr_scene_node_set_enabled(&toplevel->scene_tree->node,
toplevel_is_unmanaged(toplevel));
toplevel->tiled = true;
if (toplevel->type != TOPLEVEL_X11 &&
wl_resource_get_version(toplevel->xdg->resource) >=
XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
+28
View File
@@ -2,6 +2,7 @@
#include <wlr/util/log.h>
#include "config.h"
#include "layout.h"
#include "toplevel.h"
#include "types.h"
#include "xdg-shell-protocol.h"
@@ -162,6 +163,24 @@ toplevel_set_geom(absn_toplevel *toplevel, struct wlr_box *geom)
toplevel_set_size(toplevel, geom->width, geom->height);
}
void
toplevel_set_floating(absn_toplevel *toplevel, bool floating)
{
if (!toplevel || toplevel->floating == floating)
return;
toplevel->floating = floating;
if (floating)
wlr_scene_node_reparent(&toplevel->scene_tree->node,
toplevel->server->layers[LAYER_FLOAT]);
else
wlr_scene_node_reparent(&toplevel->scene_tree->node,
toplevel->server->layers[LAYER_TILE]);
layout_arrange(toplevel->output);
}
void
toplevel_set_fullscreen(absn_toplevel *toplevel, bool fullscreen)
{
@@ -176,10 +195,19 @@ toplevel_set_fullscreen(absn_toplevel *toplevel, bool fullscreen)
toplevel->prev_geom = toplevel->geom;
toplevel->bw = 0;
toplevel_set_geom(toplevel, &output->geom);
wlr_scene_node_reparent(&toplevel->scene_tree->node,
toplevel->server->layers[LAYER_FULLSCREEN]);
} else {
toplevel->bw = toplevel_is_unmanaged(toplevel) ? 0 :
TOPLEVEL_BW;
toplevel_set_geom(toplevel, &toplevel->prev_geom);
if (toplevel->floating)
wlr_scene_node_reparent(&toplevel->scene_tree->node,
toplevel->server->layers[LAYER_FLOAT]);
else
wlr_scene_node_reparent(&toplevel->scene_tree->node,
toplevel->server->layers[LAYER_TILE]);
}
toplevel_update_borders_geom(toplevel);