2026-01-02 22:53:34 +07:00
|
|
|
#include <wayland-server-core.h>
|
2026-01-13 10:51:36 +07:00
|
|
|
#include <wlr/util/log.h>
|
2026-01-02 22:53:34 +07:00
|
|
|
|
|
|
|
|
#include "types.h"
|
2026-01-11 03:22:05 +07:00
|
|
|
#include "absinthe-toplevel.h"
|
2026-01-02 22:53:34 +07:00
|
|
|
|
|
|
|
|
void focus_toplevel(struct absinthe_toplevel *toplevel)
|
|
|
|
|
{
|
2026-04-25 14:09:14 +07:00
|
|
|
if (!toplevel)
|
|
|
|
|
return;
|
2026-01-02 22:53:34 +07:00
|
|
|
|
2026-04-25 14:09:14 +07:00
|
|
|
struct absinthe_server *server = toplevel->server;
|
|
|
|
|
struct wlr_seat *seat = server->seat;
|
|
|
|
|
struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
|
|
|
|
|
struct wlr_surface *surface;
|
2026-04-19 19:45:45 +07:00
|
|
|
#ifdef XWAYLAND
|
2026-04-25 18:11:07 +07:00
|
|
|
if (toplevel->type == ABSINTHE_TOPLEVEL_X11)
|
2026-04-25 14:09:14 +07:00
|
|
|
surface = toplevel->toplevel.x11->surface;
|
|
|
|
|
else
|
2026-04-19 19:45:45 +07:00
|
|
|
#endif
|
2026-04-25 14:09:14 +07:00
|
|
|
surface = toplevel->toplevel.xdg->base->surface;
|
2026-01-02 22:53:34 +07:00
|
|
|
|
2026-04-25 14:09:14 +07:00
|
|
|
if (surface == prev_surface)
|
|
|
|
|
return;
|
2026-01-02 22:53:34 +07:00
|
|
|
|
2026-04-25 14:09:14 +07:00
|
|
|
if (prev_surface) {
|
|
|
|
|
struct wlr_xdg_toplevel *prev_toplevel = wlr_xdg_toplevel_try_from_wlr_surface(prev_surface);
|
|
|
|
|
if (prev_toplevel) {
|
|
|
|
|
wlr_xdg_toplevel_set_activated(prev_toplevel, false);
|
|
|
|
|
absinthe_toplevel_set_border_color(prev_toplevel->base->data, unfocused_border_color);
|
|
|
|
|
}
|
2026-04-26 14:31:03 +07:00
|
|
|
|
|
|
|
|
struct wlr_xwayland_surface *prev_xwayland_surface = wlr_xwayland_surface_try_from_wlr_surface(prev_surface);
|
|
|
|
|
if (prev_xwayland_surface)
|
|
|
|
|
absinthe_toplevel_set_border_color(prev_surface->data, unfocused_border_color);
|
2026-04-25 14:09:14 +07:00
|
|
|
}
|
2026-01-02 22:53:34 +07:00
|
|
|
|
2026-04-25 14:09:14 +07:00
|
|
|
toplevel->server->focused_toplevel = toplevel;
|
2026-01-14 09:56:27 +07:00
|
|
|
|
2026-04-25 14:09:14 +07:00
|
|
|
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
|
|
|
|
|
wlr_scene_node_raise_to_top(&toplevel->scene_tree->node);
|
|
|
|
|
wl_list_remove(&toplevel->flink);
|
|
|
|
|
wl_list_insert(&server->focus_stack, &toplevel->flink);
|
2026-04-25 18:11:07 +07:00
|
|
|
if (toplevel->type != ABSINTHE_TOPLEVEL_X11)
|
2026-04-25 14:09:14 +07:00
|
|
|
wlr_xdg_toplevel_set_activated(toplevel->toplevel.xdg, true);
|
|
|
|
|
absinthe_toplevel_set_border_color(toplevel, focused_border_color);
|
2026-01-02 22:53:34 +07:00
|
|
|
|
2026-04-25 14:09:14 +07:00
|
|
|
if (keyboard)
|
|
|
|
|
wlr_seat_keyboard_notify_enter(seat, surface, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
|
2026-01-02 22:53:34 +07:00
|
|
|
}
|
2026-01-13 10:51:36 +07:00
|
|
|
|
2026-04-26 14:31:03 +07:00
|
|
|
struct absinthe_toplevel *focus_get_topmost(struct absinthe_server *server)
|
2026-01-13 10:51:36 +07:00
|
|
|
{
|
2026-04-25 14:09:14 +07:00
|
|
|
struct absinthe_toplevel *toplevel;
|
|
|
|
|
wl_list_for_each(toplevel, &server->focus_stack, flink) {
|
|
|
|
|
if (toplevel)
|
|
|
|
|
return toplevel;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
2026-01-13 10:51:36 +07:00
|
|
|
}
|
|
|
|
|
|
2026-04-26 22:34:31 +07:00
|
|
|
struct absinthe_toplevel *focus_get_first_tiled(struct absinthe_output *output)
|
|
|
|
|
{
|
|
|
|
|
struct absinthe_toplevel *toplevel;
|
|
|
|
|
wl_list_for_each(toplevel, &output->server->focus_stack, flink) {
|
|
|
|
|
if (toplevel->tiled && toplevel->output == output)
|
|
|
|
|
return toplevel;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct absinthe_toplevel *focus_get_last_tiled(struct absinthe_output *output)
|
|
|
|
|
{
|
|
|
|
|
struct absinthe_toplevel *toplevel;
|
|
|
|
|
wl_list_for_each_reverse(toplevel, &output->server->focus_stack, flink) {
|
|
|
|
|
if (toplevel->tiled && toplevel->output == output)
|
|
|
|
|
return toplevel;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-13 10:51:36 +07:00
|
|
|
void focus_next(struct absinthe_server *server)
|
|
|
|
|
{
|
2026-04-25 14:09:14 +07:00
|
|
|
struct absinthe_toplevel *toplevel = focus_get_topmost(server);
|
2026-04-26 14:31:03 +07:00
|
|
|
if (!toplevel)
|
|
|
|
|
return;
|
|
|
|
|
|
2026-04-25 14:09:14 +07:00
|
|
|
struct absinthe_toplevel *next;
|
|
|
|
|
wl_list_for_each(next, &toplevel->link, link) {
|
|
|
|
|
if (&next->link == &toplevel->server->toplevels)
|
|
|
|
|
continue;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
focus_toplevel(next);
|
2026-01-13 10:51:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void focus_prev(struct absinthe_server *server)
|
|
|
|
|
{
|
2026-04-25 14:09:14 +07:00
|
|
|
struct absinthe_toplevel *toplevel = focus_get_topmost(server);
|
2026-04-26 14:31:03 +07:00
|
|
|
if (!toplevel)
|
|
|
|
|
return;
|
|
|
|
|
|
2026-04-25 14:09:14 +07:00
|
|
|
struct absinthe_toplevel *prev;
|
|
|
|
|
wl_list_for_each_reverse(prev, &toplevel->link, link) {
|
|
|
|
|
if (&prev->link == &toplevel->server->toplevels)
|
|
|
|
|
continue;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
focus_toplevel(prev);
|
2026-01-13 10:51:36 +07:00
|
|
|
}
|