base
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
absinthe
|
||||||
|
.cache/
|
||||||
|
compile_commands.json
|
||||||
|
xdg-shell-protocol.h
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
all: compile
|
||||||
|
|
||||||
|
proto:
|
||||||
|
wayland-scanner server-header /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml xdg-shell-protocol.h
|
||||||
|
|
||||||
|
compile: proto
|
||||||
|
gcc -o absinthe src/* \
|
||||||
|
-I./ -I./include -DWLR_USE_UNSTABLE $(shell pkg-config wlroots-0.19 --libs --cflags) -lwayland-server -lxkbcommon \
|
||||||
|
-ggdb -Wall -Wextra
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#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);
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
void reset_cursor_mode(struct absinthe_server *server);
|
||||||
|
void process_cursor_motion(struct absinthe_server *server, uint32_t time);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
void focus_toplevel(struct absinthe_toplevel *toplevel);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
|
void keyboard_handle_modifiers(struct wl_listener *listener, void *data);
|
||||||
|
void keyboard_handle_key(struct wl_listener *listener, void *data);
|
||||||
|
void keyboard_handle_destroy(struct wl_listener *listener, void *data);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
|
void output_frame(struct wl_listener *listener, void *data);
|
||||||
|
void output_request_state(struct wl_listener *listener, void *data);
|
||||||
|
void output_destroy(struct wl_listener *listener, void *data);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
|
void seat_request_cursor(struct wl_listener *listener, void *data);
|
||||||
|
void seat_pointer_focus_change(struct wl_listener *listener, void *data);
|
||||||
|
void seat_request_set_selection(struct wl_listener *listener, void *data);
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
|
void server_new_output(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
|
void server_new_xdg_toplevel(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
|
void server_new_xdg_popup(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
|
void server_cursor_motion(struct wl_listener *listener, void *data);
|
||||||
|
void server_cursor_motion_absolute(struct wl_listener *listener, void *data);
|
||||||
|
void server_cursor_button(struct wl_listener *listener, void *data);
|
||||||
|
void server_cursor_axis(struct wl_listener *listener, void *data);
|
||||||
|
void server_cursor_frame(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
|
void server_new_input(struct wl_listener *listener, void *data);
|
||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/backend.h>
|
||||||
|
#include <wlr/render/wlr_renderer.h>
|
||||||
|
#include <wlr/render/allocator.h>
|
||||||
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
#include <wlr/types/wlr_cursor.h>
|
||||||
|
#include <wlr/types/wlr_seat.h>
|
||||||
|
#include <wlr/types/wlr_keyboard.h>
|
||||||
|
|
||||||
|
#define ABSINTHE_CURSOR_MOD WLR_MODIFIER_ALT
|
||||||
|
#define ABSINTHE_CURSOR_MOVE_BUTTON BTN_LEFT
|
||||||
|
#define ABSINTHE_CURSOR_RESIZE_BUTTON BTN_RIGHT
|
||||||
|
|
||||||
|
enum absinthe_cursor_mode {
|
||||||
|
ABSINTHE_CURSOR_PASSTHROUGH,
|
||||||
|
ABSINTHE_CURSOR_MOVE,
|
||||||
|
ABSINTHE_CURSOR_RESIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum absinthe_cursor_resize_corner {
|
||||||
|
ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT,
|
||||||
|
ABSINTHE_CURSOR_RESIZE_CORNER_TOP_RIGHT,
|
||||||
|
ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_LEFT,
|
||||||
|
ABSINTHE_CURSOR_RESIZE_CORNER_BOTTOM_RIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct absinthe_server {
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wlr_backend *backend;
|
||||||
|
struct wlr_renderer *renderer;
|
||||||
|
struct wlr_allocator *allocator;
|
||||||
|
struct wlr_scene *scene;
|
||||||
|
struct wlr_scene_output_layout *scene_layout;
|
||||||
|
|
||||||
|
struct wlr_xdg_shell *xdg_shell;
|
||||||
|
struct wl_listener new_xdg_toplevel;
|
||||||
|
struct wl_listener new_xdg_popup;
|
||||||
|
struct wl_list toplevels;
|
||||||
|
|
||||||
|
struct wlr_cursor *cursor;
|
||||||
|
struct wlr_xcursor_manager *cursor_mgr;
|
||||||
|
struct wl_listener cursor_motion;
|
||||||
|
struct wl_listener cursor_motion_absolute;
|
||||||
|
struct wl_listener cursor_button;
|
||||||
|
struct wl_listener cursor_axis;
|
||||||
|
struct wl_listener cursor_frame;
|
||||||
|
|
||||||
|
struct wlr_seat *seat;
|
||||||
|
struct wl_listener new_input;
|
||||||
|
struct wl_listener request_cursor;
|
||||||
|
struct wl_listener pointer_focus_change;
|
||||||
|
struct wl_listener request_set_selection;
|
||||||
|
struct wl_list keyboards;
|
||||||
|
enum absinthe_cursor_mode cursor_mode;
|
||||||
|
struct absinthe_toplevel *grabbed_toplevel;
|
||||||
|
uint32_t grabbed_toplevel_x, grabbed_toplevel_y;
|
||||||
|
uint32_t grabbed_toplevel_width, grabbed_toplevel_height;
|
||||||
|
uint32_t grab_x, grab_y;
|
||||||
|
enum absinthe_cursor_resize_corner cursor_resize_corner;
|
||||||
|
|
||||||
|
struct wlr_output_layout *output_layout;
|
||||||
|
struct wl_list outputs;
|
||||||
|
struct wl_listener new_output;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct absinthe_output {
|
||||||
|
struct wl_list link;
|
||||||
|
struct absinthe_server *server;
|
||||||
|
struct wlr_output *wlr_output;
|
||||||
|
struct wl_listener frame;
|
||||||
|
struct wl_listener request_state;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct absinthe_toplevel {
|
||||||
|
struct wl_list link;
|
||||||
|
struct absinthe_server *server;
|
||||||
|
struct wlr_xdg_toplevel *xdg_toplevel;
|
||||||
|
struct wlr_scene_tree *scene_tree;
|
||||||
|
struct wl_listener map;
|
||||||
|
struct wl_listener unmap;
|
||||||
|
struct wl_listener commit;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
struct wl_listener request_move;
|
||||||
|
struct wl_listener request_resize;
|
||||||
|
struct wl_listener request_maximize;
|
||||||
|
struct wl_listener request_fullscreen;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct absinthe_popup {
|
||||||
|
struct wlr_xdg_popup *xdg_popup;
|
||||||
|
struct wl_listener commit;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct absinthe_keyboard {
|
||||||
|
struct wl_list link;
|
||||||
|
struct absinthe_server *server;
|
||||||
|
struct wlr_keyboard *wlr_keyboard;
|
||||||
|
struct wl_listener modifiers;
|
||||||
|
struct wl_listener key;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
|
void xdg_popup_commit(struct wl_listener *listener, void *data);
|
||||||
|
void xdg_popup_destroy(struct wl_listener *listener, void *data);
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
|
void xdg_toplevel_map(struct wl_listener *listener, void *data);
|
||||||
|
void xdg_toplevel_unmap(struct wl_listener *listener, void *data);
|
||||||
|
void xdg_toplevel_commit(struct wl_listener *listener, void *data);
|
||||||
|
void xdg_toplevel_destroy(struct wl_listener *listener, void *data);
|
||||||
|
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);
|
||||||
|
void xdg_toplevel_request_fullscreen(struct wl_listener *listener, void *data);
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
@@ -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
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user