This commit is contained in:
2026-04-25 14:09:14 +07:00
parent 30e0b73447
commit 61439a9390
14 changed files with 1012 additions and 1011 deletions
+113 -113
View File
@@ -25,161 +25,161 @@
#include "config.h" #include "config.h"
enum absinthe_cursor_mode { enum absinthe_cursor_mode {
ABSINTHE_CURSOR_PASSTHROUGH, ABSINTHE_CURSOR_PASSTHROUGH,
ABSINTHE_CURSOR_MOVE, ABSINTHE_CURSOR_MOVE,
ABSINTHE_CURSOR_RESIZE, ABSINTHE_CURSOR_RESIZE,
}; };
enum absinthe_cursor_resize_corner { enum absinthe_cursor_resize_corner {
ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT, ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT,
ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT, ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT,
ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT, ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT,
ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT, ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT,
}; };
enum absinthe_toplevel_type { enum absinthe_toplevel_type {
ABSINTHE_TOPLEVEL_XDG, ABSINTHE_TOPLEVEL_XDG,
ABSINTHE_TOPLEVEL_LAYER_SHELL, ABSINTHE_TOPLEVEL_LAYER_SHELL,
ABSINTHE_TOPLEVEL_X11, ABSINTHE_TOPLEVEL_X11,
}; };
enum absinthe_layers { enum absinthe_layers {
ABSINTHE_LAYER_BACKGROUND, ABSINTHE_LAYER_BACKGROUND,
ABSINTHE_LAYER_BOTTOM, ABSINTHE_LAYER_BOTTOM,
ABSINTHE_LAYER_TILE, ABSINTHE_LAYER_TILE,
ABSINTHE_LAYER_FLOAT, ABSINTHE_LAYER_FLOAT,
ABSINTHE_LAYER_TOP, ABSINTHE_LAYER_TOP,
ABSINTHE_LAYER_FULLSCREEN, ABSINTHE_LAYER_FULLSCREEN,
ABSINTHE_LAYER_OVERLAY, ABSINTHE_LAYER_OVERLAY,
ABSINTHE_LAYER_LOCK, ABSINTHE_LAYER_LOCK,
ABSINTHE_LAYERS_COUNT, ABSINTHE_LAYERS_COUNT,
}; };
struct absinthe_output; struct absinthe_output;
struct absinthe_server { struct absinthe_server {
struct wl_display *display; struct wl_display *display;
struct wlr_backend *backend; struct wlr_backend *backend;
struct wlr_renderer *renderer; struct wlr_renderer *renderer;
struct wlr_allocator *allocator; struct wlr_allocator *allocator;
struct wlr_compositor *compositor; struct wlr_compositor *compositor;
struct wlr_scene *scene; struct wlr_scene *scene;
struct wlr_scene_output_layout *scene_layout; struct wlr_scene_output_layout *scene_layout;
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 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;
#ifdef XWAYLAND #ifdef XWAYLAND
struct wlr_xwayland *xwayland; struct wlr_xwayland *xwayland;
struct wl_listener xwayland_new_surface; struct wl_listener xwayland_new_surface;
struct wl_listener xwayland_ready; struct wl_listener xwayland_ready;
#endif #endif
struct wlr_cursor *cursor; struct wlr_cursor *cursor;
struct wlr_xcursor_manager *cursor_mgr; struct wlr_xcursor_manager *cursor_mgr;
struct wl_listener cursor_motion; struct wl_listener cursor_motion;
struct wl_listener cursor_motion_absolute; struct wl_listener cursor_motion_absolute;
struct wl_listener cursor_button; struct wl_listener cursor_button;
struct wl_listener cursor_axis; struct wl_listener cursor_axis;
struct wl_listener cursor_frame; struct wl_listener cursor_frame;
struct wlr_seat *seat; struct wlr_seat *seat;
struct wl_listener new_input; struct wl_listener new_input;
struct wl_listener request_cursor; struct wl_listener request_cursor;
struct wl_listener pointer_focus_change; struct wl_listener pointer_focus_change;
struct wl_listener request_set_selection; struct wl_listener request_set_selection;
struct wl_list keyboards; struct wl_list keyboards;
enum absinthe_cursor_mode cursor_mode; enum absinthe_cursor_mode cursor_mode;
struct wlr_box grabbed_geometry; struct wlr_box grabbed_geometry;
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 toplevels;
struct wl_list focus_stack; struct wl_list focus_stack;
struct absinthe_toplevel *focused_toplevel; struct absinthe_toplevel *focused_toplevel;
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;
struct wlr_output_layout *output_layout; struct wlr_output_layout *output_layout;
struct wl_listener output_layout_change; struct wl_listener output_layout_change;
struct wlr_output_manager_v1 *output_mgr; struct wlr_output_manager_v1 *output_mgr;
struct wl_listener output_mgr_apply; struct wl_listener output_mgr_apply;
struct wl_listener output_mgr_test; struct wl_listener output_mgr_test;
}; };
struct absinthe_output { struct absinthe_output {
struct wl_list link; struct wl_list link;
struct absinthe_server *server; struct absinthe_server *server;
struct wlr_box geometry; struct wlr_box geometry;
struct wlr_output *wlr_output; struct wlr_output *wlr_output;
struct wl_listener frame; struct wl_listener frame;
struct wl_listener request_state; struct wl_listener request_state;
struct wl_listener destroy; struct wl_listener destroy;
float main_stack_width; float main_stack_width;
float main_stack_size; float main_stack_size;
}; };
struct absinthe_toplevel { struct absinthe_toplevel {
enum absinthe_toplevel_type type; enum absinthe_toplevel_type type;
struct wl_list link; struct wl_list link;
struct wl_list flink; struct wl_list flink;
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;
struct wlr_scene_tree *scene_surface; struct wlr_scene_tree *scene_surface;
int32_t border_width; int32_t border_width;
struct wlr_scene_rect *border[4]; struct wlr_scene_rect *border[4];
struct wlr_xdg_toplevel_decoration_v1 *decoration; struct wlr_xdg_toplevel_decoration_v1 *decoration;
bool tiled, floating, fullscreen, maximized; bool tiled, floating, fullscreen, maximized;
uint32_t resizing; uint32_t resizing;
struct wlr_box geometry; struct wlr_box geometry;
struct wlr_box prev_geometry; struct wlr_box prev_geometry;
union { union {
struct wlr_xdg_toplevel *xdg; struct wlr_xdg_toplevel *xdg;
struct wlr_xwayland_surface *x11; struct wlr_xwayland_surface *x11;
} toplevel; } toplevel;
struct wl_listener map; struct wl_listener map;
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener commit; struct wl_listener commit;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener request_move; struct wl_listener request_move;
struct wl_listener request_resize; struct wl_listener request_resize;
struct wl_listener request_maximize; struct wl_listener request_maximize;
struct wl_listener request_fullscreen; struct wl_listener request_fullscreen;
struct wl_listener decoration_request_mode; struct wl_listener decoration_request_mode;
struct wl_listener decoration_destroy; struct wl_listener decoration_destroy;
#ifdef XWAYLAND #ifdef XWAYLAND
struct wl_listener xwayland_activate; struct wl_listener xwayland_activate;
struct wl_listener xwayland_associate; struct wl_listener xwayland_associate;
struct wl_listener xwayland_dissociate; struct wl_listener xwayland_dissociate;
struct wl_listener xwayland_configure; struct wl_listener xwayland_configure;
struct wl_listener xwayland_set_hints; struct wl_listener xwayland_set_hints;
#endif #endif
}; };
struct absinthe_popup { struct absinthe_popup {
struct wlr_xdg_popup *xdg_popup; struct wlr_xdg_popup *xdg_popup;
struct wl_listener commit; struct wl_listener commit;
struct wl_listener destroy; struct wl_listener destroy;
}; };
struct absinthe_keyboard { struct absinthe_keyboard {
struct wl_list link; struct wl_list link;
struct absinthe_server *server; struct absinthe_server *server;
struct wlr_keyboard *wlr_keyboard; struct wlr_keyboard *wlr_keyboard;
struct wl_listener modifiers; struct wl_listener modifiers;
struct wl_listener key; struct wl_listener key;
struct wl_listener destroy; struct wl_listener destroy;
}; };
+161 -161
View File
@@ -12,272 +12,272 @@
bool absinthe_toplevel_is_x11(struct absinthe_toplevel *toplevel) bool absinthe_toplevel_is_x11(struct absinthe_toplevel *toplevel)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
return toplevel->type == ABSINTHE_TOPLEVEL_X11; return toplevel->type == ABSINTHE_TOPLEVEL_X11;
#endif #endif
return false; return false;
} }
bool absinthe_toplevel_is_unmanaged(struct absinthe_toplevel *toplevel) bool absinthe_toplevel_is_unmanaged(struct absinthe_toplevel *toplevel)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
if (absinthe_toplevel_is_x11(toplevel)) if (absinthe_toplevel_is_x11(toplevel))
return toplevel->toplevel.x11->override_redirect; return toplevel->toplevel.x11->override_redirect;
#endif #endif
return false; return false;
} }
void absinthe_toplevel_update_geometry(struct absinthe_toplevel *toplevel) void absinthe_toplevel_update_geometry(struct absinthe_toplevel *toplevel)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
if (absinthe_toplevel_is_x11(toplevel)) { if (absinthe_toplevel_is_x11(toplevel)) {
toplevel->geometry.x = toplevel->toplevel.x11->x; toplevel->geometry.x = toplevel->toplevel.x11->x;
toplevel->geometry.y = toplevel->toplevel.x11->y; toplevel->geometry.y = toplevel->toplevel.x11->y;
toplevel->geometry.width = toplevel->toplevel.x11->width; toplevel->geometry.width = toplevel->toplevel.x11->width;
toplevel->geometry.height = toplevel->toplevel.x11->height; toplevel->geometry.height = toplevel->toplevel.x11->height;
} else } else
#endif #endif
{ {
toplevel->geometry = toplevel->toplevel.xdg->base->geometry; toplevel->geometry = toplevel->toplevel.xdg->base->geometry;
} }
} }
struct wlr_surface *absinthe_toplevel_surface(struct absinthe_toplevel *toplevel) struct wlr_surface *absinthe_toplevel_surface(struct absinthe_toplevel *toplevel)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
if (absinthe_toplevel_is_x11(toplevel)) if (absinthe_toplevel_is_x11(toplevel))
return toplevel->toplevel.x11->surface; return toplevel->toplevel.x11->surface;
#endif #endif
return toplevel->toplevel.xdg->base->surface; return toplevel->toplevel.xdg->base->surface;
} }
void absinthe_toplevel_map(struct wl_listener *listener, void *data) void absinthe_toplevel_map(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, map); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, map);
toplevel->scene_tree = wlr_scene_tree_create(&toplevel->server->scene->tree); toplevel->scene_tree = wlr_scene_tree_create(&toplevel->server->scene->tree);
toplevel->scene_tree->node.data = toplevel; toplevel->scene_tree->node.data = toplevel;
wlr_scene_node_set_enabled(&toplevel->scene_tree->node, false); wlr_scene_node_set_enabled(&toplevel->scene_tree->node, false);
toplevel->tiled = true; toplevel->tiled = true;
if (wl_resource_get_version(toplevel->toplevel.xdg->resource) >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { if (wl_resource_get_version(toplevel->toplevel.xdg->resource) >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
wlr_xdg_toplevel_set_tiled(toplevel->toplevel.xdg, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); wlr_xdg_toplevel_set_tiled(toplevel->toplevel.xdg, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
} else { } else {
wlr_xdg_toplevel_set_maximized(toplevel->toplevel.xdg, true); wlr_xdg_toplevel_set_maximized(toplevel->toplevel.xdg, true);
} }
toplevel->border_width = absinthe_toplevel_is_unmanaged(toplevel) toplevel->border_width = absinthe_toplevel_is_unmanaged(toplevel)
? 0 ? 0
: ABSINTHE_TOPLEVEL_BORDER_WIDTH; : ABSINTHE_TOPLEVEL_BORDER_WIDTH;
#ifdef XWAYLAND #ifdef XWAYLAND
if (absinthe_toplevel_is_x11(toplevel)) { if (absinthe_toplevel_is_x11(toplevel)) {
toplevel->scene_surface = wlr_scene_subsurface_tree_create(toplevel->scene_tree, toplevel->toplevel.x11->surface); toplevel->scene_surface = wlr_scene_subsurface_tree_create(toplevel->scene_tree, toplevel->toplevel.x11->surface);
} else } else
#endif #endif
{ {
toplevel->scene_surface = wlr_scene_subsurface_tree_create(toplevel->scene_tree, toplevel->toplevel.xdg->base->surface); toplevel->scene_surface = wlr_scene_subsurface_tree_create(toplevel->scene_tree, toplevel->toplevel.xdg->base->surface);
} }
toplevel->scene_surface->node.data = toplevel; toplevel->scene_surface->node.data = toplevel;
absinthe_toplevel_update_geometry(toplevel); absinthe_toplevel_update_geometry(toplevel);
toplevel->border_width = absinthe_toplevel_is_unmanaged(toplevel) toplevel->border_width = absinthe_toplevel_is_unmanaged(toplevel)
? 0 ? 0
: ABSINTHE_TOPLEVEL_BORDER_WIDTH; : ABSINTHE_TOPLEVEL_BORDER_WIDTH;
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_border_color); toplevel->border[i] = wlr_scene_rect_create(toplevel->scene_tree, 0, 0, unfocused_border_color);
toplevel->border[i]->node.data = toplevel; toplevel->border[i]->node.data = toplevel;
} }
update_focused_output(toplevel->server); update_focused_output(toplevel->server);
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); wl_list_insert(&toplevel->server->focus_stack, &toplevel->flink);
layout_arrange(toplevel->output); layout_arrange(toplevel->output);
} }
void absinthe_toplevel_unmap(struct wl_listener *listener, void *data) void absinthe_toplevel_unmap(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, unmap); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, unmap);
if (toplevel == toplevel->server->focused_toplevel) if (toplevel == toplevel->server->focused_toplevel)
toplevel->server->focused_toplevel = NULL; toplevel->server->focused_toplevel = NULL;
wl_list_remove(&toplevel->link); wl_list_remove(&toplevel->link);
wl_list_remove(&toplevel->flink); wl_list_remove(&toplevel->flink);
wlr_scene_node_destroy(&toplevel->scene_tree->node); wlr_scene_node_destroy(&toplevel->scene_tree->node);
layout_arrange(toplevel->output); layout_arrange(toplevel->output);
} }
void absinthe_toplevel_destroy(struct wl_listener *listener, void *data) void absinthe_toplevel_destroy(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, destroy); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, destroy);
#ifdef XWAYLAND #ifdef XWAYLAND
if (absinthe_toplevel_is_x11(toplevel)) { if (absinthe_toplevel_is_x11(toplevel)) {
wl_list_remove(&toplevel->xwayland_activate.link); wl_list_remove(&toplevel->xwayland_activate.link);
wl_list_remove(&toplevel->xwayland_associate.link); wl_list_remove(&toplevel->xwayland_associate.link);
wl_list_remove(&toplevel->xwayland_dissociate.link); wl_list_remove(&toplevel->xwayland_dissociate.link);
wl_list_remove(&toplevel->xwayland_configure.link); wl_list_remove(&toplevel->xwayland_configure.link);
wl_list_remove(&toplevel->xwayland_set_hints.link); wl_list_remove(&toplevel->xwayland_set_hints.link);
} else } else
#endif #endif
{ {
wl_list_remove(&toplevel->map.link); wl_list_remove(&toplevel->map.link);
wl_list_remove(&toplevel->unmap.link); wl_list_remove(&toplevel->unmap.link);
wl_list_remove(&toplevel->commit.link); wl_list_remove(&toplevel->commit.link);
wl_list_remove(&toplevel->request_move.link); wl_list_remove(&toplevel->request_move.link);
wl_list_remove(&toplevel->request_resize.link); wl_list_remove(&toplevel->request_resize.link);
} }
wl_list_remove(&toplevel->destroy.link); wl_list_remove(&toplevel->destroy.link);
wl_list_remove(&toplevel->request_maximize.link); wl_list_remove(&toplevel->request_maximize.link);
wl_list_remove(&toplevel->request_fullscreen.link); wl_list_remove(&toplevel->request_fullscreen.link);
free(toplevel); free(toplevel);
} }
void absinthe_toplevel_request_move(struct wl_listener *listener, void *data) void absinthe_toplevel_request_move(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_maximize); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_maximize);
if (toplevel->toplevel.xdg->base->initialized) if (toplevel->toplevel.xdg->base->initialized)
wlr_xdg_surface_schedule_configure(toplevel->toplevel.xdg->base); wlr_xdg_surface_schedule_configure(toplevel->toplevel.xdg->base);
} }
void absinthe_toplevel_request_resize(struct wl_listener *listener, void *data) void absinthe_toplevel_request_resize(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_maximize); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_maximize);
if (toplevel->toplevel.xdg->base->initialized) if (toplevel->toplevel.xdg->base->initialized)
wlr_xdg_surface_schedule_configure(toplevel->toplevel.xdg->base); wlr_xdg_surface_schedule_configure(toplevel->toplevel.xdg->base);
} }
void absinthe_toplevel_request_maximize(struct wl_listener *listener, void *data) void absinthe_toplevel_request_maximize(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_maximize); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_maximize);
if (toplevel->toplevel.xdg->base->initialized) if (toplevel->toplevel.xdg->base->initialized)
wlr_xdg_surface_schedule_configure(toplevel->toplevel.xdg->base); wlr_xdg_surface_schedule_configure(toplevel->toplevel.xdg->base);
} }
void absinthe_toplevel_request_fullscreen(struct wl_listener *listener, void *data) void absinthe_toplevel_request_fullscreen(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_fullscreen); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_fullscreen);
absinthe_toplevel_set_fullscreen(toplevel, toplevel->toplevel.xdg->requested.fullscreen); absinthe_toplevel_set_fullscreen(toplevel, toplevel->toplevel.xdg->requested.fullscreen);
} }
struct absinthe_toplevel *absinthe_toplevel_at(struct absinthe_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) struct absinthe_toplevel *absinthe_toplevel_at(struct absinthe_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy)
{ {
struct wlr_scene_node *node = wlr_scene_node_at(&server->scene->tree.node, lx, ly, sx, sy); struct wlr_scene_node *node = wlr_scene_node_at(&server->scene->tree.node, lx, ly, sx, sy);
if (!node) { if (!node) {
return NULL; return NULL;
} }
switch (node->type) { switch (node->type) {
case WLR_SCENE_NODE_BUFFER: case WLR_SCENE_NODE_BUFFER:
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(scene_buffer); struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(scene_buffer);
if (!scene_surface) { if (!scene_surface) {
return NULL; return NULL;
} }
*surface = scene_surface->surface; *surface = scene_surface->surface;
struct wlr_scene_tree *tree = node->parent; struct wlr_scene_tree *tree = node->parent;
while (tree != NULL && tree->node.data == NULL) { while (tree != NULL && tree->node.data == NULL) {
tree = tree->node.parent; tree = tree->node.parent;
} }
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;
} }
} }
void absinthe_toplevel_set_position(struct absinthe_toplevel *toplevel, int32_t x, int32_t y) 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); 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) void absinthe_toplevel_set_size(struct absinthe_toplevel *toplevel, int32_t width, int32_t height)
{ {
if (width <= toplevel->border_width || height <= toplevel->border_width || (width == toplevel->geometry.width && height == toplevel->geometry.height)) if (width <= toplevel->border_width || height <= toplevel->border_width || (width == toplevel->geometry.width && height == toplevel->geometry.height))
return; return;
toplevel->geometry.width = width; toplevel->geometry.width = width;
toplevel->geometry.height = height; toplevel->geometry.height = height;
if (toplevel->type == ABSINTHE_TOPLEVEL_XDG) { if (toplevel->type == ABSINTHE_TOPLEVEL_XDG) {
toplevel->resizing = wlr_xdg_toplevel_set_size(toplevel->toplevel.xdg, width - 2 * toplevel->border_width, height - 2 * toplevel->border_width); toplevel->resizing = wlr_xdg_toplevel_set_size(toplevel->toplevel.xdg, width - 2 * toplevel->border_width, height - 2 * toplevel->border_width);
} }
#ifdef XWAYLAND #ifdef XWAYLAND
else if (toplevel->type == ABSINTHE_TOPLEVEL_X11) { else if (toplevel->type == ABSINTHE_TOPLEVEL_X11) {
wlr_xwayland_surface_configure(toplevel->toplevel.x11, wlr_xwayland_surface_configure(toplevel->toplevel.x11,
toplevel->geometry.x, toplevel->geometry.y, width - 2 * toplevel->border_width, height - 2 * toplevel->border_width); toplevel->geometry.x, toplevel->geometry.y, width - 2 * toplevel->border_width, height - 2 * toplevel->border_width);
absinthe_toplevel_set_position(toplevel, toplevel->geometry.x + toplevel->border_width, toplevel->geometry.y + toplevel->border_width); absinthe_toplevel_set_position(toplevel, toplevel->geometry.x + toplevel->border_width, toplevel->geometry.y + toplevel->border_width);
} }
#endif #endif
struct wlr_box clip = { struct wlr_box clip = {
.x = 0, .x = 0,
.y = 0, .y = 0,
.width = width - toplevel->border_width, .width = width - toplevel->border_width,
.height = height - toplevel->border_width, .height = height - toplevel->border_width,
}; };
wlr_scene_subsurface_tree_set_clip(&toplevel->scene_surface->node, &clip); wlr_scene_subsurface_tree_set_clip(&toplevel->scene_surface->node, &clip);
} }
void absinthe_toplevel_set_fullscreen(struct absinthe_toplevel *toplevel, bool fullscreen) void absinthe_toplevel_set_fullscreen(struct absinthe_toplevel *toplevel, bool fullscreen)
{ {
if (!toplevel || toplevel->fullscreen == fullscreen) if (!toplevel || toplevel->fullscreen == fullscreen)
return; return;
struct absinthe_output *output = toplevel->server->focused_output; struct absinthe_output *output = toplevel->server->focused_output;
toplevel->fullscreen = fullscreen; toplevel->fullscreen = fullscreen;
wlr_xdg_toplevel_set_fullscreen(toplevel->toplevel.xdg, fullscreen); wlr_xdg_toplevel_set_fullscreen(toplevel->toplevel.xdg, fullscreen);
if (fullscreen) { if (fullscreen) {
toplevel->prev_geometry = toplevel->geometry; toplevel->prev_geometry = toplevel->geometry;
toplevel->geometry = output->geometry; toplevel->geometry = output->geometry;
toplevel->border_width = 0; toplevel->border_width = 0;
absinthe_toplevel_set_size(toplevel, toplevel->geometry.width, toplevel->geometry.height); absinthe_toplevel_set_size(toplevel, toplevel->geometry.width, toplevel->geometry.height);
} else { } else {
toplevel->geometry = toplevel->prev_geometry; toplevel->geometry = toplevel->prev_geometry;
toplevel->border_width = absinthe_toplevel_is_unmanaged(toplevel) toplevel->border_width = absinthe_toplevel_is_unmanaged(toplevel)
? 0 ? 0
: ABSINTHE_TOPLEVEL_BORDER_WIDTH; : ABSINTHE_TOPLEVEL_BORDER_WIDTH;
absinthe_toplevel_set_size(toplevel, toplevel->geometry.width, toplevel->geometry.height); absinthe_toplevel_set_size(toplevel, toplevel->geometry.width, toplevel->geometry.height);
} }
} }
void absinthe_toplevel_set_border_color(struct absinthe_toplevel *toplevel, const float color[4]) void absinthe_toplevel_set_border_color(struct absinthe_toplevel *toplevel, const float color[4])
{ {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
wlr_scene_rect_set_color(toplevel->border[i], color); wlr_scene_rect_set_color(toplevel->border[i], color);
} }
} }
void absinthe_toplevel_update_borders_geometry(struct absinthe_toplevel *toplevel) void absinthe_toplevel_update_borders_geometry(struct absinthe_toplevel *toplevel)
{ {
int32_t border_width = toplevel->border_width; int32_t border_width = toplevel->border_width;
if (toplevel->geometry.width - 2 * border_width < 0 || toplevel->geometry.height - 2 * border_width < 0) if (toplevel->geometry.width - 2 * border_width < 0 || toplevel->geometry.height - 2 * border_width < 0)
return; return;
wlr_scene_node_set_position(&toplevel->scene_tree->node, toplevel->geometry.x, toplevel->geometry.y); wlr_scene_node_set_position(&toplevel->scene_tree->node, toplevel->geometry.x, toplevel->geometry.y);
wlr_scene_node_set_position(&toplevel->scene_surface->node, border_width, border_width); wlr_scene_node_set_position(&toplevel->scene_surface->node, border_width, border_width);
wlr_scene_rect_set_size(toplevel->border[0], toplevel->geometry.width - 2 * border_width, border_width); wlr_scene_rect_set_size(toplevel->border[0], toplevel->geometry.width - 2 * border_width, border_width);
wlr_scene_rect_set_size(toplevel->border[1], toplevel->geometry.width - 2 * border_width, border_width); wlr_scene_rect_set_size(toplevel->border[1], toplevel->geometry.width - 2 * border_width, border_width);
wlr_scene_rect_set_size(toplevel->border[2], border_width, toplevel->geometry.height); wlr_scene_rect_set_size(toplevel->border[2], border_width, toplevel->geometry.height);
wlr_scene_rect_set_size(toplevel->border[3], border_width, toplevel->geometry.height); wlr_scene_rect_set_size(toplevel->border[3], border_width, toplevel->geometry.height);
wlr_scene_node_set_position(&toplevel->border[0]->node, border_width, 0); wlr_scene_node_set_position(&toplevel->border[0]->node, border_width, 0);
wlr_scene_node_set_position(&toplevel->border[1]->node, border_width, toplevel->geometry.height - border_width); wlr_scene_node_set_position(&toplevel->border[1]->node, border_width, toplevel->geometry.height - border_width);
wlr_scene_node_set_position(&toplevel->border[2]->node, 0, 0); wlr_scene_node_set_position(&toplevel->border[2]->node, 0, 0);
wlr_scene_node_set_position(&toplevel->border[3]->node, toplevel->geometry.width - border_width, 0); wlr_scene_node_set_position(&toplevel->border[3]->node, toplevel->geometry.width - border_width, 0);
} }
+105 -105
View File
@@ -6,143 +6,143 @@
void reset_cursor_mode(struct absinthe_server *server) void reset_cursor_mode(struct absinthe_server *server)
{ {
server->cursor_mode = ABSINTHE_CURSOR_PASSTHROUGH; server->cursor_mode = ABSINTHE_CURSOR_PASSTHROUGH;
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "default"); wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "default");
if (server->focused_toplevel) { if (server->focused_toplevel) {
wlr_xdg_toplevel_set_resizing(server->focused_toplevel->toplevel.xdg, false); wlr_xdg_toplevel_set_resizing(server->focused_toplevel->toplevel.xdg, false);
} }
} }
static void process_cursor_move(struct absinthe_server *server) { static void process_cursor_move(struct absinthe_server *server) {
struct absinthe_toplevel *toplevel = server->focused_toplevel; struct absinthe_toplevel *toplevel = server->focused_toplevel;
if (!toplevel) if (!toplevel)
return; return;
if (toplevel->fullscreen) { if (toplevel->fullscreen) {
toplevel->prev_geometry = toplevel->geometry; toplevel->prev_geometry = toplevel->geometry;
absinthe_toplevel_set_fullscreen(toplevel, false); absinthe_toplevel_set_fullscreen(toplevel, false);
} }
uint32_t new_x, new_y; uint32_t new_x, new_y;
new_x = server->cursor->x - server->grab_x + server->grabbed_geometry.x; new_x = server->cursor->x - server->grab_x + server->grabbed_geometry.x;
new_y = server->cursor->y - server->grab_y + server->grabbed_geometry.y; new_y = server->cursor->y - server->grab_y + server->grabbed_geometry.y;
toplevel->geometry.x = new_x; toplevel->geometry.x = new_x;
toplevel->geometry.y = new_y; toplevel->geometry.y = new_y;
absinthe_toplevel_set_position(toplevel, new_x, new_y); absinthe_toplevel_set_position(toplevel, new_x, new_y);
} }
static void apply_resize(struct absinthe_toplevel *toplevel, struct wlr_box *new_geometry) static void apply_resize(struct absinthe_toplevel *toplevel, struct wlr_box *new_geometry)
{ {
int32_t min_width = toplevel->toplevel.xdg->current.min_width; int32_t min_width = toplevel->toplevel.xdg->current.min_width;
int32_t min_height = toplevel->toplevel.xdg->current.min_height; int32_t min_height = toplevel->toplevel.xdg->current.min_height;
int32_t max_width = toplevel->toplevel.xdg->current.max_width; int32_t max_width = toplevel->toplevel.xdg->current.max_width;
int32_t max_height = toplevel->toplevel.xdg->current.max_height; int32_t max_height = toplevel->toplevel.xdg->current.max_height;
bool resize = false; bool resize = false;
if (max_width == 0) if (max_width == 0)
max_width = 10000; max_width = 10000;
if (max_height == 0) if (max_height == 0)
max_height = 10000; max_height = 10000;
if (toplevel->geometry.width != min_width && new_geometry->width >= min_width && new_geometry->width <= max_width) { if (toplevel->geometry.width != min_width && new_geometry->width >= min_width && new_geometry->width <= max_width) {
toplevel->geometry.x = new_geometry->x; toplevel->geometry.x = new_geometry->x;
toplevel->geometry.width = new_geometry->width; toplevel->geometry.width = new_geometry->width;
resize = true; resize = true;
} }
if (toplevel->geometry.height != min_height && new_geometry->height >= min_height && new_geometry->height<= max_height) { if (toplevel->geometry.height != min_height && new_geometry->height >= min_height && new_geometry->height<= max_height) {
toplevel->geometry.y = new_geometry->y; toplevel->geometry.y = new_geometry->y;
toplevel->geometry.height = new_geometry->height; toplevel->geometry.height = new_geometry->height;
resize = true; resize = true;
} }
if (resize) if (resize)
absinthe_toplevel_set_size(toplevel, toplevel->geometry.width, toplevel->geometry.height); absinthe_toplevel_set_size(toplevel, toplevel->geometry.width, toplevel->geometry.height);
} }
static void process_cursor_resize(struct absinthe_server *server) { static void process_cursor_resize(struct absinthe_server *server) {
struct absinthe_toplevel *toplevel = server->focused_toplevel; struct absinthe_toplevel *toplevel = server->focused_toplevel;
if (!toplevel) if (!toplevel)
return; return;
if (toplevel->resizing) if (toplevel->resizing)
return; return;
if (toplevel->fullscreen) if (toplevel->fullscreen)
absinthe_toplevel_set_fullscreen(toplevel, false); absinthe_toplevel_set_fullscreen(toplevel, false);
int32_t new_x, new_y, new_width, new_height; int32_t new_x, new_y, new_width, new_height;
new_x = server->grabbed_geometry.x; new_x = server->grabbed_geometry.x;
new_y = server->grabbed_geometry.y; new_y = server->grabbed_geometry.y;
new_width = server->grabbed_geometry.width; new_width = server->grabbed_geometry.width;
new_height = server->grabbed_geometry.height; new_height = server->grabbed_geometry.height;
int32_t dx = server->cursor->x - server->grab_x; int32_t dx = server->cursor->x - server->grab_x;
int32_t dy = server->cursor->y - server->grab_y; int32_t dy = server->cursor->y - server->grab_y;
if (dx == 0 && dy == 0) if (dx == 0 && dy == 0)
return; return;
switch (server->cursor_resize_corner) { switch (server->cursor_resize_corner) {
case ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT: case ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT:
new_x += dx; new_x += dx;
new_y += dy; new_y += dy;
new_width -= dx; new_width -= dx;
new_height -= dy; new_height -= dy;
break; break;
case ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT: case ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT:
new_y += dy; new_y += dy;
new_width += dx; new_width += dx;
new_height -= dy; new_height -= dy;
break; break;
case ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT: case ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT:
new_x += dx; new_x += dx;
new_width -= dx; new_width -= dx;
new_height += dy; new_height += dy;
break; break;
case ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT: case ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT:
new_width += dx; new_width += dx;
new_height += dy; new_height += dy;
break; break;
default: // unreachable default: // unreachable
break; break;
} }
if (new_width > 0 && new_height > 0) { if (new_width > 0 && new_height > 0) {
struct wlr_box new_geometry = { struct wlr_box new_geometry = {
.x = new_x, .x = new_x,
.y = new_y, .y = new_y,
.width = new_width, .width = new_width,
.height = new_height, .height = new_height,
}; };
apply_resize(server->focused_toplevel, &new_geometry); apply_resize(server->focused_toplevel, &new_geometry);
} }
} }
void process_cursor_motion(struct absinthe_server *server, uint32_t time) void process_cursor_motion(struct absinthe_server *server, uint32_t time)
{ {
double sx, sy; double sx, sy;
struct wlr_seat *seat = server->seat; struct wlr_seat *seat = server->seat;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
struct absinthe_toplevel *toplevel = absinthe_toplevel_at(server, server->cursor->x, server->cursor->y, &surface, &sx, &sy); struct absinthe_toplevel *toplevel = absinthe_toplevel_at(server, server->cursor->x, server->cursor->y, &surface, &sx, &sy);
if (server->cursor_mode == ABSINTHE_CURSOR_MOVE) { if (server->cursor_mode == ABSINTHE_CURSOR_MOVE) {
process_cursor_move(server); process_cursor_move(server);
return; return;
} else if (server->cursor_mode == ABSINTHE_CURSOR_RESIZE) { } else if (server->cursor_mode == ABSINTHE_CURSOR_RESIZE) {
process_cursor_resize(server); process_cursor_resize(server);
return; return;
} }
if (surface) { if (surface) {
wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat, time, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy);
} else { } else {
wlr_seat_pointer_clear_focus(seat); wlr_seat_pointer_clear_focus(seat);
} }
} }
+51 -51
View File
@@ -6,75 +6,75 @@
void focus_toplevel(struct absinthe_toplevel *toplevel) void focus_toplevel(struct absinthe_toplevel *toplevel)
{ {
if (!toplevel) if (!toplevel)
return; return;
struct absinthe_server *server = toplevel->server; struct absinthe_server *server = toplevel->server;
struct wlr_seat *seat = server->seat; struct wlr_seat *seat = server->seat;
struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface; struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
struct wlr_surface *surface; struct wlr_surface *surface;
#ifdef XWAYLAND #ifdef XWAYLAND
if (absinthe_toplevel_is_x11(toplevel)) if (absinthe_toplevel_is_x11(toplevel))
surface = toplevel->toplevel.x11->surface; surface = toplevel->toplevel.x11->surface;
else else
#endif #endif
surface = toplevel->toplevel.xdg->base->surface; surface = toplevel->toplevel.xdg->base->surface;
if (surface == prev_surface) if (surface == prev_surface)
return; return;
if (prev_surface) { if (prev_surface) {
struct wlr_xdg_toplevel *prev_toplevel = wlr_xdg_toplevel_try_from_wlr_surface(prev_surface); struct wlr_xdg_toplevel *prev_toplevel = wlr_xdg_toplevel_try_from_wlr_surface(prev_surface);
if (prev_toplevel) { if (prev_toplevel) {
wlr_xdg_toplevel_set_activated(prev_toplevel, false); wlr_xdg_toplevel_set_activated(prev_toplevel, false);
absinthe_toplevel_set_border_color(prev_toplevel->base->data, unfocused_border_color); absinthe_toplevel_set_border_color(prev_toplevel->base->data, unfocused_border_color);
} }
} }
toplevel->server->focused_toplevel = toplevel; toplevel->server->focused_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->flink); wl_list_remove(&toplevel->flink);
wl_list_insert(&server->focus_stack, &toplevel->flink); wl_list_insert(&server->focus_stack, &toplevel->flink);
if (!absinthe_toplevel_is_x11(toplevel)) if (!absinthe_toplevel_is_x11(toplevel))
wlr_xdg_toplevel_set_activated(toplevel->toplevel.xdg, true); wlr_xdg_toplevel_set_activated(toplevel->toplevel.xdg, 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) static struct absinthe_toplevel *focus_get_topmost(struct absinthe_server *server)
{ {
struct absinthe_toplevel *toplevel; struct absinthe_toplevel *toplevel;
wl_list_for_each(toplevel, &server->focus_stack, flink) { wl_list_for_each(toplevel, &server->focus_stack, flink) {
if (toplevel) if (toplevel)
return toplevel; return toplevel;
} }
return NULL; return NULL;
} }
void focus_next(struct absinthe_server *server) void focus_next(struct absinthe_server *server)
{ {
struct absinthe_toplevel *toplevel = focus_get_topmost(server); struct absinthe_toplevel *toplevel = focus_get_topmost(server);
struct absinthe_toplevel *next; struct absinthe_toplevel *next;
wl_list_for_each(next, &toplevel->link, link) { wl_list_for_each(next, &toplevel->link, link) {
if (&next->link == &toplevel->server->toplevels) if (&next->link == &toplevel->server->toplevels)
continue; continue;
break; break;
} }
focus_toplevel(next); focus_toplevel(next);
} }
void focus_prev(struct absinthe_server *server) void focus_prev(struct absinthe_server *server)
{ {
struct absinthe_toplevel *toplevel = focus_get_topmost(server); struct absinthe_toplevel *toplevel = focus_get_topmost(server);
struct absinthe_toplevel *prev; struct absinthe_toplevel *prev;
wl_list_for_each_reverse(prev, &toplevel->link, link) { wl_list_for_each_reverse(prev, &toplevel->link, link) {
if (&prev->link == &toplevel->server->toplevels) if (&prev->link == &toplevel->server->toplevels)
continue; continue;
break; break;
} }
focus_toplevel(prev); focus_toplevel(prev);
} }
+75 -75
View File
@@ -13,97 +13,97 @@
void keyboard_handle_modifiers(struct wl_listener *listener, void *data) void keyboard_handle_modifiers(struct wl_listener *listener, void *data)
{ {
struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, modifiers); struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, modifiers);
wlr_seat_set_keyboard(keyboard->server->seat, keyboard->wlr_keyboard); wlr_seat_set_keyboard(keyboard->server->seat, keyboard->wlr_keyboard);
wlr_seat_keyboard_notify_modifiers(keyboard->server->seat, &keyboard->wlr_keyboard->modifiers); wlr_seat_keyboard_notify_modifiers(keyboard->server->seat, &keyboard->wlr_keyboard->modifiers);
} }
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)
{ {
switch (keysym) { switch (keysym) {
case XKB_KEY_Escape: case XKB_KEY_Escape:
wl_display_terminate(server->display); wl_display_terminate(server->display);
break; break;
case XKB_KEY_Return: case XKB_KEY_Return:
if (fork() == 0) if (fork() == 0)
execl("/bin/sh", "sh", "-c", "foot", NULL); execl("/bin/sh", "sh", "-c", "foot", NULL);
break; break;
case XKB_KEY_r: case XKB_KEY_r:
if (fork() == 0) if (fork() == 0)
execl("/bin/sh", "sh", "-c", "wofi --show drun", NULL); execl("/bin/sh", "sh", "-c", "wofi --show drun", NULL);
break; break;
case XKB_KEY_f: case XKB_KEY_f:
if (server->focused_toplevel) if (server->focused_toplevel)
absinthe_toplevel_set_fullscreen(server->focused_toplevel, !server->focused_toplevel->fullscreen); absinthe_toplevel_set_fullscreen(server->focused_toplevel, !server->focused_toplevel->fullscreen);
break; break;
case XKB_KEY_j: case XKB_KEY_j:
focus_next(server); focus_next(server);
break; break;
case XKB_KEY_k: case XKB_KEY_k:
focus_prev(server); focus_prev(server);
break; break;
case XKB_KEY_h: case XKB_KEY_h:
if (server->focused_output && server->focused_output->main_stack_width > 0.15) { if (server->focused_output && server->focused_output->main_stack_width > 0.15) {
server->focused_output->main_stack_width -= 0.1; server->focused_output->main_stack_width -= 0.1;
layout_arrange(server->focused_output); layout_arrange(server->focused_output);
} }
break; break;
case XKB_KEY_l: case XKB_KEY_l:
if (server->focused_output && server->focused_output->main_stack_width < 0.9) { if (server->focused_output && server->focused_output->main_stack_width < 0.9) {
server->focused_output->main_stack_width += 0.1; server->focused_output->main_stack_width += 0.1;
layout_arrange(server->focused_output); layout_arrange(server->focused_output);
} }
break; break;
case XKB_KEY_H: case XKB_KEY_H:
if (server->focused_output) { if (server->focused_output) {
server->focused_output->main_stack_size += 1; server->focused_output->main_stack_size += 1;
layout_arrange(server->focused_output); layout_arrange(server->focused_output);
} }
break; break;
case XKB_KEY_L: case XKB_KEY_L:
if (server->focused_output && server->focused_output->main_stack_size > 1) { if (server->focused_output && server->focused_output->main_stack_size > 1) {
server->focused_output->main_stack_size -= 1; server->focused_output->main_stack_size -= 1;
layout_arrange(server->focused_output); layout_arrange(server->focused_output);
} }
break; break;
default: default:
return false; return false;
} }
return true; return true;
} }
void keyboard_handle_key(struct wl_listener *listener, void *data) void keyboard_handle_key(struct wl_listener *listener, void *data)
{ {
struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, key);
struct wlr_keyboard_key_event *event = data; struct wlr_keyboard_key_event *event = data;
uint32_t keycode = event->keycode + 8; uint32_t keycode = event->keycode + 8;
uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->wlr_keyboard); uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->wlr_keyboard);
const xkb_keysym_t *syms; const xkb_keysym_t *syms;
int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms);
bool handled = false; bool handled = false;
if ((modifiers & WLR_MODIFIER_ALT) && (event->state == WL_KEYBOARD_KEY_STATE_PRESSED)) { if ((modifiers & WLR_MODIFIER_ALT) && (event->state == WL_KEYBOARD_KEY_STATE_PRESSED)) {
for (int i = 0; i < nsyms; ++i) { for (int i = 0; i < nsyms; ++i) {
handled = keyboard_handle_keybind(keyboard->server, syms[i]); handled = keyboard_handle_keybind(keyboard->server, syms[i]);
} }
} }
if (!handled) { if (!handled) {
wlr_seat_set_keyboard(keyboard->server->seat, keyboard->wlr_keyboard); wlr_seat_set_keyboard(keyboard->server->seat, keyboard->wlr_keyboard);
wlr_seat_keyboard_notify_key(keyboard->server->seat, event->time_msec, event->keycode, event->state); wlr_seat_keyboard_notify_key(keyboard->server->seat, event->time_msec, event->keycode, event->state);
} }
} }
void keyboard_handle_destroy(struct wl_listener *listener, void *data) void keyboard_handle_destroy(struct wl_listener *listener, void *data)
{ {
struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, modifiers); struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, modifiers);
wl_list_remove(&keyboard->modifiers.link); wl_list_remove(&keyboard->modifiers.link);
wl_list_remove(&keyboard->key.link); wl_list_remove(&keyboard->key.link);
wl_list_remove(&keyboard->destroy.link); wl_list_remove(&keyboard->destroy.link);
wl_list_remove(&keyboard->link); wl_list_remove(&keyboard->link);
free(keyboard); free(keyboard);
} }
+66 -66
View File
@@ -3,81 +3,81 @@
void layout_arrange(struct absinthe_output *output) void layout_arrange(struct absinthe_output *output)
{ {
if (!output) if (!output)
return; return;
struct absinthe_toplevel *toplevel; struct absinthe_toplevel *toplevel;
size_t toplevels_count = 0; size_t toplevels_count = 0;
wl_list_for_each(toplevel, &output->server->toplevels, link) { wl_list_for_each(toplevel, &output->server->toplevels, link) {
if (toplevel->tiled && toplevel->output == output) { if (toplevel->tiled && toplevel->output == output) {
toplevels_count++; toplevels_count++;
wlr_scene_node_set_enabled(&toplevel->scene_tree->node, true); wlr_scene_node_set_enabled(&toplevel->scene_tree->node, true);
} }
} }
if (toplevels_count < 1) if (toplevels_count < 1)
return; return;
int32_t output_gap = ABSINTHE_OUTPUT_GAP; int32_t output_gap = ABSINTHE_OUTPUT_GAP;
if (toplevels_count == 1) { if (toplevels_count == 1) {
wl_list_for_each(toplevel, &output->server->toplevels, link) { wl_list_for_each(toplevel, &output->server->toplevels, link) {
if (toplevel->output == output) if (toplevel->output == output)
break; break;
} }
toplevel->geometry.x = output->geometry.x + output_gap; toplevel->geometry.x = output->geometry.x + output_gap;
toplevel->geometry.y = output->geometry.y + output_gap; toplevel->geometry.y = output->geometry.y + output_gap;
absinthe_toplevel_set_size(toplevel, absinthe_toplevel_set_size(toplevel,
output->geometry.width - 2 * output_gap, output->geometry.width - 2 * output_gap,
output->geometry.height - 2 * output_gap); output->geometry.height - 2 * output_gap);
return; return;
} }
int32_t layout_gap = ABSINTHE_LAYOUT_GAP; int32_t layout_gap = ABSINTHE_LAYOUT_GAP;
int32_t main_stack_width = (toplevels_count <= output->main_stack_size) int32_t main_stack_width = (toplevels_count <= output->main_stack_size)
? output->geometry.width - 2 * output_gap ? output->geometry.width - 2 * output_gap
: output->main_stack_width * (output->geometry.width - 2 * output_gap); : output->main_stack_width * (output->geometry.width - 2 * output_gap);
int32_t width = output->geometry.width - main_stack_width - 2 * output_gap - layout_gap; int32_t width = output->geometry.width - main_stack_width - 2 * output_gap - layout_gap;
int32_t height; int32_t height;
int32_t dy = output_gap; int32_t dy = output_gap;
size_t i = 0; size_t i = 0;
if (toplevels_count <= output->main_stack_size) { if (toplevels_count <= output->main_stack_size) {
wl_list_for_each(toplevel, &output->server->toplevels, link) { wl_list_for_each(toplevel, &output->server->toplevels, link) {
if (toplevel->output != output || !toplevel->tiled) if (toplevel->output != output || !toplevel->tiled)
continue; continue;
height = (output->geometry.height - dy - output_gap) / (toplevels_count - i); height = (output->geometry.height - dy - output_gap) / (toplevels_count - i);
toplevel->geometry.x = output->geometry.x + output_gap; toplevel->geometry.x = output->geometry.x + output_gap;
toplevel->geometry.y = output->geometry.y + dy; toplevel->geometry.y = output->geometry.y + dy;
absinthe_toplevel_set_size(toplevel, main_stack_width, height); absinthe_toplevel_set_size(toplevel, main_stack_width, height);
dy += height + layout_gap; dy += height + layout_gap;
i++; i++;
} }
return; return;
} }
wl_list_for_each(toplevel, &output->server->toplevels, link) { wl_list_for_each(toplevel, &output->server->toplevels, link) {
if (toplevel->output != output || !toplevel->tiled) if (toplevel->output != output || !toplevel->tiled)
continue; continue;
if (i < output->main_stack_size) { if (i < output->main_stack_size) {
height = (output->geometry.height - dy - output_gap) / (output->main_stack_size - i); height = (output->geometry.height - dy - output_gap) / (output->main_stack_size - i);
toplevel->geometry.x = output->geometry.x + output_gap; toplevel->geometry.x = output->geometry.x + output_gap;
toplevel->geometry.y = output->geometry.y + dy; toplevel->geometry.y = output->geometry.y + dy;
absinthe_toplevel_set_size(toplevel, main_stack_width, height); absinthe_toplevel_set_size(toplevel, main_stack_width, height);
dy += height + layout_gap; dy += height + layout_gap;
} else { } else {
if (i == output->main_stack_size) if (i == output->main_stack_size)
dy = output_gap; dy = output_gap;
height = (output->geometry.height - dy - output_gap) / (toplevels_count - i); height = (output->geometry.height - dy - output_gap) / (toplevels_count - i);
toplevel->geometry.x = output->geometry.x + main_stack_width + layout_gap + output_gap; toplevel->geometry.x = output->geometry.x + main_stack_width + layout_gap + output_gap;
toplevel->geometry.y = output->geometry.y + dy; toplevel->geometry.y = output->geometry.y + dy;
absinthe_toplevel_set_size(toplevel, width, height); absinthe_toplevel_set_size(toplevel, width, height);
dy += height + layout_gap; dy += height + layout_gap;
} }
i++; i++;
} }
} }
+134 -134
View File
@@ -24,174 +24,174 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
wlr_log_init(WLR_DEBUG, NULL); wlr_log_init(WLR_DEBUG, NULL);
struct absinthe_server server = {0}; struct absinthe_server server = {0};
server.display = wl_display_create(); server.display = wl_display_create();
if (!server.display) { if (!server.display) {
wlr_log(WLR_ERROR, "Failed to create wl_display"); wlr_log(WLR_ERROR, "Failed to create wl_display");
return 1; return 1;
} }
server.backend = wlr_backend_autocreate(wl_display_get_event_loop(server.display), NULL); server.backend = wlr_backend_autocreate(wl_display_get_event_loop(server.display), NULL);
if (!server.backend) { if (!server.backend) {
wlr_log(WLR_ERROR, "Failed to create wlr_backend"); wlr_log(WLR_ERROR, "Failed to create wlr_backend");
return 1; return 1;
} }
server.renderer = wlr_renderer_autocreate(server.backend); server.renderer = wlr_renderer_autocreate(server.backend);
if (!server.renderer) { if (!server.renderer) {
wlr_log(WLR_ERROR, "Failed to create wlr_renderer"); wlr_log(WLR_ERROR, "Failed to create wlr_renderer");
return 1; return 1;
} }
wlr_renderer_init_wl_shm(server.renderer, server.display); wlr_renderer_init_wl_shm(server.renderer, server.display);
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.allocator = wlr_allocator_autocreate(server.backend, server.renderer); server.allocator = wlr_allocator_autocreate(server.backend, server.renderer);
if (!server.allocator) { if (!server.allocator) {
wlr_log(WLR_ERROR, "Failed to create wlr_allocator"); wlr_log(WLR_ERROR, "Failed to create wlr_allocator");
return 1; return 1;
} }
server.compositor = wlr_compositor_create(server.display, 6, server.renderer); server.compositor = wlr_compositor_create(server.display, 6, server.renderer);
wlr_subcompositor_create(server.display); wlr_subcompositor_create(server.display);
wlr_data_device_manager_create(server.display); wlr_data_device_manager_create(server.display);
wlr_screencopy_manager_v1_create(server.display); wlr_screencopy_manager_v1_create(server.display);
wlr_data_control_manager_v1_create(server.display); wlr_data_control_manager_v1_create(server.display);
wlr_viewporter_create(server.display); wlr_viewporter_create(server.display);
wlr_single_pixel_buffer_manager_v1_create(server.display); wlr_single_pixel_buffer_manager_v1_create(server.display);
wlr_fractional_scale_manager_v1_create(server.display, 1); wlr_fractional_scale_manager_v1_create(server.display, 1);
wlr_presentation_create(server.display, server.backend, 2); wlr_presentation_create(server.display, server.backend, 2);
wlr_alpha_modifier_v1_create(server.display); wlr_alpha_modifier_v1_create(server.display);
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_set_default_mode(
wlr_server_decoration_manager_create(server.display), wlr_server_decoration_manager_create(server.display),
WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
server.xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(server.display); server.xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(server.display);
server.new_xdg_decoration.notify = server_new_xdg_decoration; server.new_xdg_decoration.notify = server_new_xdg_decoration;
wl_signal_add(&server.xdg_decoration_mgr->events.new_toplevel_decoration, &server.new_xdg_decoration); wl_signal_add(&server.xdg_decoration_mgr->events.new_toplevel_decoration, &server.new_xdg_decoration);
wl_list_init(&server.outputs); wl_list_init(&server.outputs);
server.new_output.notify = server_new_output; server.new_output.notify = server_new_output;
wl_signal_add(&server.backend->events.new_output, &server.new_output); wl_signal_add(&server.backend->events.new_output, &server.new_output);
server.output_layout = wlr_output_layout_create(server.display); server.output_layout = wlr_output_layout_create(server.display);
server.output_layout_change.notify = outputs_update; server.output_layout_change.notify = outputs_update;
wl_signal_add(&server.output_layout->events.change, &server.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); server.output_mgr = wlr_output_manager_v1_create(server.display);
wlr_xdg_output_manager_v1_create(server.display, server.output_layout); wlr_xdg_output_manager_v1_create(server.display, server.output_layout);
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); wl_list_init(&server.focus_stack);
server.xdg_shell = wlr_xdg_shell_create(server.display, 6); server.xdg_shell = wlr_xdg_shell_create(server.display, 6);
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);
server.new_xdg_popup.notify = server_new_xdg_popup; server.new_xdg_popup.notify = server_new_xdg_popup;
wl_signal_add(&server.xdg_shell->events.new_popup, &server.new_xdg_popup); wl_signal_add(&server.xdg_shell->events.new_popup, &server.new_xdg_popup);
server.cursor = wlr_cursor_create(); server.cursor = wlr_cursor_create();
wlr_cursor_attach_output_layout(server.cursor, server.output_layout); wlr_cursor_attach_output_layout(server.cursor, server.output_layout);
server.cursor_mgr = wlr_xcursor_manager_create(NULL, 24); server.cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
server.cursor_mode = ABSINTHE_CURSOR_PASSTHROUGH; server.cursor_mode = ABSINTHE_CURSOR_PASSTHROUGH;
server.cursor_motion.notify = server_cursor_motion; server.cursor_motion.notify = server_cursor_motion;
wl_signal_add(&server.cursor->events.motion, &server.cursor_motion); wl_signal_add(&server.cursor->events.motion, &server.cursor_motion);
server.cursor_motion_absolute.notify = server_cursor_motion_absolute; server.cursor_motion_absolute.notify = server_cursor_motion_absolute;
wl_signal_add(&server.cursor->events.motion_absolute, &server.cursor_motion_absolute); wl_signal_add(&server.cursor->events.motion_absolute, &server.cursor_motion_absolute);
server.cursor_button.notify = server_cursor_button; server.cursor_button.notify = server_cursor_button;
wl_signal_add(&server.cursor->events.button, &server.cursor_button); wl_signal_add(&server.cursor->events.button, &server.cursor_button);
server.cursor_axis.notify = server_cursor_axis; server.cursor_axis.notify = server_cursor_axis;
wl_signal_add(&server.cursor->events.axis, &server.cursor_axis); wl_signal_add(&server.cursor->events.axis, &server.cursor_axis);
server.cursor_frame.notify = server_cursor_frame; server.cursor_frame.notify = server_cursor_frame;
wl_signal_add(&server.cursor->events.frame, &server.cursor_frame); wl_signal_add(&server.cursor->events.frame, &server.cursor_frame);
wl_list_init(&server.keyboards); wl_list_init(&server.keyboards);
server.new_input.notify = server_new_input; server.new_input.notify = server_new_input;
wl_signal_add(&server.backend->events.new_input, &server.new_input); wl_signal_add(&server.backend->events.new_input, &server.new_input);
server.seat = wlr_seat_create(server.display, "seat0"); server.seat = wlr_seat_create(server.display, "seat0");
server.request_cursor.notify = seat_request_cursor; server.request_cursor.notify = seat_request_cursor;
wl_signal_add(&server.seat->events.request_set_cursor, &server.request_cursor); wl_signal_add(&server.seat->events.request_set_cursor, &server.request_cursor);
server.pointer_focus_change.notify = seat_pointer_focus_change; server.pointer_focus_change.notify = seat_pointer_focus_change;
wl_signal_add(&server.seat->pointer_state.events.focus_change, &server.pointer_focus_change); wl_signal_add(&server.seat->pointer_state.events.focus_change, &server.pointer_focus_change);
server.request_set_selection.notify = seat_request_set_selection; server.request_set_selection.notify = seat_request_set_selection;
wl_signal_add(&server.seat->events.request_set_selection, &server.request_set_selection); wl_signal_add(&server.seat->events.request_set_selection, &server.request_set_selection);
unsetenv("DISPLAY"); unsetenv("DISPLAY");
const char *socket = wl_display_add_socket_auto(server.display); const char *socket = wl_display_add_socket_auto(server.display);
if (!socket) { if (!socket) {
wlr_log(WLR_ERROR, "Failed to add socket"); wlr_log(WLR_ERROR, "Failed to add socket");
wlr_backend_destroy(server.backend); wlr_backend_destroy(server.backend);
return 1; return 1;
} }
if (!wlr_backend_start(server.backend)) { if (!wlr_backend_start(server.backend)) {
wlr_log(WLR_ERROR, "Failed to start wlr_backend"); wlr_log(WLR_ERROR, "Failed to start wlr_backend");
wlr_backend_destroy(server.backend); wlr_backend_destroy(server.backend);
wl_display_destroy(server.display); wl_display_destroy(server.display);
return 1; return 1;
} }
#ifdef XWAYLAND #ifdef XWAYLAND
if ((server.xwayland = wlr_xwayland_create(server.display, server.compositor, 1))) { if ((server.xwayland = wlr_xwayland_create(server.display, server.compositor, 1))) {
server.xwayland_ready.notify = server_xwayland_ready; server.xwayland_ready.notify = server_xwayland_ready;
wl_signal_add(&server.xwayland->events.ready, &server.xwayland_ready); wl_signal_add(&server.xwayland->events.ready, &server.xwayland_ready);
server.xwayland_new_surface.notify = server_xwayland_new_surface; server.xwayland_new_surface.notify = server_xwayland_new_surface;
wl_signal_add(&server.xwayland->events.new_surface, &server.xwayland_new_surface); wl_signal_add(&server.xwayland->events.new_surface, &server.xwayland_new_surface);
setenv("DISPLAY", server.xwayland->display_name, 1); setenv("DISPLAY", server.xwayland->display_name, 1);
wlr_log(WLR_INFO, "Running XWayland, DISPLAY=%s", server.xwayland->display_name); wlr_log(WLR_INFO, "Running XWayland, DISPLAY=%s", server.xwayland->display_name);
} else { } else {
wlr_log(WLR_ERROR, "Failed to setup XWayland, continuing without it"); wlr_log(WLR_ERROR, "Failed to setup XWayland, continuing without it");
} }
#endif #endif
setenv("WAYLAND_DISPLAY", socket, true); setenv("WAYLAND_DISPLAY", socket, true);
wlr_log(WLR_INFO, "Running absinthe on WAYLAND_DISPLAY=%s", socket); wlr_log(WLR_INFO, "Running absinthe on WAYLAND_DISPLAY=%s", socket);
wl_display_run(server.display); wl_display_run(server.display);
wl_display_destroy_clients(server.display); wl_display_destroy_clients(server.display);
wl_list_remove(&server.new_xdg_toplevel.link); wl_list_remove(&server.new_xdg_toplevel.link);
wl_list_remove(&server.new_xdg_popup.link); wl_list_remove(&server.new_xdg_popup.link);
wl_list_remove(&server.new_xdg_decoration.link); wl_list_remove(&server.new_xdg_decoration.link);
wl_list_remove(&server.cursor_motion.link); wl_list_remove(&server.cursor_motion.link);
wl_list_remove(&server.cursor_motion_absolute.link); wl_list_remove(&server.cursor_motion_absolute.link);
wl_list_remove(&server.cursor_button.link); wl_list_remove(&server.cursor_button.link);
wl_list_remove(&server.cursor_axis.link); wl_list_remove(&server.cursor_axis.link);
wl_list_remove(&server.cursor_frame.link); wl_list_remove(&server.cursor_frame.link);
wl_list_remove(&server.new_input.link); wl_list_remove(&server.new_input.link);
wl_list_remove(&server.request_cursor.link); wl_list_remove(&server.request_cursor.link);
wl_list_remove(&server.pointer_focus_change.link); wl_list_remove(&server.pointer_focus_change.link);
wl_list_remove(&server.request_set_selection.link); wl_list_remove(&server.request_set_selection.link);
wl_list_remove(&server.new_output.link); wl_list_remove(&server.new_output.link);
wlr_scene_node_destroy(&server.scene->tree.node); wlr_scene_node_destroy(&server.scene->tree.node);
wlr_xcursor_manager_destroy(server.cursor_mgr); wlr_xcursor_manager_destroy(server.cursor_mgr);
wlr_cursor_destroy(server.cursor); wlr_cursor_destroy(server.cursor);
wlr_allocator_destroy(server.allocator); wlr_allocator_destroy(server.allocator);
wlr_renderer_destroy(server.renderer); wlr_renderer_destroy(server.renderer);
wlr_backend_destroy(server.backend); wlr_backend_destroy(server.backend);
wl_display_destroy(server.display); wl_display_destroy(server.display);
return 0; return 0;
} }
+33 -33
View File
@@ -6,64 +6,64 @@
void output_frame(struct wl_listener *listener, void *data) void output_frame(struct wl_listener *listener, void *data)
{ {
struct absinthe_output *output = wl_container_of(listener, output, frame); struct absinthe_output *output = wl_container_of(listener, output, frame);
struct wlr_scene *scene = output->server->scene; struct wlr_scene *scene = output->server->scene;
struct wlr_scene_output *scene_output = wlr_scene_get_scene_output(scene, output->wlr_output); struct wlr_scene_output *scene_output = wlr_scene_get_scene_output(scene, output->wlr_output);
struct absinthe_toplevel *toplevel; struct absinthe_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->output == output)
goto skip; goto skip;
} }
wlr_scene_output_commit(scene_output, NULL); wlr_scene_output_commit(scene_output, NULL);
skip: skip:
struct timespec now; struct timespec now;
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);
} }
void output_request_state(struct wl_listener *listener, void *data) void output_request_state(struct wl_listener *listener, void *data)
{ {
struct absinthe_output *output = wl_container_of(listener, output, request_state); struct absinthe_output *output = wl_container_of(listener, output, request_state);
const struct wlr_output_event_request_state *event = data; const struct wlr_output_event_request_state *event = data;
wlr_output_commit_state(output->wlr_output, event->state); wlr_output_commit_state(output->wlr_output, event->state);
} }
void output_destroy(struct wl_listener *listener, void *data) void output_destroy(struct wl_listener *listener, void *data)
{ {
struct absinthe_output *output = wl_container_of(listener, output, request_state); struct absinthe_output *output = wl_container_of(listener, output, request_state);
wl_list_remove(&output->frame.link); wl_list_remove(&output->frame.link);
wl_list_remove(&output->request_state.link); wl_list_remove(&output->request_state.link);
wl_list_remove(&output->destroy.link); wl_list_remove(&output->destroy.link);
wl_list_remove(&output->link); wl_list_remove(&output->link);
free(output); free(output);
} }
void outputs_update(struct wl_listener *listener, void *data) void outputs_update(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, output_layout_change); struct absinthe_server *server = wl_container_of(listener, server, output_layout_change);
struct absinthe_output *output; struct absinthe_output *output;
wl_list_for_each(output, &server->outputs, link) { wl_list_for_each(output, &server->outputs, link) {
wlr_output_layout_get_box(server->output_layout, output->wlr_output, &output->geometry); wlr_output_layout_get_box(server->output_layout, output->wlr_output, &output->geometry);
} }
} }
void update_focused_output(struct absinthe_server *server) void update_focused_output(struct absinthe_server *server)
{ {
struct absinthe_output *output; struct absinthe_output *output;
int32_t cursor_x = server->cursor->x; int32_t cursor_x = server->cursor->x;
int32_t cursor_y = server->cursor->y; int32_t cursor_y = server->cursor->y;
wl_list_for_each(output, &server->outputs, link) { wl_list_for_each(output, &server->outputs, link) {
bool cursor_in_output_x = cursor_x >= output->geometry.x && cursor_x <= output->geometry.x + output->geometry.width; bool cursor_in_output_x = cursor_x >= output->geometry.x && cursor_x <= output->geometry.x + output->geometry.width;
bool cursor_in_output_y = cursor_y >= output->geometry.y && cursor_y <= output->geometry.y + output->geometry.height; bool cursor_in_output_y = cursor_y >= output->geometry.y && cursor_y <= output->geometry.y + output->geometry.height;
if (cursor_in_output_x && cursor_in_output_y) { if (cursor_in_output_x && cursor_in_output_y) {
server->focused_output = output; server->focused_output = output;
break; break;
} }
} }
} }
+12 -12
View File
@@ -5,27 +5,27 @@
void seat_request_cursor(struct wl_listener *listener, void *data) void seat_request_cursor(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, request_cursor); struct absinthe_server *server = wl_container_of(listener, server, request_cursor);
struct wlr_seat_pointer_request_set_cursor_event *event = data; struct wlr_seat_pointer_request_set_cursor_event *event = data;
struct wlr_seat_client *client = server->seat->pointer_state.focused_client; struct wlr_seat_client *client = server->seat->pointer_state.focused_client;
if (client == event->seat_client) if (client == event->seat_client)
wlr_cursor_set_surface(server->cursor, event->surface, event->hotspot_x, event->hotspot_y); wlr_cursor_set_surface(server->cursor, event->surface, event->hotspot_x, event->hotspot_y);
} }
void seat_pointer_focus_change(struct wl_listener *listener, void *data) void seat_pointer_focus_change(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, pointer_focus_change); struct absinthe_server *server = wl_container_of(listener, server, pointer_focus_change);
struct wlr_seat_pointer_focus_change_event *event = data; struct wlr_seat_pointer_focus_change_event *event = data;
if (!event->new_surface) if (!event->new_surface)
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "default"); wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "default");
} }
void seat_request_set_selection(struct wl_listener *listener, void *data) void seat_request_set_selection(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, request_set_selection); struct absinthe_server *server = wl_container_of(listener, server, request_set_selection);
struct wlr_seat_request_set_selection_event *event = data; struct wlr_seat_request_set_selection_event *event = data;
wlr_seat_set_selection(server->seat, event->source, event->serial); wlr_seat_set_selection(server->seat, event->source, event->serial);
} }
+208 -208
View File
@@ -22,310 +22,310 @@
void server_new_output(struct wl_listener *listener, void *data) void server_new_output(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, new_output); struct absinthe_server *server = wl_container_of(listener, server, new_output);
struct wlr_output *wlr_output = data; struct wlr_output *wlr_output = data;
wlr_output_init_render(wlr_output, server->allocator, server->renderer); wlr_output_init_render(wlr_output, server->allocator, server->renderer);
struct wlr_output_state state; struct wlr_output_state state;
wlr_output_state_init(&state); wlr_output_state_init(&state);
wlr_output_state_set_enabled(&state, true); wlr_output_state_set_enabled(&state, true);
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
if (mode) if (mode)
wlr_output_state_set_mode(&state, mode); wlr_output_state_set_mode(&state, mode);
wlr_output_commit_state(wlr_output, &state); wlr_output_commit_state(wlr_output, &state);
wlr_output_state_finish(&state); wlr_output_state_finish(&state);
struct absinthe_output *output = calloc(1, sizeof(*output)); struct absinthe_output *output = calloc(1, sizeof(*output));
output->wlr_output = wlr_output; output->wlr_output = wlr_output;
output->server = server; output->server = server;
output->frame.notify = output_frame; output->frame.notify = output_frame;
wl_signal_add(&wlr_output->events.frame, &output->frame); wl_signal_add(&wlr_output->events.frame, &output->frame);
output->request_state.notify = output_request_state; output->request_state.notify = output_request_state;
wl_signal_add(&wlr_output->events.request_state, &output->request_state); wl_signal_add(&wlr_output->events.request_state, &output->request_state);
output->destroy.notify = output_destroy; output->destroy.notify = output_destroy;
wl_signal_add(&wlr_output->events.destroy, &output->destroy); wl_signal_add(&wlr_output->events.destroy, &output->destroy);
wl_list_insert(&server->outputs, &output->link); wl_list_insert(&server->outputs, &output->link);
struct wlr_output_layout_output *l_layout = wlr_output_layout_add_auto(server->output_layout, output->wlr_output); struct wlr_output_layout_output *l_layout = wlr_output_layout_add_auto(server->output_layout, output->wlr_output);
struct wlr_scene_output *scene_output = wlr_scene_output_create(server->scene, wlr_output); struct wlr_scene_output *scene_output = wlr_scene_output_create(server->scene, wlr_output);
wlr_scene_output_layout_add_output(server->scene_layout, l_layout, scene_output); wlr_scene_output_layout_add_output(server->scene_layout, l_layout, scene_output);
wlr_output_layout_get_box(server->output_layout, output->wlr_output, &output->geometry); wlr_output_layout_get_box(server->output_layout, output->wlr_output, &output->geometry);
output->main_stack_size = ABSINTHE_MAIN_STACK_SIZE; output->main_stack_size = ABSINTHE_MAIN_STACK_SIZE;
output->main_stack_width = ABSINTHE_MAIN_STACK_WIDTH; output->main_stack_width = ABSINTHE_MAIN_STACK_WIDTH;
} }
void server_new_xdg_toplevel(struct wl_listener *listener, void *data) void server_new_xdg_toplevel(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, new_xdg_toplevel); struct absinthe_server *server = wl_container_of(listener, server, new_xdg_toplevel);
struct wlr_xdg_toplevel *xdg_toplevel = data; struct wlr_xdg_toplevel *xdg_toplevel = data;
struct absinthe_toplevel *toplevel = calloc(1, sizeof(*toplevel)); struct absinthe_toplevel *toplevel = calloc(1, sizeof(*toplevel));
toplevel->type = ABSINTHE_TOPLEVEL_XDG; toplevel->type = ABSINTHE_TOPLEVEL_XDG;
toplevel->server = server; toplevel->server = server;
toplevel->toplevel.xdg = xdg_toplevel; toplevel->toplevel.xdg = xdg_toplevel;
toplevel->toplevel.xdg->base->data = toplevel; toplevel->toplevel.xdg->base->data = toplevel;
toplevel->commit.notify = xdg_toplevel_commit; toplevel->commit.notify = xdg_toplevel_commit;
wl_signal_add(&xdg_toplevel->base->surface->events.commit, &toplevel->commit); wl_signal_add(&xdg_toplevel->base->surface->events.commit, &toplevel->commit);
toplevel->map.notify = absinthe_toplevel_map; toplevel->map.notify = absinthe_toplevel_map;
wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map); wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map);
toplevel->unmap.notify = absinthe_toplevel_unmap; toplevel->unmap.notify = absinthe_toplevel_unmap;
wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap); wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap);
toplevel->destroy.notify = absinthe_toplevel_destroy; toplevel->destroy.notify = absinthe_toplevel_destroy;
wl_signal_add(&xdg_toplevel->events.destroy, &toplevel->destroy); wl_signal_add(&xdg_toplevel->events.destroy, &toplevel->destroy);
toplevel->request_move.notify = absinthe_toplevel_request_move; toplevel->request_move.notify = absinthe_toplevel_request_move;
wl_signal_add(&xdg_toplevel->events.request_move, &toplevel->request_move); wl_signal_add(&xdg_toplevel->events.request_move, &toplevel->request_move);
toplevel->request_resize.notify = absinthe_toplevel_request_resize; toplevel->request_resize.notify = absinthe_toplevel_request_resize;
wl_signal_add(&xdg_toplevel->events.request_resize, &toplevel->request_resize); wl_signal_add(&xdg_toplevel->events.request_resize, &toplevel->request_resize);
toplevel->request_maximize.notify = absinthe_toplevel_request_maximize; toplevel->request_maximize.notify = absinthe_toplevel_request_maximize;
wl_signal_add(&xdg_toplevel->events.request_maximize, &toplevel->request_maximize); wl_signal_add(&xdg_toplevel->events.request_maximize, &toplevel->request_maximize);
toplevel->request_fullscreen.notify = absinthe_toplevel_request_fullscreen; toplevel->request_fullscreen.notify = absinthe_toplevel_request_fullscreen;
wl_signal_add(&xdg_toplevel->events.request_fullscreen, &toplevel->request_fullscreen); wl_signal_add(&xdg_toplevel->events.request_fullscreen, &toplevel->request_fullscreen);
} }
void server_new_xdg_popup(struct wl_listener *listener, void *data) void server_new_xdg_popup(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, new_xdg_popup); struct absinthe_server *server = wl_container_of(listener, server, new_xdg_popup);
struct wlr_xdg_popup *xdg_popup = data; struct wlr_xdg_popup *xdg_popup = data;
struct absinthe_popup *popup = calloc(1, sizeof(*popup)); struct absinthe_popup *popup = calloc(1, sizeof(*popup));
popup->xdg_popup = xdg_popup; popup->xdg_popup = xdg_popup;
struct wlr_xdg_surface *parent = wlr_xdg_surface_try_from_wlr_surface(xdg_popup->parent); struct wlr_xdg_surface *parent = wlr_xdg_surface_try_from_wlr_surface(xdg_popup->parent);
struct absinthe_toplevel *parent_toplevel = parent->data; struct absinthe_toplevel *parent_toplevel = parent->data;
struct wlr_scene_tree *parent_tree = parent_toplevel->scene_tree; struct wlr_scene_tree *parent_tree = parent_toplevel->scene_tree;
xdg_popup->base->data = wlr_scene_xdg_surface_create(parent_tree, xdg_popup->base); xdg_popup->base->data = wlr_scene_xdg_surface_create(parent_tree, xdg_popup->base);
popup->commit.notify = xdg_popup_commit; popup->commit.notify = xdg_popup_commit;
wl_signal_add(&xdg_popup->base->surface->events.commit, &popup->commit); wl_signal_add(&xdg_popup->base->surface->events.commit, &popup->commit);
popup->destroy.notify = xdg_popup_destroy; popup->destroy.notify = xdg_popup_destroy;
wl_signal_add(&xdg_popup->base->surface->events.destroy, &popup->destroy); wl_signal_add(&xdg_popup->base->surface->events.destroy, &popup->destroy);
} }
void server_new_xdg_decoration(struct wl_listener *listener, void *data) void server_new_xdg_decoration(struct wl_listener *listener, void *data)
{ {
struct wlr_xdg_toplevel_decoration_v1 *xdg_decoration = data; struct wlr_xdg_toplevel_decoration_v1 *xdg_decoration = data;
struct absinthe_toplevel *toplevel = xdg_decoration->toplevel->base->data; struct absinthe_toplevel *toplevel = xdg_decoration->toplevel->base->data;
toplevel->decoration = xdg_decoration; toplevel->decoration = xdg_decoration;
toplevel->decoration_request_mode.notify = xdg_decoration_request_mode; toplevel->decoration_request_mode.notify = xdg_decoration_request_mode;
wl_signal_add(&xdg_decoration->events.request_mode, &toplevel->decoration_request_mode); wl_signal_add(&xdg_decoration->events.request_mode, &toplevel->decoration_request_mode);
toplevel->decoration_destroy.notify = xdg_decoration_destroy; toplevel->decoration_destroy.notify = xdg_decoration_destroy;
wl_signal_add(&xdg_decoration->events.destroy, &toplevel->decoration_destroy); wl_signal_add(&xdg_decoration->events.destroy, &toplevel->decoration_destroy);
/* Forse server side decoration mode */ /* Forse server side decoration mode */
xdg_decoration_request_mode(&toplevel->decoration_request_mode, toplevel->decoration); xdg_decoration_request_mode(&toplevel->decoration_request_mode, toplevel->decoration);
} }
#ifdef XWAYLAND #ifdef XWAYLAND
void server_xwayland_ready(struct wl_listener *listener, void *data) void server_xwayland_ready(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, xwayland_ready); struct absinthe_server *server = wl_container_of(listener, server, xwayland_ready);
wlr_xwayland_set_seat(server->xwayland, server->seat); wlr_xwayland_set_seat(server->xwayland, server->seat);
struct wlr_xcursor *xcursor; struct wlr_xcursor *xcursor;
if ((xcursor = wlr_xcursor_manager_get_xcursor(server->cursor_mgr, "default", 1))) { if ((xcursor = wlr_xcursor_manager_get_xcursor(server->cursor_mgr, "default", 1))) {
struct wlr_buffer *buffer = wlr_xcursor_image_get_buffer(xcursor->images[0]); struct wlr_buffer *buffer = wlr_xcursor_image_get_buffer(xcursor->images[0]);
wlr_xwayland_set_cursor(server->xwayland, buffer, wlr_xwayland_set_cursor(server->xwayland, buffer,
xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y); xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
} }
} }
void server_xwayland_new_surface(struct wl_listener *listener, void *data) void server_xwayland_new_surface(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, xwayland_new_surface); struct absinthe_server *server = wl_container_of(listener, server, xwayland_new_surface);
struct wlr_xwayland_surface *surface = data; struct wlr_xwayland_surface *surface = data;
struct absinthe_toplevel *toplevel = calloc(1, sizeof(*toplevel)); struct absinthe_toplevel *toplevel = calloc(1, sizeof(*toplevel));
toplevel->type = ABSINTHE_TOPLEVEL_X11; toplevel->type = ABSINTHE_TOPLEVEL_X11;
toplevel->server = server; toplevel->server = server;
toplevel->toplevel.x11 = surface; toplevel->toplevel.x11 = surface;
toplevel->border_width = absinthe_toplevel_is_unmanaged(toplevel) toplevel->border_width = absinthe_toplevel_is_unmanaged(toplevel)
? 0 ? 0
: ABSINTHE_TOPLEVEL_BORDER_WIDTH; : ABSINTHE_TOPLEVEL_BORDER_WIDTH;
toplevel->destroy.notify = absinthe_toplevel_destroy; toplevel->destroy.notify = absinthe_toplevel_destroy;
wl_signal_add(&surface->events.destroy, &toplevel->destroy); wl_signal_add(&surface->events.destroy, &toplevel->destroy);
toplevel->request_maximize.notify = absinthe_toplevel_request_maximize; toplevel->request_maximize.notify = absinthe_toplevel_request_maximize;
wl_signal_add(&surface->events.request_maximize, &toplevel->request_maximize); wl_signal_add(&surface->events.request_maximize, &toplevel->request_maximize);
toplevel->request_fullscreen.notify = absinthe_toplevel_request_fullscreen; toplevel->request_fullscreen.notify = absinthe_toplevel_request_fullscreen;
wl_signal_add(&surface->events.request_fullscreen, &toplevel->request_fullscreen); wl_signal_add(&surface->events.request_fullscreen, &toplevel->request_fullscreen);
toplevel->xwayland_activate.notify = xwayland_activate; toplevel->xwayland_activate.notify = xwayland_activate;
wl_signal_add(&surface->events.request_activate, &toplevel->xwayland_activate); wl_signal_add(&surface->events.request_activate, &toplevel->xwayland_activate);
toplevel->xwayland_associate.notify = xwayland_associate; toplevel->xwayland_associate.notify = xwayland_associate;
wl_signal_add(&surface->events.associate, &toplevel->xwayland_associate); wl_signal_add(&surface->events.associate, &toplevel->xwayland_associate);
toplevel->xwayland_dissociate.notify = xwayland_dissociate; toplevel->xwayland_dissociate.notify = xwayland_dissociate;
wl_signal_add(&surface->events.dissociate, &toplevel->xwayland_dissociate); wl_signal_add(&surface->events.dissociate, &toplevel->xwayland_dissociate);
toplevel->xwayland_configure.notify = xwayland_configure; toplevel->xwayland_configure.notify = xwayland_configure;
wl_signal_add(&surface->events.request_configure, &toplevel->xwayland_configure); wl_signal_add(&surface->events.request_configure, &toplevel->xwayland_configure);
toplevel->xwayland_set_hints.notify = xwayland_set_hints; toplevel->xwayland_set_hints.notify = xwayland_set_hints;
wl_signal_add(&surface->events.set_hints, &toplevel->xwayland_set_hints); wl_signal_add(&surface->events.set_hints, &toplevel->xwayland_set_hints);
} }
#endif #endif
void server_cursor_motion(struct wl_listener *listener, void *data) void server_cursor_motion(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, cursor_motion); struct absinthe_server *server = wl_container_of(listener, server, cursor_motion);
struct wlr_pointer_motion_event *event = data; struct wlr_pointer_motion_event *event = data;
update_focused_output(server); update_focused_output(server);
wlr_cursor_move(server->cursor, &event->pointer->base, event->delta_x, event->delta_y); wlr_cursor_move(server->cursor, &event->pointer->base, event->delta_x, event->delta_y);
process_cursor_motion(server, event->time_msec); process_cursor_motion(server, event->time_msec);
} }
void server_cursor_motion_absolute(struct wl_listener *listener, void *data) void server_cursor_motion_absolute(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, cursor_motion_absolute); struct absinthe_server *server = wl_container_of(listener, server, cursor_motion_absolute);
struct wlr_pointer_motion_absolute_event *event = data; struct wlr_pointer_motion_absolute_event *event = data;
update_focused_output(server); update_focused_output(server);
wlr_cursor_warp_absolute(server->cursor, &event->pointer->base, event->x, event->y); wlr_cursor_warp_absolute(server->cursor, &event->pointer->base, event->x, event->y);
process_cursor_motion(server, event->time_msec); process_cursor_motion(server, event->time_msec);
} }
void server_cursor_button(struct wl_listener *listener, void *data) void server_cursor_button(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, cursor_button); struct absinthe_server *server = wl_container_of(listener, server, cursor_button);
struct wlr_pointer_button_event *event = data; struct wlr_pointer_button_event *event = data;
bool handled = false; bool handled = false;
if (event->state == WL_POINTER_BUTTON_STATE_RELEASED) { if (event->state == WL_POINTER_BUTTON_STATE_RELEASED) {
reset_cursor_mode(server); reset_cursor_mode(server);
} else { } else {
double sx, sy; double sx, sy;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
struct absinthe_toplevel *toplevel = absinthe_toplevel_at(server, server->cursor->x, server->cursor->y, &surface, &sx, &sy); struct absinthe_toplevel *toplevel = absinthe_toplevel_at(server, server->cursor->x, server->cursor->y, &surface, &sx, &sy);
if (!toplevel) if (!toplevel)
goto handle; goto handle;
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(server->seat); struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(server->seat);
uint32_t mods = wlr_keyboard_get_modifiers(keyboard); uint32_t mods = wlr_keyboard_get_modifiers(keyboard);
if (mods & ABSINTHE_CURSOR_MOD) { if (mods & ABSINTHE_CURSOR_MOD) {
if (event->button == ABSINTHE_CURSOR_MOVE_BUTTON) { if (event->button == ABSINTHE_CURSOR_MOVE_BUTTON) {
server->cursor_mode = ABSINTHE_CURSOR_MOVE; server->cursor_mode = ABSINTHE_CURSOR_MOVE;
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "all-scroll"); wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "all-scroll");
handled = true; handled = true;
} else if (event->button == ABSINTHE_CURSOR_RESIZE_BUTTON) { } else if (event->button == ABSINTHE_CURSOR_RESIZE_BUTTON) {
server->cursor_mode = ABSINTHE_CURSOR_RESIZE; server->cursor_mode = ABSINTHE_CURSOR_RESIZE;
handled = true; handled = true;
} }
} }
focus_toplevel(toplevel); focus_toplevel(toplevel);
server->grab_x = server->cursor->x; server->grab_x = server->cursor->x;
server->grab_y = server->cursor->y; server->grab_y = server->cursor->y;
int32_t lx, ly; int32_t lx, ly;
wlr_scene_node_coords(&toplevel->scene_tree->node, &lx, &ly); wlr_scene_node_coords(&toplevel->scene_tree->node, &lx, &ly);
server->grabbed_geometry.x = lx; server->grabbed_geometry.x = lx;
server->grabbed_geometry.y = ly; server->grabbed_geometry.y = ly;
server->grabbed_geometry.width = toplevel->geometry.width; server->grabbed_geometry.width = toplevel->geometry.width;
server->grabbed_geometry.height = toplevel->geometry.height; server->grabbed_geometry.height = toplevel->geometry.height;
if (server->cursor_mode != ABSINTHE_CURSOR_RESIZE) if (server->cursor_mode != ABSINTHE_CURSOR_RESIZE)
goto handle; goto handle;
int32_t width = toplevel->toplevel.xdg->base->geometry.width; int32_t width = toplevel->toplevel.xdg->base->geometry.width;
int32_t height = toplevel->toplevel.xdg->base->geometry.height; int32_t height = toplevel->toplevel.xdg->base->geometry.height;
if (server->grab_x > (lx + width / 2) && server->grab_y > (ly + height / 2)) { if (server->grab_x > (lx + width / 2) && server->grab_y > (ly + height / 2)) {
server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT; server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT;
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "se-resize"); wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "se-resize");
} else if (server->grab_x < (lx + width / 2) && server->grab_y > (ly + height / 2)) { } else if (server->grab_x < (lx + width / 2) && server->grab_y > (ly + height / 2)) {
server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT; server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT;
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "sw-resize"); wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "sw-resize");
} else if (server->grab_x > (lx + width / 2) && server->grab_y < (ly + height / 2)) { } else if (server->grab_x > (lx + width / 2) && server->grab_y < (ly + height / 2)) {
server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT; server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT;
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "ne-resize"); wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "ne-resize");
} else { } else {
server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT; server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT;
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "nw-resize"); wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "nw-resize");
} }
wlr_xdg_toplevel_set_resizing(toplevel->toplevel.xdg, true); wlr_xdg_toplevel_set_resizing(toplevel->toplevel.xdg, true);
} }
handle: handle:
if (!handled) { if (!handled) {
wlr_seat_pointer_notify_button(server->seat, event->time_msec, event->button, event->state); wlr_seat_pointer_notify_button(server->seat, event->time_msec, event->button, event->state);
} }
} }
void server_cursor_axis(struct wl_listener *listener, void *data) void server_cursor_axis(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, cursor_axis); struct absinthe_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 server_cursor_frame(struct wl_listener *listener, void *data) void server_cursor_frame(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, cursor_frame); struct absinthe_server *server = wl_container_of(listener, server, cursor_frame);
wlr_seat_pointer_notify_frame(server->seat); wlr_seat_pointer_notify_frame(server->seat);
} }
static void server_new_keyboard(struct absinthe_server *server, struct wlr_input_device *device) static void server_new_keyboard(struct absinthe_server *server, struct wlr_input_device *device)
{ {
struct wlr_keyboard *wlr_keyboard = wlr_keyboard_from_input_device(device); struct wlr_keyboard *wlr_keyboard = wlr_keyboard_from_input_device(device);
struct absinthe_keyboard *keyboard = calloc(1, sizeof(*keyboard)); struct absinthe_keyboard *keyboard = calloc(1, sizeof(*keyboard));
keyboard->server = server; keyboard->server = server;
keyboard->wlr_keyboard = wlr_keyboard; keyboard->wlr_keyboard = wlr_keyboard;
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS);
wlr_keyboard_set_keymap(wlr_keyboard, keymap); wlr_keyboard_set_keymap(wlr_keyboard, keymap);
xkb_keymap_unref(keymap); xkb_keymap_unref(keymap);
xkb_context_unref(context); xkb_context_unref(context);
wlr_keyboard_set_repeat_info(wlr_keyboard, 25, 600); wlr_keyboard_set_repeat_info(wlr_keyboard, 25, 600);
keyboard->modifiers.notify = keyboard_handle_modifiers; keyboard->modifiers.notify = keyboard_handle_modifiers;
wl_signal_add(&wlr_keyboard->events.modifiers, &keyboard->modifiers); wl_signal_add(&wlr_keyboard->events.modifiers, &keyboard->modifiers);
keyboard->key.notify = keyboard_handle_key; keyboard->key.notify = keyboard_handle_key;
wl_signal_add(&wlr_keyboard->events.key, &keyboard->key); wl_signal_add(&wlr_keyboard->events.key, &keyboard->key);
keyboard->destroy.notify = keyboard_handle_destroy; keyboard->destroy.notify = keyboard_handle_destroy;
wl_signal_add(&device->events.destroy, &keyboard->destroy); wl_signal_add(&device->events.destroy, &keyboard->destroy);
wlr_seat_set_keyboard(server->seat, wlr_keyboard); wlr_seat_set_keyboard(server->seat, wlr_keyboard);
wl_list_insert(&server->keyboards, &keyboard->link); wl_list_insert(&server->keyboards, &keyboard->link);
} }
static void server_new_pointer(struct absinthe_server *server, struct wlr_input_device *device) static void server_new_pointer(struct absinthe_server *server, struct wlr_input_device *device)
{ {
wlr_cursor_attach_input_device(server->cursor, device); wlr_cursor_attach_input_device(server->cursor, device);
} }
void server_new_input(struct wl_listener *listener, void *data) void server_new_input(struct wl_listener *listener, void *data)
{ {
struct absinthe_server *server = wl_container_of(listener, server, new_input); struct absinthe_server *server = wl_container_of(listener, server, new_input);
struct wlr_input_device *device = data; struct wlr_input_device *device = data;
switch (device->type) { switch (device->type) {
case WLR_INPUT_DEVICE_KEYBOARD: case WLR_INPUT_DEVICE_KEYBOARD:
server_new_keyboard(server, device); server_new_keyboard(server, device);
break; break;
case WLR_INPUT_DEVICE_POINTER: case WLR_INPUT_DEVICE_POINTER:
server_new_pointer(server, device); server_new_pointer(server, device);
default: default:
break; break;
} }
uint32_t caps = WL_SEAT_CAPABILITY_POINTER; uint32_t caps = WL_SEAT_CAPABILITY_POINTER;
if (!wl_list_empty(&server->keyboards)) { if (!wl_list_empty(&server->keyboards)) {
caps |= WL_SEAT_CAPABILITY_KEYBOARD; caps |= WL_SEAT_CAPABILITY_KEYBOARD;
} }
wlr_seat_set_capabilities(server->seat, caps); wlr_seat_set_capabilities(server->seat, caps);
} }
+6 -6
View File
@@ -4,15 +4,15 @@
void xdg_decoration_request_mode(struct wl_listener *listener, void *data) void xdg_decoration_request_mode(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, decoration_request_mode); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, decoration_request_mode);
if (toplevel->toplevel.xdg->base->initialized) if (toplevel->toplevel.xdg->base->initialized)
wlr_xdg_toplevel_decoration_v1_set_mode(toplevel->decoration, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); wlr_xdg_toplevel_decoration_v1_set_mode(toplevel->decoration, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
} }
void xdg_decoration_destroy(struct wl_listener *listener, void *data) void xdg_decoration_destroy(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, decoration_destroy); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, decoration_destroy);
wl_list_remove(&toplevel->decoration_request_mode.link); wl_list_remove(&toplevel->decoration_request_mode.link);
wl_list_remove(&toplevel->decoration_destroy.link); wl_list_remove(&toplevel->decoration_destroy.link);
} }
+7 -7
View File
@@ -6,18 +6,18 @@
void xdg_popup_commit(struct wl_listener *listener, void *data) void xdg_popup_commit(struct wl_listener *listener, void *data)
{ {
struct absinthe_popup *popup = wl_container_of(listener, popup, commit); struct absinthe_popup *popup = wl_container_of(listener, popup, commit);
if (popup->xdg_popup->base->initial_commit) if (popup->xdg_popup->base->initial_commit)
wlr_xdg_surface_schedule_configure(popup->xdg_popup->base); wlr_xdg_surface_schedule_configure(popup->xdg_popup->base);
} }
void xdg_popup_destroy(struct wl_listener *listener, void *data) void xdg_popup_destroy(struct wl_listener *listener, void *data)
{ {
struct absinthe_popup *popup = wl_container_of(listener, popup, destroy); struct absinthe_popup *popup = wl_container_of(listener, popup, destroy);
wl_list_remove(&popup->commit.link); wl_list_remove(&popup->commit.link);
wl_list_remove(&popup->destroy.link); wl_list_remove(&popup->destroy.link);
free(popup); free(popup);
} }
+17 -17
View File
@@ -12,25 +12,25 @@
void xdg_toplevel_commit(struct wl_listener *listener, void *data) void xdg_toplevel_commit(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, commit); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, commit);
int32_t borders_width = 2 * toplevel->border_width; int32_t borders_width = 2 * toplevel->border_width;
if (toplevel->toplevel.xdg->base->initial_commit) { if (toplevel->toplevel.xdg->base->initial_commit) {
/* Let toplevel set preferred size */ /* Let toplevel set preferred size */
toplevel->geometry.width = toplevel->toplevel.xdg->base->geometry.width + borders_width; toplevel->geometry.width = toplevel->toplevel.xdg->base->geometry.width + borders_width;
toplevel->geometry.height = toplevel->toplevel.xdg->base->geometry.height + borders_width; toplevel->geometry.height = toplevel->toplevel.xdg->base->geometry.height + borders_width;
/* Forse server side decoration mode */ /* Forse server side decoration mode */
if (toplevel->decoration) if (toplevel->decoration)
xdg_decoration_request_mode(&toplevel->decoration_request_mode, toplevel->decoration); xdg_decoration_request_mode(&toplevel->decoration_request_mode, toplevel->decoration);
toplevel->resizing = wlr_xdg_toplevel_set_size(toplevel->toplevel.xdg, 0, 0); toplevel->resizing = wlr_xdg_toplevel_set_size(toplevel->toplevel.xdg, 0, 0);
return; return;
} }
/* Update borders and position only after client prepared new buffer */ /* Update borders and position only after client prepared new buffer */
absinthe_toplevel_set_position(toplevel, toplevel->geometry.x, toplevel->geometry.y); absinthe_toplevel_set_position(toplevel, toplevel->geometry.x, toplevel->geometry.y);
absinthe_toplevel_update_borders_geometry(toplevel); absinthe_toplevel_update_borders_geometry(toplevel);
if (toplevel->resizing && toplevel->resizing <= toplevel->toplevel.xdg->base->current.configure_serial) if (toplevel->resizing && toplevel->resizing <= toplevel->toplevel.xdg->base->current.configure_serial)
toplevel->resizing = 0; toplevel->resizing = 0;
} }
+24 -23
View File
@@ -1,4 +1,5 @@
#ifdef XWAYLAND #ifdef XWAYLAND
#include "types.h" #include "types.h"
#include "absinthe-toplevel.h" #include "absinthe-toplevel.h"
#include "xdg-toplevel.h" #include "xdg-toplevel.h"
@@ -6,46 +7,46 @@
void xwayland_activate(struct wl_listener *listener, void *data) void xwayland_activate(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, xwayland_activate); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, xwayland_activate);
if (!absinthe_toplevel_is_unmanaged(toplevel)) if (!absinthe_toplevel_is_unmanaged(toplevel))
wlr_xwayland_surface_activate(toplevel->toplevel.x11, 1); wlr_xwayland_surface_activate(toplevel->toplevel.x11, 1);
} }
void xwayland_associate(struct wl_listener *listener, void *data) void xwayland_associate(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, xwayland_associate); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, xwayland_associate);
toplevel->map.notify = absinthe_toplevel_map; toplevel->map.notify = absinthe_toplevel_map;
wl_signal_add(&toplevel->toplevel.x11->surface->events.map, &toplevel->map); wl_signal_add(&toplevel->toplevel.x11->surface->events.map, &toplevel->map);
toplevel->unmap.notify = absinthe_toplevel_unmap; toplevel->unmap.notify = absinthe_toplevel_unmap;
wl_signal_add(&toplevel->toplevel.x11->surface->events.unmap, &toplevel->unmap); wl_signal_add(&toplevel->toplevel.x11->surface->events.unmap, &toplevel->unmap);
} }
void xwayland_dissociate(struct wl_listener *listener, void *data) void xwayland_dissociate(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, xwayland_dissociate); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, xwayland_dissociate);
wl_list_remove(&toplevel->map.link); wl_list_remove(&toplevel->map.link);
wl_list_remove(&toplevel->unmap.link); wl_list_remove(&toplevel->unmap.link);
} }
void xwayland_configure(struct wl_listener *listener, void *data) void xwayland_configure(struct wl_listener *listener, void *data)
{ {
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, xwayland_configure); struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, xwayland_configure);
struct wlr_xwayland_surface_configure_event *event = data; struct wlr_xwayland_surface_configure_event *event = data;
if (!toplevel->toplevel.x11->surface || !toplevel->toplevel.x11->surface->mapped) { if (!toplevel->toplevel.x11->surface || !toplevel->toplevel.x11->surface->mapped) {
wlr_xwayland_surface_configure(toplevel->toplevel.x11, event->x, event->y, event->width, event->height); wlr_xwayland_surface_configure(toplevel->toplevel.x11, event->x, event->y, event->width, event->height);
return; return;
} }
if (absinthe_toplevel_is_unmanaged(toplevel)) { if (absinthe_toplevel_is_unmanaged(toplevel)) {
wlr_scene_node_set_position(&toplevel->scene_tree->node, event->x, event->y); wlr_scene_node_set_position(&toplevel->scene_tree->node, event->x, event->y);
wlr_xwayland_surface_configure(toplevel->toplevel.x11, wlr_xwayland_surface_configure(toplevel->toplevel.x11,
event->x, event->y, event->width, event->height); event->x, event->y, event->width, event->height);
return; return;
} }
} }
void xwayland_set_hints(struct wl_listener *listener, void *data) {} void xwayland_set_hints(struct wl_listener *listener, void *data) {}