This commit is contained in:
2026-01-02 22:53:34 +07:00
commit a12293fd3a
22 changed files with 915 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
#include <wayland-server-core.h>
#include "types.h"
struct absinthe_toplevel *absinthe_toplevel_at(struct absinthe_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy)
{
struct wlr_scene_node *node = wlr_scene_node_at(&server->scene->tree.node, lx, ly, sx, sy);
if (!node || node->type != WLR_SCENE_NODE_BUFFER) {
return NULL;
}
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);
if (!scene_surface) {
return NULL;
}
*surface = scene_surface->surface;
struct wlr_scene_tree *tree = node->parent;
while (tree != NULL && tree->node.data == NULL) {
tree = tree->node.parent;
}
return tree->node.data;
}
+89
View File
@@ -0,0 +1,89 @@
#include <wayland-server-core.h>
#include <wlr/util/log.h>
#include "types.h"
#include "absinthe-toplevel.h"
void reset_cursor_mode(struct absinthe_server *server)
{
server->cursor_mode = ABSINTHE_CURSOR_PASSTHROUGH;
server->grabbed_toplevel = NULL;
}
static void process_cursor_move(struct absinthe_server *server) {
struct absinthe_toplevel *toplevel = server->grabbed_toplevel;
if (!toplevel) return;
uint32_t new_x, new_y;
new_x = server->cursor->x - server->grab_x + server->grabbed_toplevel_x;
new_y = server->cursor->y - server->grab_y + server->grabbed_toplevel_y;
wlr_scene_node_set_position(&toplevel->scene_tree->node, new_x, new_y);
}
static void process_cursor_resize(struct absinthe_server *server) {
struct absinthe_toplevel *toplevel = server->grabbed_toplevel;
if (!toplevel) return;
int32_t new_x, new_y, new_width, new_height;
new_x = server->grabbed_toplevel_x;
new_y = server->grabbed_toplevel_y;
new_width = server->grabbed_toplevel_width;
new_height = server->grabbed_toplevel_height;
switch (server->cursor_resize_corner) {
case ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT:
new_x += server->cursor->x - server->grab_x;
new_y += server->cursor->y - server->grab_y;
new_width -= server->cursor->x - server->grab_x;
new_height -= server->cursor->y - server->grab_y;
break;
case ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT:
new_y += server->cursor->y - server->grab_y;
new_width += server->cursor->x - server->grab_x;
new_height -= server->cursor->y - server->grab_y;
break;
case ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT:
new_x += server->cursor->x - server->grab_x;
new_width -= server->cursor->x - server->grab_x;
new_height += server->cursor->y - server->grab_y;
break;
case ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT:
new_width += server->cursor->x - server->grab_x;
new_height += server->cursor->y - server->grab_y;
break;
default: // unreachable
break;
}
if (new_width > 0 && new_height > 0) {
wlr_scene_node_set_position(&toplevel->scene_tree->node, new_x, new_y);
wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, new_width, new_height);
}
}
void process_cursor_motion(struct absinthe_server *server, uint32_t time)
{
if (server->cursor_mode == ABSINTHE_CURSOR_MOVE) {
process_cursor_move(server);
return;
} else if (server->cursor_mode == ABSINTHE_CURSOR_RESIZE) {
process_cursor_resize(server);
return;
}
double sx, sy;
struct wlr_seat *seat = server->seat;
struct wlr_surface *surface = NULL;
struct absinthe_toplevel *toplevel = absinthe_toplevel_at(server, server->cursor->x, server->cursor->y, &surface, &sx, &sy);
if (!toplevel) {
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "default");
}
if (surface) {
wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat, time, sx, sy);
} else {
wlr_seat_pointer_clear_focus(seat);
}
}
+34
View File
@@ -0,0 +1,34 @@
#include <wayland-server-core.h>
#include "types.h"
void focus_toplevel(struct absinthe_toplevel *toplevel)
{
if (!toplevel) {
return;
}
struct absinthe_server *server = toplevel->server;
struct wlr_seat *seat = server->seat;
struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface;
struct wlr_surface *surface = toplevel->xdg_toplevel->base->surface;
if (surface == prev_surface) {
return;
}
if (prev_surface) {
struct wlr_xdg_toplevel *prev_toplevel = wlr_xdg_toplevel_try_from_wlr_surface(prev_surface);
if (prev_toplevel) wlr_xdg_toplevel_set_activated(prev_toplevel, false);
}
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
wlr_scene_node_raise_to_top(&toplevel->scene_tree->node);
wl_list_remove(&toplevel->link);
wl_list_insert(&server->toplevels, &toplevel->link);
wlr_xdg_toplevel_set_activated(toplevel->xdg_toplevel, true);
if (keyboard) {
wlr_seat_keyboard_notify_enter(seat, surface, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
}
}
+47
View File
@@ -0,0 +1,47 @@
#include <stdlib.h>
#include <wayland-server-core.h>
#include <xkbcommon/xkbcommon.h>
#include "types.h"
void keyboard_handle_modifiers(struct wl_listener *listener, void *data)
{
struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, modifiers);
wlr_seat_set_keyboard(keyboard->server->seat, keyboard->wlr_keyboard);
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)
{
switch (keysym) {
case XKB_KEY_Escape:
wl_display_terminate(server->display);
break;
default:
return false;
}
return true;
}
void keyboard_handle_key(struct wl_listener *listener, void *data)
{
struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, key);
struct wlr_keyboard_key_event *event = data;
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);
}
void keyboard_handle_destroy(struct wl_listener *listener, void *data)
{
struct absinthe_keyboard *keyboard = wl_container_of(listener, keyboard, modifiers);
wl_list_remove(&keyboard->modifiers.link);
wl_list_remove(&keyboard->key.link);
wl_list_remove(&keyboard->destroy.link);
wl_list_remove(&keyboard->link);
free(keyboard);
}
+139
View File
@@ -0,0 +1,139 @@
#include <stdlib.h>
#include <wlr/util/log.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include "types.h"
#include "server.h"
#include "seat.h"
int main(int argc, char **argv)
{
wlr_log_init(WLR_DEBUG, NULL);
struct absinthe_server server = {0};
server.display = wl_display_create();
if (!server.display) {
wlr_log(WLR_ERROR, "Failed to create wl_display");
return 1;
}
server.backend = wlr_backend_autocreate(wl_display_get_event_loop(server.display), NULL);
if (!server.backend) {
wlr_log(WLR_ERROR, "Failed to create wlr_backend");
return 1;
}
server.renderer = wlr_renderer_autocreate(server.backend);
if (!server.renderer) {
wlr_log(WLR_ERROR, "Failed to create wlr_renderer");
return 1;
}
wlr_renderer_init_wl_display(server.renderer, server.display);
server.allocator = wlr_allocator_autocreate(server.backend, server.renderer);
if (!server.allocator) {
wlr_log(WLR_ERROR, "Failed to create wlr_allocator");
return 1;
}
wlr_compositor_create(server.display, 5, server.renderer);
wlr_subcompositor_create(server.display);
wlr_data_device_manager_create(server.display);
wlr_screencopy_manager_v1_create(server.display);
server.output_layout = wlr_output_layout_create(server.display);
wl_list_init(&server.outputs);
server.new_output.notify = server_new_output;
wl_signal_add(&server.backend->events.new_output, &server.new_output);
server.scene = wlr_scene_create();
server.scene_layout = wlr_scene_attach_output_layout(server.scene, server.output_layout);
wl_list_init(&server.toplevels);
server.xdg_shell = wlr_xdg_shell_create(server.display, 3);
server.new_xdg_toplevel.notify = server_new_xdg_toplevel;
wl_signal_add(&server.xdg_shell->events.new_toplevel, &server.new_xdg_toplevel);
server.new_xdg_popup.notify = server_new_xdg_popup;
wl_signal_add(&server.xdg_shell->events.new_popup, &server.new_xdg_popup);
server.cursor = wlr_cursor_create();
wlr_cursor_attach_output_layout(server.cursor, server.output_layout);
server.cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
server.cursor_mode = ABSINTHE_CURSOR_PASSTHROUGH;
server.cursor_motion.notify = server_cursor_motion;
wl_signal_add(&server.cursor->events.motion, &server.cursor_motion);
server.cursor_motion_absolute.notify = server_cursor_motion_absolute;
wl_signal_add(&server.cursor->events.motion_absolute, &server.cursor_motion_absolute);
server.cursor_button.notify = server_cursor_button;
wl_signal_add(&server.cursor->events.button, &server.cursor_button);
server.cursor_axis.notify = server_cursor_axis;
wl_signal_add(&server.cursor->events.axis, &server.cursor_axis);
server.cursor_frame.notify = server_cursor_frame;
wl_signal_add(&server.cursor->events.frame, &server.cursor_frame);
wl_list_init(&server.keyboards);
server.new_input.notify = server_new_input;
wl_signal_add(&server.backend->events.new_input, &server.new_input);
server.seat = wlr_seat_create(server.display, "seat0");
server.request_cursor.notify = seat_request_cursor;
wl_signal_add(&server.seat->events.request_set_cursor, &server.request_cursor);
server.pointer_focus_change.notify = seat_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;
wl_signal_add(&server.seat->events.request_set_selection, &server.request_set_selection);
const char *socket = wl_display_add_socket_auto(server.display);
if (!socket) {
wlr_log(WLR_ERROR, "Failed to add socket");
wlr_backend_destroy(server.backend);
return 1;
}
if (!wlr_backend_start(server.backend)) {
wlr_log(WLR_ERROR, "Failed to start wlr_backend");
wlr_backend_destroy(server.backend);
wl_display_destroy(server.display);
return 1;
}
setenv("WAYLAND_DISPLAY", socket, true);
wlr_log(WLR_INFO, "Running absinthe on WAYLAND_DISPLAY=%s", socket);
wl_display_run(server.display);
wl_display_destroy_clients(server.display);
wl_list_remove(&server.new_xdg_toplevel.link);
wl_list_remove(&server.new_xdg_popup.link);
wl_list_remove(&server.cursor_motion.link);
wl_list_remove(&server.cursor_motion_absolute.link);
wl_list_remove(&server.cursor_button.link);
wl_list_remove(&server.cursor_axis.link);
wl_list_remove(&server.cursor_frame.link);
wl_list_remove(&server.new_input.link);
wl_list_remove(&server.request_cursor.link);
wl_list_remove(&server.pointer_focus_change.link);
wl_list_remove(&server.request_set_selection.link);
wl_list_remove(&server.new_output.link);
wlr_scene_node_destroy(&server.scene->tree.node);
wlr_xcursor_manager_destroy(server.cursor_mgr);
wlr_cursor_destroy(server.cursor);
wlr_allocator_destroy(server.allocator);
wlr_renderer_destroy(server.renderer);
wlr_backend_destroy(server.backend);
wl_display_destroy(server.display);
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
#include <stdlib.h>
#include "types.h"
void output_frame(struct wl_listener *listener, void *data)
{
struct absinthe_output *output = wl_container_of(listener, output, frame);
struct wlr_scene *scene = output->server->scene;
struct wlr_scene_output *scene_output = wlr_scene_get_scene_output(scene, output->wlr_output);
wlr_scene_output_commit(scene_output, NULL);
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_output_send_frame_done(scene_output, &now);
}
void output_request_state(struct wl_listener *listener, void *data)
{
struct absinthe_output *output = wl_container_of(listener, output, request_state);
const struct wlr_output_event_request_state *event = data;
wlr_output_commit_state(output->wlr_output, event->state);
}
void output_destroy(struct wl_listener *listener, void *data)
{
struct absinthe_output *output = wl_container_of(listener, output, request_state);
wl_list_remove(&output->frame.link);
wl_list_remove(&output->request_state.link);
wl_list_remove(&output->destroy.link);
wl_list_remove(&output->link);
free(output);
}
+33
View File
@@ -0,0 +1,33 @@
#include <wayland-server-core.h>
#include <wlr/types/wlr_data_device.h>
#include "types.h"
void seat_request_cursor(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, request_cursor);
struct wlr_seat_pointer_request_set_cursor_event *event = data;
struct wlr_seat_client *client = server->seat->pointer_state.focused_client;
if (client == event->seat_client) {
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)
{
struct absinthe_server *server = wl_container_of(listener, server, pointer_focus_change);
struct wlr_seat_pointer_focus_change_event *event = data;
if (!event->new_surface) {
wlr_cursor_set_xcursor(server->cursor, server->cursor_mgr, "default");
}
}
void seat_request_set_selection(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, request_set_selection);
struct wlr_seat_request_set_selection_event *event = data;
wlr_seat_set_selection(server->seat, event->source, event->serial);
}
+236
View File
@@ -0,0 +1,236 @@
#include <assert.h>
#include <stdlib.h>
#include <wlr/util/log.h>
#include "types.h"
#include "output.h"
#include "xdg-toplevel.h"
#include "xdg-popup.h"
#include "absinthe-toplevel.h"
#include "focus.h"
#include "keyboard.h"
#include "cursor.h"
void server_new_output(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, new_output);
struct wlr_output *wlr_output = data;
wlr_output_init_render(wlr_output, server->allocator, server->renderer);
struct wlr_output_state state;
wlr_output_state_init(&state);
wlr_output_state_set_enabled(&state, true);
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
if (mode) {
wlr_output_state_set_mode(&state, mode);
}
wlr_output_commit_state(wlr_output, &state);
wlr_output_state_finish(&state);
struct absinthe_output *output = calloc(1, sizeof(*output));
output->wlr_output = wlr_output;
output->server = server;
output->frame.notify = output_frame;
wl_signal_add(&wlr_output->events.frame, &output->frame);
output->request_state.notify = output_request_state;
wl_signal_add(&wlr_output->events.request_state, &output->request_state);
output->destroy.notify = output_destroy;
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
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);
wlr_scene_output_layout_add_output(server->scene_layout, l_layout, scene_output);
}
void server_new_xdg_toplevel(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, new_xdg_toplevel);
struct wlr_xdg_toplevel *xdg_toplevel = data;
struct absinthe_toplevel *toplevel = calloc(1, sizeof(*toplevel));
toplevel->server = server;
toplevel->xdg_toplevel = xdg_toplevel;
toplevel->scene_tree = wlr_scene_xdg_surface_create(&toplevel->server->scene->tree, xdg_toplevel->base);
toplevel->scene_tree->node.data = toplevel;
xdg_toplevel->base->data = toplevel->scene_tree;
toplevel->map.notify = xdg_toplevel_map;
wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map);
toplevel->unmap.notify = xdg_toplevel_unmap;
wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap);
toplevel->commit.notify = xdg_toplevel_commit;
wl_signal_add(&xdg_toplevel->base->surface->events.commit, &toplevel->commit);
toplevel->destroy.notify = xdg_toplevel_destroy;
wl_signal_add(&xdg_toplevel->events.destroy, &toplevel->destroy);
toplevel->request_move.notify = xdg_toplevel_request_move;
wl_signal_add(&xdg_toplevel->events.request_move, &toplevel->request_move);
toplevel->request_resize.notify = xdg_toplevel_request_resize;
wl_signal_add(&xdg_toplevel->events.request_resize, &toplevel->request_resize);
toplevel->request_maximize.notify = xdg_toplevel_request_maximize;
wl_signal_add(&xdg_toplevel->events.request_maximize, &toplevel->request_maximize);
toplevel->request_fullscreen.notify = xdg_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)
{
struct absinthe_server *server = wl_container_of(listener, server, new_xdg_popup);
struct wlr_xdg_popup *xdg_popup = data;
struct absinthe_popup *popup = calloc(1, sizeof(*popup));
popup->xdg_popup = xdg_popup;
struct wlr_xdg_surface *parent = wlr_xdg_surface_try_from_wlr_surface(xdg_popup->parent);
assert(parent != NULL);
struct wlr_scene_tree *parent_tree = parent->data;
xdg_popup->base->data = wlr_scene_xdg_surface_create(parent_tree, xdg_popup->base);
popup->commit.notify = xdg_popup_commit;
wl_signal_add(&xdg_popup->base->surface->events.commit, &popup->commit);
popup->destroy.notify = xdg_popup_destroy;
wl_signal_add(&xdg_popup->base->surface->events.destroy, &popup->destroy);
}
void server_cursor_motion(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, cursor_motion);
struct wlr_pointer_motion_event *event = data;
wlr_cursor_move(server->cursor, &event->pointer->base, event->delta_x, event->delta_y);
process_cursor_motion(server, event->time_msec);
}
void server_cursor_motion_absolute(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, cursor_motion_absolute);
struct wlr_pointer_motion_absolute_event *event = data;
wlr_cursor_warp_absolute(server->cursor, &event->pointer->base, event->x, event->y);
process_cursor_motion(server, event->time_msec);
}
void server_cursor_button(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, cursor_button);
struct wlr_pointer_button_event *event = data;
wlr_seat_pointer_notify_button(server->seat, event->time_msec, event->button, event->state);
if (event->state == WL_POINTER_BUTTON_STATE_RELEASED) {
reset_cursor_mode(server);
} else {
double sx, sy;
struct wlr_surface *surface = NULL;
struct absinthe_toplevel *toplevel = absinthe_toplevel_at(server, server->cursor->x, server->cursor->y, &surface, &sx, &sy);
focus_toplevel(toplevel);
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(server->seat);
uint32_t mods = wlr_keyboard_get_modifiers(keyboard);
if (mods & ABSINTHE_CURSOR_MOD) {
if (event->button == ABSINTHE_CURSOR_MOVE_BUTTON) {
server->cursor_mode = ABSINTHE_CURSOR_MOVE;
} else if (event->button == ABSINTHE_CURSOR_RESIZE_BUTTON) {
server->cursor_mode = ABSINTHE_CURSOR_RESIZE;
}
}
if (toplevel) {
server->grab_x = server->cursor->x;
server->grab_y = server->cursor->y;
int lx, ly;
wlr_scene_node_coords(&toplevel->scene_tree->node, &lx, &ly);
server->grabbed_toplevel_x = lx;
server->grabbed_toplevel_y = ly;
server->grabbed_toplevel_width = toplevel->xdg_toplevel->base->geometry.width;
server->grabbed_toplevel_height = toplevel->xdg_toplevel->base->geometry.height;
wlr_log(WLR_DEBUG, "%d, %d", server->grabbed_toplevel_width, server->grabbed_toplevel_width);
server->grabbed_toplevel = toplevel;
int width = toplevel->xdg_toplevel->base->geometry.width;
int height = toplevel->xdg_toplevel->base->geometry.height;
if ((int)server->grab_x > (lx + width / 2) && (int)server->grab_y > (ly + height / 2)) {
server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT;
} else if ((int)server->grab_x < (lx + width / 2) && (int)server->grab_y > (ly + height / 2)) {
server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT;
} else if ((int)server->grab_x > (lx + width / 2) && (int)server->grab_y < (ly + height / 2)) {
server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT;
} else {
server->cursor_resize_corner = ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT;
}
}
}
}
void server_cursor_axis(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, cursor_axis);
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);
}
void server_cursor_frame(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, cursor_frame);
wlr_seat_pointer_notify_frame(server->seat);
}
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 absinthe_keyboard *keyboard = calloc(1, sizeof(*keyboard));
keyboard->server = server;
keyboard->wlr_keyboard = wlr_keyboard;
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);
wlr_keyboard_set_keymap(wlr_keyboard, keymap);
xkb_keymap_unref(keymap);
xkb_context_unref(context);
wlr_keyboard_set_repeat_info(wlr_keyboard, 25, 600);
keyboard->modifiers.notify = keyboard_handle_modifiers;
wl_signal_add(&wlr_keyboard->events.modifiers, &keyboard->modifiers);
keyboard->key.notify = keyboard_handle_key;
wl_signal_add(&wlr_keyboard->events.key, &keyboard->key);
keyboard->destroy.notify = keyboard_handle_destroy;
wl_signal_add(&device->events.destroy, &keyboard->destroy);
wlr_seat_set_keyboard(server->seat, wlr_keyboard);
wl_list_insert(&server->keyboards, &keyboard->link);
}
static void server_new_pointer(struct absinthe_server *server, struct wlr_input_device *device)
{
wlr_cursor_attach_input_device(server->cursor, device);
}
void server_new_input(struct wl_listener *listener, void *data)
{
struct absinthe_server *server = wl_container_of(listener, server, new_input);
struct wlr_input_device *device = data;
switch (device->type) {
case WLR_INPUT_DEVICE_KEYBOARD:
server_new_keyboard(server, device);
break;
case WLR_INPUT_DEVICE_POINTER:
server_new_pointer(server, device);
default:
break;
}
uint32_t caps = WL_SEAT_CAPABILITY_POINTER;
if (!wl_list_empty(&server->keyboards)) {
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
}
wlr_seat_set_capabilities(server->seat, caps);
}
+24
View File
@@ -0,0 +1,24 @@
#include <stdlib.h>
#include <wayland-server-core.h>
#include "types.h"
void xdg_popup_commit(struct wl_listener *listener, void *data)
{
struct absinthe_popup *popup = wl_container_of(listener, popup, commit);
if (popup->xdg_popup->base->initial_commit) {
wlr_xdg_surface_schedule_configure(popup->xdg_popup->base);
}
}
void xdg_popup_destroy(struct wl_listener *listener, void *data)
{
struct absinthe_popup *popup = wl_container_of(listener, popup, commit);
wl_list_remove(&popup->commit.link);
wl_list_remove(&popup->destroy.link);
free(popup);
}
+63
View File
@@ -0,0 +1,63 @@
#include <stdlib.h>
#include <wayland-server-core.h>
#include "types.h"
void xdg_toplevel_map(struct wl_listener *listener, void *data)
{
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, map);
wl_list_insert(&toplevel->server->toplevels, &toplevel->link);
}
void xdg_toplevel_unmap(struct wl_listener *listener, void *data)
{
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, unmap);
wl_list_remove(&toplevel->link);
}
void xdg_toplevel_commit(struct wl_listener *listener, void *data)
{
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, commit);
if (toplevel->xdg_toplevel->base->initial_commit) {
wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, 0, 0);
}
}
void xdg_toplevel_destroy(struct wl_listener *listener, void *data)
{
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, destroy);
wl_list_remove(&toplevel->map.link);
wl_list_remove(&toplevel->unmap.link);
wl_list_remove(&toplevel->commit.link);
wl_list_remove(&toplevel->destroy.link);
wl_list_remove(&toplevel->request_move.link);
wl_list_remove(&toplevel->request_resize.link);
wl_list_remove(&toplevel->request_maximize.link);
wl_list_remove(&toplevel->request_fullscreen.link);
free(toplevel);
}
void xdg_toplevel_request_move(struct wl_listener *listener, void *data) {}
void xdg_toplevel_request_resize(struct wl_listener *listener, void *data) {}
void xdg_toplevel_request_maximize(struct wl_listener *listener, void *data)
{
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_maximize);
if (toplevel->xdg_toplevel->base->initialized) {
wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base);
}
}
void xdg_toplevel_request_fullscreen(struct wl_listener *listener, void *data)
{
struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, request_fullscreen);
if (toplevel->xdg_toplevel->base->initialized) {
wlr_xdg_surface_schedule_configure(toplevel->xdg_toplevel->base);
}
}