focus stack and next/prev toplevel keybinds

This commit is contained in:
2026-01-13 10:51:36 +07:00
parent 6ba17ad0b4
commit e7f194ed8d
7 changed files with 69 additions and 19 deletions
+2
View File
@@ -3,3 +3,5 @@
#include "types.h" #include "types.h"
void focus_toplevel(struct absinthe_toplevel *toplevel); void focus_toplevel(struct absinthe_toplevel *toplevel);
void focus_next(struct absinthe_server *server);
void focus_prev(struct absinthe_server *server);
+4 -1
View File
@@ -54,7 +54,6 @@ struct absinthe_server {
struct wlr_xdg_shell *xdg_shell; struct wlr_xdg_shell *xdg_shell;
struct wl_listener new_xdg_toplevel; struct wl_listener new_xdg_toplevel;
struct wl_listener new_xdg_popup; struct wl_listener new_xdg_popup;
struct wl_list toplevels;
struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr;
struct wl_listener new_xdg_decoration; struct wl_listener new_xdg_decoration;
@@ -78,6 +77,9 @@ struct absinthe_server {
uint32_t grab_x, grab_y; uint32_t grab_x, grab_y;
enum absinthe_cursor_resize_corner cursor_resize_corner; enum absinthe_cursor_resize_corner cursor_resize_corner;
struct wl_list toplevels;
struct wl_list focus_stack;
struct absinthe_output *focused_output; struct absinthe_output *focused_output;
struct wl_list outputs; struct wl_list outputs;
struct wl_listener new_output; struct wl_listener new_output;
@@ -100,6 +102,7 @@ struct absinthe_output {
struct absinthe_toplevel { struct absinthe_toplevel {
struct wl_list link; struct wl_list link;
struct wl_list flink; // for focus stack
struct absinthe_server *server; struct absinthe_server *server;
struct absinthe_output *output; struct absinthe_output *output;
struct wlr_scene_tree *scene_tree; struct wlr_scene_tree *scene_tree;
+2 -2
View File
@@ -27,7 +27,7 @@ struct absinthe_toplevel *absinthe_toplevel_at(struct absinthe_server *server, d
return tree->node.data; return tree->node.data;
break; break;
case WLR_SCENE_NODE_RECT: case WLR_SCENE_NODE_RECT:
return node->data; return node->data;
break; break;
default: default:
return NULL; return NULL;
@@ -66,7 +66,7 @@ void absinthe_toplevel_set_fullscreen(struct absinthe_toplevel *toplevel, bool f
} else { } else {
toplevel->geometry = toplevel->prev_geometry; toplevel->geometry = toplevel->prev_geometry;
toplevel->border_width = ABSINTHE_WINDOW_BORDER_WIDTH; toplevel->border_width = ABSINTHE_WINDOW_BORDER_WIDTH;
absinthe_toplevel_set_size(toplevel, toplevel->geometry.width, toplevel->geometry.height); absinthe_toplevel_set_size(toplevel, toplevel->geometry.width, toplevel->geometry.height);
} }
} }
+37 -2
View File
@@ -1,4 +1,5 @@
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/util/log.h>
#include "types.h" #include "types.h"
#include "absinthe-toplevel.h" #include "absinthe-toplevel.h"
@@ -26,11 +27,45 @@ void focus_toplevel(struct absinthe_toplevel *toplevel)
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat); struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
wlr_scene_node_raise_to_top(&toplevel->scene_tree->node); wlr_scene_node_raise_to_top(&toplevel->scene_tree->node);
wl_list_remove(&toplevel->link); wl_list_remove(&toplevel->flink);
wl_list_insert(&server->toplevels, &toplevel->link); wl_list_insert(&server->focus_stack, &toplevel->flink);
wlr_xdg_toplevel_set_activated(toplevel->xdg_toplevel, true); wlr_xdg_toplevel_set_activated(toplevel->xdg_toplevel, true);
absinthe_toplevel_set_border_color(toplevel, focused_border_color); absinthe_toplevel_set_border_color(toplevel, focused_border_color);
if (keyboard) if (keyboard)
wlr_seat_keyboard_notify_enter(seat, surface, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); wlr_seat_keyboard_notify_enter(seat, surface, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
} }
static struct absinthe_toplevel *focus_get_topmost(struct absinthe_server *server)
{
struct absinthe_toplevel *toplevel;
wl_list_for_each(toplevel, &server->focus_stack, flink) {
if (toplevel)
return toplevel;
}
return NULL;
}
void focus_next(struct absinthe_server *server)
{
struct absinthe_toplevel *toplevel = focus_get_topmost(server);
struct absinthe_toplevel *next;
wl_list_for_each(next, &toplevel->link, link) {
if (&next->link == &toplevel->server->toplevels)
continue;
break;
}
focus_toplevel(next);
}
void focus_prev(struct absinthe_server *server)
{
struct absinthe_toplevel *toplevel = focus_get_topmost(server);
struct absinthe_toplevel *prev;
wl_list_for_each_reverse(prev, &toplevel->link, link) {
if (&prev->link == &toplevel->server->toplevels)
continue;
break;
}
focus_toplevel(prev);
}
+19 -12
View File
@@ -8,6 +8,7 @@
#include "types.h" #include "types.h"
#include "absinthe-toplevel.h" #include "absinthe-toplevel.h"
#include "focus.h"
void keyboard_handle_modifiers(struct wl_listener *listener, void *data) void keyboard_handle_modifiers(struct wl_listener *listener, void *data)
{ {
@@ -19,6 +20,18 @@ void keyboard_handle_modifiers(struct wl_listener *listener, void *data)
static bool keyboard_handle_keybind(struct absinthe_server *server, xkb_keysym_t keysym) static bool keyboard_handle_keybind(struct absinthe_server *server, xkb_keysym_t keysym)
{ {
struct wlr_surface *surface;
struct wlr_xdg_toplevel *xdg_toplevel;
struct absinthe_toplevel *toplevel;
surface = server->seat->pointer_state.focused_surface;
if (surface)
xdg_toplevel = wlr_xdg_toplevel_try_from_wlr_surface(surface);
if (xdg_toplevel)
toplevel = xdg_toplevel->base->data;
switch (keysym) { switch (keysym) {
case XKB_KEY_Escape: case XKB_KEY_Escape:
wl_display_terminate(server->display); wl_display_terminate(server->display);
@@ -28,21 +41,15 @@ static bool keyboard_handle_keybind(struct absinthe_server *server, xkb_keysym_t
execl("/bin/sh", "sh", "-c", "alacritty", NULL); execl("/bin/sh", "sh", "-c", "alacritty", NULL);
break; break;
case XKB_KEY_f: case XKB_KEY_f:
struct wlr_surface *surface = server->seat->pointer_state.focused_surface;
if (!surface)
break;
struct wlr_xdg_toplevel *xdg_toplevel = wlr_xdg_toplevel_try_from_wlr_surface(surface);
if (!xdg_toplevel)
break;
struct absinthe_toplevel *toplevel = xdg_toplevel->base->data;
if (toplevel) if (toplevel)
absinthe_toplevel_set_fullscreen(toplevel, !toplevel->fullscreen); absinthe_toplevel_set_fullscreen(toplevel, !toplevel->fullscreen);
break; break;
case XKB_KEY_j:
focus_next(server);
break;
case XKB_KEY_k:
focus_prev(server);
break;
default: default:
return false; return false;
} }
+2
View File
@@ -89,6 +89,8 @@ int main(int argc, char **argv)
server.scene_layout = wlr_scene_attach_output_layout(server.scene, server.output_layout); server.scene_layout = wlr_scene_attach_output_layout(server.scene, server.output_layout);
wl_list_init(&server.toplevels); wl_list_init(&server.toplevels);
wl_list_init(&server.focus_stack);
server.xdg_shell = wlr_xdg_shell_create(server.display, 3); server.xdg_shell = wlr_xdg_shell_create(server.display, 3);
server.new_xdg_toplevel.notify = server_new_xdg_toplevel; server.new_xdg_toplevel.notify = server_new_xdg_toplevel;
wl_signal_add(&server.xdg_shell->events.new_toplevel, &server.new_xdg_toplevel); wl_signal_add(&server.xdg_shell->events.new_toplevel, &server.new_xdg_toplevel);
+3 -2
View File
@@ -42,14 +42,15 @@ void xdg_toplevel_map(struct wl_listener *listener, void *data)
} }
toplevel->border_width = ABSINTHE_WINDOW_BORDER_WIDTH; toplevel->border_width = ABSINTHE_WINDOW_BORDER_WIDTH;
absinthe_toplevel_set_border_color(toplevel, unfocused_border_color); absinthe_toplevel_set_border_color(toplevel, unfocused_border_color);
absinthe_toplevel_update_borders_geometry(toplevel); absinthe_toplevel_update_borders_geometry(toplevel);
toplevel->output = toplevel->server->focused_output; toplevel->output = toplevel->server->focused_output;
toplevel->fullscreen = false; 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);
} }
void xdg_toplevel_unmap(struct wl_listener *listener, void *data) void xdg_toplevel_unmap(struct wl_listener *listener, void *data)