From e4657bb3dba9896e6df28f269bdd39b974267d9a Mon Sep 17 00:00:00 2001 From: speckitor Date: Tue, 6 Jan 2026 01:41:46 +0700 Subject: [PATCH] borders --- include/absinthe-toplevel.h | 5 +++++ include/types.h | 11 +++++++++- src/absinthe-toplevel.c | 41 +++++++++++++++++++++++++++++++++++++ src/cursor.c | 16 ++++++++------- src/main.c | 3 +-- src/server.c | 27 ++++++++++++++++-------- src/xdg-toplevel.c | 11 ++++++++++ 7 files changed, 95 insertions(+), 19 deletions(-) diff --git a/include/absinthe-toplevel.h b/include/absinthe-toplevel.h index 1c41677..a40455f 100644 --- a/include/absinthe-toplevel.h +++ b/include/absinthe-toplevel.h @@ -1,3 +1,8 @@ #include "types.h" struct absinthe_toplevel *absinthe_toplevel_at(struct absinthe_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); + +void absinthe_toplevel_set_position(struct absinthe_toplevel *toplevel, int32_t x, int32_t y); +void absinthe_toplevel_set_size(struct absinthe_toplevel *toplevel, int32_t width, int32_t height); +void absinthe_toplevel_update_border_geometry(struct absinthe_toplevel *toplevel); +void absinthe_toplevel_set_border_color(struct absinthe_toplevel *toplevel, const float color[4]); diff --git a/include/types.h b/include/types.h index 2ed838e..5f96eec 100644 --- a/include/types.h +++ b/include/types.h @@ -16,10 +16,16 @@ #include #include +// Configuration, later will be moved + #define ABSINTHE_CURSOR_MOD WLR_MODIFIER_ALT #define ABSINTHE_CURSOR_MOVE_BUTTON BTN_LEFT #define ABSINTHE_CURSOR_RESIZE_BUTTON BTN_RIGHT +#define ABSINTHE_BORDER_WIDTH 2 + +static const float bordercolor[4] = {0.88, 0.18, 0.18, 1.0}; + enum absinthe_cursor_mode { ABSINTHE_CURSOR_PASSTHROUGH, ABSINTHE_CURSOR_MOVE, @@ -63,9 +69,10 @@ struct absinthe_server { struct wl_listener pointer_focus_change; struct wl_listener request_set_selection; struct wl_list keyboards; + uint32_t last_pointer_motion_time_msec; enum absinthe_cursor_mode cursor_mode; struct absinthe_toplevel *grabbed_toplevel; - struct wlr_box grabbed_box; + struct wlr_box grabbed_geometry; uint32_t grab_x, grab_y; enum absinthe_cursor_resize_corner cursor_resize_corner; @@ -91,6 +98,8 @@ struct absinthe_toplevel { struct wl_list link; struct absinthe_server *server; struct wlr_scene_tree *scene_tree; + struct wlr_scene_rect *border[4]; + struct wlr_box geometry; struct wlr_xdg_toplevel *xdg_toplevel; struct wl_listener map; struct wl_listener unmap; diff --git a/src/absinthe-toplevel.c b/src/absinthe-toplevel.c index f74edd5..dc4deaf 100644 --- a/src/absinthe-toplevel.c +++ b/src/absinthe-toplevel.c @@ -22,3 +22,44 @@ struct absinthe_toplevel *absinthe_toplevel_at(struct absinthe_server *server, d } return tree->node.data; } + +void absinthe_toplevel_set_position(struct absinthe_toplevel *toplevel, int32_t x, int32_t y) +{ + wlr_scene_node_set_position(&toplevel->scene_tree->node, x, y); +} + +void absinthe_toplevel_set_size(struct absinthe_toplevel *toplevel, int32_t width, int32_t height) +{ + if (width == toplevel->xdg_toplevel->current.width && height == toplevel->xdg_toplevel->current.height) { + return; + } + + toplevel->geometry.width = width; + toplevel->geometry.height = height; + + wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, width, height); +} + +void absinthe_toplevel_update_border_geometry(struct absinthe_toplevel *toplevel) +{ + int bw = ABSINTHE_BORDER_WIDTH; + + wlr_scene_rect_set_size(toplevel->border[0], toplevel->geometry.width - 2 * bw, bw); + wlr_scene_rect_set_size(toplevel->border[1], toplevel->geometry.width - 2 * bw, bw); + wlr_scene_rect_set_size(toplevel->border[2], bw, toplevel->geometry.height); + wlr_scene_rect_set_size(toplevel->border[3], bw, toplevel->geometry.height); + + wlr_scene_node_set_position(&toplevel->border[0]->node, 0, -bw); + wlr_scene_node_set_position(&toplevel->border[1]->node, 0, toplevel->geometry.height - 2 * bw); + wlr_scene_node_set_position(&toplevel->border[2]->node, -bw, -bw); + wlr_scene_node_set_position(&toplevel->border[3]->node, toplevel->geometry.width - 2 * bw, -bw); + + absinthe_toplevel_set_size(toplevel, toplevel->geometry.width - 2 * bw, toplevel->geometry.height - 2 * bw); +} + +void absinthe_toplevel_set_border_color(struct absinthe_toplevel *toplevel, const float color[4]) +{ + for (int i = 0; i < 4; ++i) { + wlr_scene_rect_set_color(toplevel->border[i], color); + } +} diff --git a/src/cursor.c b/src/cursor.c index 963e339..21acc89 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -16,8 +16,8 @@ static void process_cursor_move(struct absinthe_server *server) { if (!toplevel) return; uint32_t new_x, new_y; - new_x = server->cursor->x - server->grab_x + server->grabbed_box.x; - new_y = server->cursor->y - server->grab_y + server->grabbed_box.y; + new_x = server->cursor->x - server->grab_x + server->grabbed_geometry.x; + new_y = server->cursor->y - server->grab_y + server->grabbed_geometry.y; wlr_scene_node_set_position(&toplevel->scene_tree->node, new_x, new_y); } @@ -27,10 +27,10 @@ static void process_cursor_resize(struct absinthe_server *server) { if (!toplevel) return; int32_t new_x, new_y, new_width, new_height; - new_x = server->grabbed_box.x; - new_y = server->grabbed_box.y; - new_width = server->grabbed_box.width; - new_height = server->grabbed_box.height; + new_x = server->grabbed_geometry.x; + new_y = server->grabbed_geometry.y; + new_width = server->grabbed_geometry.width; + new_height = server->grabbed_geometry.height; switch (server->cursor_resize_corner) { case ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT: @@ -59,7 +59,9 @@ static void process_cursor_resize(struct absinthe_server *server) { if (new_width > 0 && new_height > 0) { wlr_scene_node_set_position(&toplevel->scene_tree->node, new_x, new_y); - wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, new_width, new_height); + absinthe_toplevel_set_size(toplevel, new_width, new_height); + + absinthe_toplevel_update_border_geometry(toplevel); } } diff --git a/src/main.c b/src/main.c index c92f362..d0a605c 100644 --- a/src/main.c +++ b/src/main.c @@ -78,8 +78,6 @@ int main(int argc, char **argv) wl_signal_add(&server.backend->events.new_output, &server.new_output); server.output_layout = wlr_output_layout_create(server.display); - server.output_layout_change.notify = output_layout_change; - wl_signal_add(&server.output_layout->events.change, &server.output_layout_change); server.output_mgr = wlr_output_manager_v1_create(server.display); @@ -100,6 +98,7 @@ int main(int argc, char **argv) server.cursor_mgr = wlr_xcursor_manager_create(NULL, 24); + server.last_pointer_motion_time_msec = 0; server.cursor_mode = ABSINTHE_CURSOR_PASSTHROUGH; server.cursor_motion.notify = server_cursor_motion; wl_signal_add(&server.cursor->events.motion, &server.cursor_motion); diff --git a/src/server.c b/src/server.c index 7601a89..afc5615 100644 --- a/src/server.c +++ b/src/server.c @@ -60,6 +60,10 @@ void server_new_xdg_toplevel(struct wl_listener *listener, void *data) toplevel->xdg_toplevel = xdg_toplevel; toplevel->scene_tree = wlr_scene_xdg_surface_create(&toplevel->server->scene->tree, xdg_toplevel->base); toplevel->scene_tree->node.data = toplevel; + toplevel->geometry.x = 0; + toplevel->geometry.y = 0; + toplevel->geometry.width = 100; + toplevel->geometry.height = 100; xdg_toplevel->base->data = toplevel; toplevel->map.notify = xdg_toplevel_map; @@ -120,16 +124,22 @@ void server_cursor_motion(struct wl_listener *listener, void *data) { struct absinthe_server *server = wl_container_of(listener, server, cursor_motion); struct wlr_pointer_motion_event *event = data; - wlr_cursor_move(server->cursor, &event->pointer->base, event->delta_x, event->delta_y); - process_cursor_motion(server, event->time_msec); + if (event->time_msec - server->last_pointer_motion_time_msec > 5) { + wlr_cursor_move(server->cursor, &event->pointer->base, event->delta_x, event->delta_y); + process_cursor_motion(server, event->time_msec); + server->last_pointer_motion_time_msec = event->time_msec; + } } void server_cursor_motion_absolute(struct wl_listener *listener, void *data) { struct absinthe_server *server = wl_container_of(listener, server, cursor_motion_absolute); struct wlr_pointer_motion_absolute_event *event = data; - wlr_cursor_warp_absolute(server->cursor, &event->pointer->base, event->x, event->y); - process_cursor_motion(server, event->time_msec); + if (event->time_msec - server->last_pointer_motion_time_msec > 5) { + wlr_cursor_warp_absolute(server->cursor, &event->pointer->base, event->x, event->y); + process_cursor_motion(server, event->time_msec); + server->last_pointer_motion_time_msec = event->time_msec; + } } void server_cursor_button(struct wl_listener *listener, void *data) @@ -163,11 +173,10 @@ void server_cursor_button(struct wl_listener *listener, void *data) int lx, ly; wlr_scene_node_coords(&toplevel->scene_tree->node, &lx, &ly); - server->grabbed_box.x = lx; - server->grabbed_box.y = ly; - server->grabbed_box.width = toplevel->xdg_toplevel->base->geometry.width; - server->grabbed_box.height = toplevel->xdg_toplevel->base->geometry.height; - wlr_log(WLR_DEBUG, "%d, %d", server->grabbed_box.width, server->grabbed_box.height); + server->grabbed_geometry.x = lx; + server->grabbed_geometry.y = ly; + server->grabbed_geometry.width = toplevel->xdg_toplevel->base->geometry.width; + server->grabbed_geometry.height = toplevel->xdg_toplevel->base->geometry.height; server->grabbed_toplevel = toplevel; int width = toplevel->xdg_toplevel->base->geometry.width; diff --git a/src/xdg-toplevel.c b/src/xdg-toplevel.c index c6e94d0..7dd04d3 100644 --- a/src/xdg-toplevel.c +++ b/src/xdg-toplevel.c @@ -4,6 +4,7 @@ #include "types.h" #include "xdg-decoration.h" +#include "absinthe-toplevel.h" void xdg_toplevel_commit(struct wl_listener *listener, void *data) { @@ -22,6 +23,16 @@ void xdg_toplevel_map(struct wl_listener *listener, void *data) { struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, map); + for (int i = 0; i < 4; ++i) { + toplevel->border[i] = wlr_scene_rect_create(toplevel->scene_tree, 0, 0, bordercolor); + toplevel->border[i]->node.data = toplevel; + } + + absinthe_toplevel_update_border_geometry(toplevel); + + absinthe_toplevel_set_border_color(toplevel, bordercolor); + + wl_list_insert(&toplevel->server->toplevels, &toplevel->link); }