diff --git a/include/focus.h b/include/focus.h index 0068028..f920f7c 100644 --- a/include/focus.h +++ b/include/focus.h @@ -3,3 +3,5 @@ #include "types.h" void focus_toplevel(struct absinthe_toplevel *toplevel); +void focus_next(struct absinthe_server *server); +void focus_prev(struct absinthe_server *server); diff --git a/include/types.h b/include/types.h index 4d538a5..460f996 100644 --- a/include/types.h +++ b/include/types.h @@ -54,7 +54,6 @@ struct absinthe_server { struct wlr_xdg_shell *xdg_shell; struct wl_listener new_xdg_toplevel; struct wl_listener new_xdg_popup; - struct wl_list toplevels; struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; struct wl_listener new_xdg_decoration; @@ -78,6 +77,9 @@ struct absinthe_server { uint32_t grab_x, grab_y; enum absinthe_cursor_resize_corner cursor_resize_corner; + struct wl_list toplevels; + struct wl_list focus_stack; + struct absinthe_output *focused_output; struct wl_list outputs; struct wl_listener new_output; @@ -100,6 +102,7 @@ struct absinthe_output { struct absinthe_toplevel { struct wl_list link; + struct wl_list flink; // for focus stack struct absinthe_server *server; struct absinthe_output *output; struct wlr_scene_tree *scene_tree; diff --git a/src/absinthe-toplevel.c b/src/absinthe-toplevel.c index 8327bf4..7330031 100644 --- a/src/absinthe-toplevel.c +++ b/src/absinthe-toplevel.c @@ -27,7 +27,7 @@ struct absinthe_toplevel *absinthe_toplevel_at(struct absinthe_server *server, d return tree->node.data; break; case WLR_SCENE_NODE_RECT: - return node->data; + return node->data; break; default: return NULL; @@ -66,7 +66,7 @@ void absinthe_toplevel_set_fullscreen(struct absinthe_toplevel *toplevel, bool f } else { toplevel->geometry = toplevel->prev_geometry; 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); } } diff --git a/src/focus.c b/src/focus.c index 2292bae..f9d50a8 100644 --- a/src/focus.c +++ b/src/focus.c @@ -1,4 +1,5 @@ #include +#include #include "types.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); wlr_scene_node_raise_to_top(&toplevel->scene_tree->node); - wl_list_remove(&toplevel->link); - wl_list_insert(&server->toplevels, &toplevel->link); + wl_list_remove(&toplevel->flink); + wl_list_insert(&server->focus_stack, &toplevel->flink); wlr_xdg_toplevel_set_activated(toplevel->xdg_toplevel, true); absinthe_toplevel_set_border_color(toplevel, focused_border_color); if (keyboard) 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); +} diff --git a/src/keyboard.c b/src/keyboard.c index 19c4e4f..7436682 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -8,6 +8,7 @@ #include "types.h" #include "absinthe-toplevel.h" +#include "focus.h" 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) { + 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) { case XKB_KEY_Escape: 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); break; 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) absinthe_toplevel_set_fullscreen(toplevel, !toplevel->fullscreen); break; + case XKB_KEY_j: + focus_next(server); + break; + case XKB_KEY_k: + focus_prev(server); + break; default: return false; } diff --git a/src/main.c b/src/main.c index 4773479..00f66a4 100644 --- a/src/main.c +++ b/src/main.c @@ -89,6 +89,8 @@ int main(int argc, char **argv) server.scene_layout = wlr_scene_attach_output_layout(server.scene, server.output_layout); wl_list_init(&server.toplevels); + wl_list_init(&server.focus_stack); + server.xdg_shell = wlr_xdg_shell_create(server.display, 3); server.new_xdg_toplevel.notify = server_new_xdg_toplevel; wl_signal_add(&server.xdg_shell->events.new_toplevel, &server.new_xdg_toplevel); diff --git a/src/xdg-toplevel.c b/src/xdg-toplevel.c index f7f44fa..29c3af6 100644 --- a/src/xdg-toplevel.c +++ b/src/xdg-toplevel.c @@ -42,14 +42,15 @@ void xdg_toplevel_map(struct wl_listener *listener, void *data) } toplevel->border_width = ABSINTHE_WINDOW_BORDER_WIDTH; - + absinthe_toplevel_set_border_color(toplevel, unfocused_border_color); absinthe_toplevel_update_borders_geometry(toplevel); toplevel->output = toplevel->server->focused_output; toplevel->fullscreen = false; - + 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)