This commit is contained in:
2026-05-22 19:32:18 +07:00
parent 58ac1fb881
commit d34faf3469
16 changed files with 111 additions and 42 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ BasedOnStyle: LLVM
IndentWidth: 4 IndentWidth: 4
TabWidth: 4 TabWidth: 4
UseTab: Never UseTab: Never
ColumnLimit: 200 ColumnLimit: 120
AllowShortFunctionsOnASingleLine: false AllowShortFunctionsOnASingleLine: false
SortIncludes: true SortIncludes: true
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
+2 -1
View File
@@ -1,6 +1,7 @@
#include "types.h" #include "types.h"
void client_from_coords(absn_server *server, double x, double y, struct wlr_surface **rsurface, absn_toplevel **rtoplevel, absn_layer_surface **rlayer_surface, double *rx, double *ry); void client_from_coords(absn_server *server, double x, double y, struct wlr_surface **rsurface,
absn_toplevel **rtoplevel, absn_layer_surface **rlayer_surface, double *rx, double *ry);
void reset_cursor_mode(absn_server *server); void reset_cursor_mode(absn_server *server);
void process_cursor_motion(absn_server *server, uint32_t time); void process_cursor_motion(absn_server *server, uint32_t time);
+1
View File
@@ -4,6 +4,7 @@
#include "types.h" #include "types.h"
bool toplevel_is_unmanaged(absn_toplevel *toplevel); bool toplevel_is_unmanaged(absn_toplevel *toplevel);
bool toplevel_wants_focus(absn_toplevel *toplevel);
void toplevel_get_geom(absn_toplevel *toplevel); void toplevel_get_geom(absn_toplevel *toplevel);
+7 -5
View File
@@ -28,10 +28,10 @@
#define MAX(A, B) (A) > (B) ? (A) : (B) #define MAX(A, B) (A) > (B) ? (A) : (B)
#define MIN(A, B) (A) < (B) ? (A) : (B) #define MIN(A, B) (A) < (B) ? (A) : (B)
/* macro for adding listener for event */ /* macro for adding listener for event */
#define LISTEN(L, C, E) \ #define LISTEN(L, C, E) \
do { \ do { \
(L).notify = (C); \ (L).notify = (C); \
wl_signal_add(&(E), &(L)); \ wl_signal_add(&(E), &(L)); \
} while (0); } while (0);
#define UNUSED(X) (void)(X) #define UNUSED(X) (void)(X)
#define CLEANMASK(M) (M & ~WLR_MODIFIER_CAPS) #define CLEANMASK(M) (M & ~WLR_MODIFIER_CAPS)
@@ -51,7 +51,7 @@ enum {
BOTTOM_RIGHT, BOTTOM_RIGHT,
}; };
/* toplevel types */ /* client types */
enum { enum {
TOPLEVEL_XDG, TOPLEVEL_XDG,
TOPLEVEL_X11, TOPLEVEL_X11,
@@ -218,6 +218,8 @@ struct absn_toplevel {
struct wlr_scene_rect *border[4]; struct wlr_scene_rect *border[4];
struct wlr_xdg_toplevel_decoration_v1 *deco; struct wlr_xdg_toplevel_decoration_v1 *deco;
bool can_be_tiled;
bool floating; bool floating;
bool fullscreen; bool fullscreen;
bool urgent; bool urgent;
+4 -2
View File
@@ -50,7 +50,8 @@ static int setup(absn_server *server)
server->scene = wlr_scene_create(); server->scene = wlr_scene_create();
if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF)) { if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF)) {
wlr_drm_create(server->display, server->renderer); wlr_drm_create(server->display, server->renderer);
wlr_scene_set_linux_dmabuf_v1(server->scene, wlr_linux_dmabuf_v1_create_with_renderer(server->display, 5, server->renderer)); wlr_scene_set_linux_dmabuf_v1(server->scene,
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->bg = wlr_scene_rect_create(&server->scene->tree, 0, 0, bgcolor);
@@ -74,7 +75,8 @@ static int setup(absn_server *server)
wlr_export_dmabuf_manager_v1_create(server->display); wlr_export_dmabuf_manager_v1_create(server->display);
wlr_ext_foreign_toplevel_list_v1_create(server->display, 1); wlr_ext_foreign_toplevel_list_v1_create(server->display, 1);
wlr_server_decoration_manager_set_default_mode(wlr_server_decoration_manager_create(server->display), WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); wlr_server_decoration_manager_set_default_mode(wlr_server_decoration_manager_create(server->display),
WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
server->xdg_deco_mgr = wlr_xdg_decoration_manager_v1_create(server->display); server->xdg_deco_mgr = wlr_xdg_decoration_manager_v1_create(server->display);
LISTEN(server->new_xdg_deco, new_xdg_decoration, server->xdg_deco_mgr->events.new_toplevel_decoration); LISTEN(server->new_xdg_deco, new_xdg_decoration, server->xdg_deco_mgr->events.new_toplevel_decoration);
+2 -1
View File
@@ -9,7 +9,8 @@
* returns surface at given cursor coordinates * returns surface at given cursor coordinates
* and coordinates inside of it to process input event * and coordinates inside of it to process input event
*/ */
void client_from_coords(absn_server *server, double x, double y, struct wlr_surface **rsurface, absn_toplevel **rtoplevel, absn_layer_surface **rlayer_surface, double *rx, double *ry) void client_from_coords(absn_server *server, double x, double y, struct wlr_surface **rsurface,
absn_toplevel **rtoplevel, absn_layer_surface **rlayer_surface, double *rx, double *ry)
{ {
struct wlr_scene_node *pnode = NULL, *node = NULL; struct wlr_scene_node *pnode = NULL, *node = NULL;
struct wlr_scene_buffer *buffer = NULL; struct wlr_scene_buffer *buffer = NULL;
+1 -1
View File
@@ -1,5 +1,5 @@
#include <stdnoreturn.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdnoreturn.h>
#include <unistd.h> #include <unistd.h>
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
+2 -1
View File
@@ -21,7 +21,8 @@ static bool handle_keybind(absn_server *server, uint32_t mods, xkb_keysym_t keys
{ {
int nkeyb = sizeof(keybinds) / sizeof(keybinds[0]); int nkeyb = sizeof(keybinds) / sizeof(keybinds[0]);
for (int i = 0; i < nkeyb; ++i) { for (int i = 0; i < nkeyb; ++i) {
if (CLEANMASK(keybinds[i].mods) == CLEANMASK(mods) && xkb_keysym_to_lower(keybinds[i].keysym) == xkb_keysym_to_lower(keysym)) { if (CLEANMASK(keybinds[i].mods) == CLEANMASK(mods) &&
xkb_keysym_to_lower(keybinds[i].keysym) == xkb_keysym_to_lower(keysym)) {
keybinds[i].cb(server, &keybinds[i].arg); keybinds[i].cb(server, &keybinds[i].arg);
return true; return true;
} }
+2 -1
View File
@@ -1,5 +1,5 @@
#include <wlr/types/wlr_layer_shell_v1.h>
#include <stdlib.h> #include <stdlib.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include "focus.h" #include "focus.h"
#include "layers.h" #include "layers.h"
@@ -54,6 +54,7 @@ void layer_surface_commit(struct wl_listener *listener, void *data)
} }
layers_arrange(layer_surface->output); layers_arrange(layer_surface->output);
wlr_surface_send_enter(surface->surface, surface->output);
} }
void layer_surface_new_popup(struct wl_listener *listener, void *data) void layer_surface_new_popup(struct wl_listener *listener, void *data)
+4 -2
View File
@@ -19,7 +19,8 @@ static void layer_arrange(absn_output *output, struct wl_list *list, struct wlr_
} }
wlr_scene_layer_surface_v1_configure(layer_surface->scene_layer, &output->geom, usable_area); wlr_scene_layer_surface_v1_configure(layer_surface->scene_layer, &output->geom, usable_area);
wlr_scene_node_set_position(&layer_surface->popups->node, layer_surface->scene_tree->node.x, layer_surface->scene_tree->node.y); wlr_scene_node_set_position(&layer_surface->popups->node, layer_surface->scene_tree->node.x,
layer_surface->scene_tree->node.y);
} }
} }
@@ -64,7 +65,8 @@ void layers_arrange(absn_output *output)
output->server->exclusive_focus = layer_surface; output->server->exclusive_focus = layer_surface;
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(output->server->seat); struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(output->server->seat);
if (keyboard) { if (keyboard) {
wlr_seat_keyboard_notify_enter(output->server->seat, layer_surface->wlr->surface, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); wlr_seat_keyboard_notify_enter(output->server->seat, layer_surface->wlr->surface, keyboard->keycodes,
keyboard->num_keycodes, &keyboard->modifiers);
} }
return; return;
} }
+8 -4
View File
@@ -44,7 +44,8 @@ static void tile(struct absn_output *output)
break; break;
} }
} }
new_geom.x = output->usable_area.x + og, new_geom.y = output->usable_area.y + og, new_geom.width = output->usable_area.width - 2 * og, new_geom.height = output->usable_area.height - 2 * og, new_geom.x = output->usable_area.x + og, new_geom.y = output->usable_area.y + og,
new_geom.width = output->usable_area.width - 2 * og, new_geom.height = output->usable_area.height - 2 * og,
toplevel_set_geom(toplevel, &new_geom); toplevel_set_geom(toplevel, &new_geom);
return; return;
@@ -56,7 +57,8 @@ static void tile(struct absn_output *output)
int mcount = output->workspace->count; int mcount = output->workspace->count;
float msize = output->workspace->size; float msize = output->workspace->size;
int32_t main_stack_width = (toplevels_count <= mcount) ? output->usable_area.width - 2 * og : msize * (output->usable_area.width - 2 * og); int32_t main_stack_width =
(toplevels_count <= mcount) ? output->usable_area.width - 2 * og : msize * (output->usable_area.width - 2 * og);
int32_t w = output->usable_area.width - main_stack_width - 2 * og - lg; int32_t w = output->usable_area.width - main_stack_width - 2 * og - lg;
int32_t pure_h; int32_t pure_h;
@@ -163,7 +165,8 @@ static void tile_left(struct absn_output *output)
break; break;
} }
} }
new_geom.x = output->usable_area.x + og, new_geom.y = output->usable_area.y + og, new_geom.width = output->usable_area.width - 2 * og, new_geom.height = output->usable_area.height - 2 * og, new_geom.x = output->usable_area.x + og, new_geom.y = output->usable_area.y + og,
new_geom.width = output->usable_area.width - 2 * og, new_geom.height = output->usable_area.height - 2 * og,
toplevel_set_geom(toplevel, &new_geom); toplevel_set_geom(toplevel, &new_geom);
return; return;
@@ -175,7 +178,8 @@ static void tile_left(struct absn_output *output)
int mcount = output->workspace->count; int mcount = output->workspace->count;
float msize = output->workspace->size; float msize = output->workspace->size;
int32_t main_stack_width = (toplevels_count <= mcount) ? output->usable_area.width - 2 * og : msize * (output->usable_area.width - 2 * og); int32_t main_stack_width =
(toplevels_count <= mcount) ? output->usable_area.width - 2 * og : msize * (output->usable_area.width - 2 * og);
int32_t w = output->usable_area.width - main_stack_width - 2 * og - lg; int32_t w = output->usable_area.width - main_stack_width - 2 * og - lg;
int32_t pure_h; int32_t pure_h;
+2 -1
View File
@@ -17,12 +17,13 @@ void output_frame(struct wl_listener *listener, void *data)
absn_toplevel *toplevel; absn_toplevel *toplevel;
wl_list_for_each(toplevel, &output->server->toplevels, link) wl_list_for_each(toplevel, &output->server->toplevels, link)
{ {
if (toplevel->resizing && toplevel->output == output) { if (toplevel->resizing && !toplevel->floating && toplevel->output == output) {
goto skip; goto skip;
} }
} }
wlr_scene_output_commit(scene_output, NULL); wlr_scene_output_commit(scene_output, NULL);
skip: skip:
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_output_send_frame_done(scene_output, &now); wlr_scene_output_send_frame_done(scene_output, &now);
+4 -2
View File
@@ -156,7 +156,8 @@ void new_layer_surface(struct wl_listener *listener, void *data)
struct wlr_scene_tree *scene_layer = server->layers[layermap[surface->pending.layer]]; 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_layer = wlr_scene_layer_surface_v1_create(scene_layer, surface);
layer_surface->scene_tree = layer_surface->scene_layer->tree; layer_surface->scene_tree = layer_surface->scene_layer->tree;
layer_surface->popups = wlr_scene_tree_create(surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? server->layers[LAYER_TOP] : scene_layer); layer_surface->popups = wlr_scene_tree_create(
surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? server->layers[LAYER_TOP] : scene_layer);
wl_list_insert(&layer_surface->output->layers[surface->pending.layer], &layer_surface->link); wl_list_insert(&layer_surface->output->layers[surface->pending.layer], &layer_surface->link);
wlr_surface_send_enter(surface->surface, surface->output); wlr_surface_send_enter(surface->surface, surface->output);
@@ -300,7 +301,8 @@ void cursor_axis(struct wl_listener *listener, void *data)
{ {
absn_server *server = wl_container_of(listener, server, cursor_axis); absn_server *server = wl_container_of(listener, server, cursor_axis);
struct wlr_pointer_axis_event *event = data; struct wlr_pointer_axis_event *event = data;
wlr_seat_pointer_notify_axis(server->seat, event->time_msec, event->orientation, event->delta, event->delta_discrete, event->source, event->relative_direction); wlr_seat_pointer_notify_axis(server->seat, event->time_msec, event->orientation, event->delta,
event->delta_discrete, event->source, event->relative_direction);
} }
void cursor_frame(struct wl_listener *listener, void *data) void cursor_frame(struct wl_listener *listener, void *data)
+42 -15
View File
@@ -17,10 +17,20 @@ void toplevel_map(struct wl_listener *listener, void *data)
toplevel->scene_tree->node.data = toplevel; toplevel->scene_tree->node.data = toplevel;
wlr_scene_node_set_enabled(&toplevel->scene_tree->node, toplevel_is_unmanaged(toplevel)); wlr_scene_node_set_enabled(&toplevel->scene_tree->node, toplevel_is_unmanaged(toplevel));
if (toplevel->type != TOPLEVEL_X11 && wl_resource_get_version(toplevel->xdg->resource) >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { update_focused_output(toplevel->server);
toplevel->output = toplevel->server->focused_output;
toplevel->workspace = toplevel->output->workspace;
toplevel->fullscreen = false;
#ifdef XWAYLAND
if (toplevel->type == TOPLEVEL_X11) {
toplevel->xw->surface->data = toplevel;
}
#endif
if (toplevel->type != TOPLEVEL_X11 &&
wl_resource_get_version(toplevel->xdg->resource) >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
wlr_xdg_toplevel_set_tiled(toplevel->xdg, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); wlr_xdg_toplevel_set_tiled(toplevel->xdg, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
} else {
wlr_xdg_toplevel_set_maximized(toplevel->xdg, true);
} }
#ifdef XWAYLAND #ifdef XWAYLAND
@@ -36,27 +46,42 @@ void toplevel_map(struct wl_listener *listener, void *data)
toplevel_get_geom(toplevel); toplevel_get_geom(toplevel);
toplevel->bw = toplevel_is_unmanaged(toplevel) ? 0 : TOPLEVEL_BW; toplevel->bw = toplevel_is_unmanaged(toplevel) ? 0 : TOPLEVEL_BW;
#ifdef XWAYLAND if (toplevel_is_unmanaged(toplevel)) {
if (toplevel->type == TOPLEVEL_X11) { toplevel_set_floating(toplevel, true);
toplevel->xw->surface->data = toplevel; toplevel_set_size(toplevel, toplevel->geom.width, toplevel->geom.height);
if (toplevel_wants_focus(toplevel)) {
focus_toplevel(toplevel);
server->exclusive_focus = toplevel;
}
goto unset_fullscreen;
} }
#endif
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
toplevel->border[i] = wlr_scene_rect_create(toplevel->scene_tree, 0, 0, unfocused_bc); toplevel->border[i] = wlr_scene_rect_create(toplevel->scene_tree, 0, 0, unfocused_bc);
toplevel->border[i]->node.data = toplevel; toplevel->border[i]->node.data = toplevel;
} }
update_focused_output(toplevel->server);
toplevel->output = toplevel->server->focused_output;
toplevel->workspace = toplevel->output->workspace;
toplevel->fullscreen = false;
wl_list_insert(&toplevel->server->toplevels, &toplevel->link); wl_list_insert(&toplevel->server->toplevels, &toplevel->link);
wl_list_insert(&toplevel->server->focus_stack, &toplevel->flink); wl_list_insert(&toplevel->server->focus_stack, &toplevel->flink);
layout_arrange(toplevel->output);
focus_toplevel(focus_get_topmost(toplevel->server)); focus_toplevel(focus_get_topmost(toplevel->server));
if (toplevel->type == TOPLEVEL_XDG && toplevel->xdg->parent) {
toplevel->floating = 1;
} else if (toplevel->type == TOPLEVEL_X11 && toplevel->xw->parent) {
toplevel->floating = 1;
}
unset_fullscreen:
absn_toplevel *t;
wl_list_for_each(t, &server->toplevels, link)
{
if (t->workspace == toplevel->workspace && t->fullscreen) {
toplevel_set_fullscreen(t, false);
}
}
layout_arrange(toplevel->output);
} }
void toplevel_unmap(struct wl_listener *listener, void *data) void toplevel_unmap(struct wl_listener *listener, void *data)
@@ -73,8 +98,10 @@ void toplevel_unmap(struct wl_listener *listener, void *data)
toplevel->server->exclusive_focus = NULL; toplevel->server->exclusive_focus = NULL;
} }
wl_list_remove(&toplevel->link); if (!toplevel_is_unmanaged(toplevel)) {
wl_list_remove(&toplevel->flink); wl_list_remove(&toplevel->link);
wl_list_remove(&toplevel->flink);
}
layout_arrange(toplevel->output); layout_arrange(toplevel->output);
focus_toplevel(focus_get_topmost(toplevel->server)); focus_toplevel(focus_get_topmost(toplevel->server));
+18 -4
View File
@@ -22,6 +22,14 @@ bool toplevel_is_unmanaged(absn_toplevel *toplevel)
return false; return false;
} }
bool toplevel_wants_focus(absn_toplevel *toplevel)
{
#ifdef XWAYLAND
return toplevel_is_unmanaged(toplevel) && wlr_xwayland_surface_override_redirect_wants_focus(toplevel->xw) &&
wlr_xwayland_surface_icccm_input_model(toplevel->xw) != WLR_ICCCM_INPUT_MODEL_NONE;
#endif
}
/* used only to get initial window size */ /* used only to get initial window size */
void toplevel_get_geom(absn_toplevel *toplevel) void toplevel_get_geom(absn_toplevel *toplevel)
{ {
@@ -69,7 +77,8 @@ void toplevel_set_pos(absn_toplevel *toplevel, int32_t x, int32_t y)
void toplevel_set_size(absn_toplevel *toplevel, int32_t width, int32_t height) void toplevel_set_size(absn_toplevel *toplevel, int32_t width, int32_t height)
{ {
if (width <= 2 * toplevel->bw || height <= 2 * toplevel->bw || (width == toplevel->geom.width && height == toplevel->geom.height)) { if (width <= 2 * toplevel->bw || height <= 2 * toplevel->bw ||
(width == toplevel->geom.width && height == toplevel->geom.height)) {
return; return;
} }
toplevel->geom.width = width; toplevel->geom.width = width;
@@ -94,13 +103,14 @@ void toplevel_set_size(absn_toplevel *toplevel, int32_t width, int32_t height)
} }
#ifdef XWAYLAND #ifdef XWAYLAND
else if (toplevel->type == TOPLEVEL_X11) { else if (toplevel->type == TOPLEVEL_X11) {
wlr_xwayland_surface_configure(toplevel->xw, toplevel->geom.x, toplevel->geom.y, width - 2 * bw, height - 2 * toplevel->bw); wlr_xwayland_surface_configure(toplevel->xw, toplevel->geom.x, toplevel->geom.y, width - 2 * bw,
height - 2 * toplevel->bw);
/* manually update position */ /* manually update position */
toplevel_set_pos(toplevel, toplevel->geom.x, toplevel->geom.y); toplevel_set_pos(toplevel, toplevel->geom.x, toplevel->geom.y);
} else }
#endif #endif
wlr_scene_subsurface_tree_set_clip(&toplevel->scene_surface->node, &clip); wlr_scene_subsurface_tree_set_clip(&toplevel->scene_surface->node, &clip);
} }
void toplevel_set_geom(absn_toplevel *toplevel, struct wlr_box *geom) void toplevel_set_geom(absn_toplevel *toplevel, struct wlr_box *geom)
@@ -115,6 +125,10 @@ void toplevel_set_floating(absn_toplevel *toplevel, bool floating)
return; return;
} }
if (floating && !toplevel->can_be_tiled) {
return;
}
toplevel->floating = floating; toplevel->floating = floating;
if (floating) { if (floating) {
+11 -1
View File
@@ -1,5 +1,6 @@
#ifdef XWAYLAND #ifdef XWAYLAND
#include "config.h"
#include "xwayland.h" #include "xwayland.h"
#include "toplevel-handlers.h" #include "toplevel-handlers.h"
#include "toplevel.h" #include "toplevel.h"
@@ -53,7 +54,16 @@ void xwayland_configure(struct wl_listener *listener, void *data)
void xwayland_set_hints(struct wl_listener *listener, void *data) void xwayland_set_hints(struct wl_listener *listener, void *data)
{ {
UNUSED(listener);
UNUSED(data); UNUSED(data);
absn_toplevel *toplevel = wl_container_of(listener, toplevel, xw_set_hints);
if (toplevel == toplevel->server->focused_toplevel || !toplevel->xw->hints) {
return;
}
toplevel->urgent = xcb_icccm_wm_hints_get_urgency(toplevel->xw->hints);
struct wlr_surface *surface = toplevel->xw->surface;
if (toplevel->urgent && surface && surface->mapped) {
toplevel_set_border_color(toplevel, urgent_bc);
}
} }
#endif #endif