commit 28b60a4
uint
·
2026-08-04 01:00:50 +0000 UTC
parent 5e2f2b5
Wayland: wayland-cursor hiding support
3 files changed,
+126,
-14
+2,
-2
1@@ -30,8 +30,8 @@ case "$backend" in
2 echo "CONF_LIB_NAME = libmaus_x11.a" >> config.mk
3 ;;
4 wayland)
5- echo "CONF_CPPFLAGS = -DBACKEND_WAY $(pkg-config --cflags wayland-client xkbcommon)" >> config.mk
6- echo "CONF_LDFLAGS = $(pkg-config --libs wayland-client xkbcommon)" >> config.mk
7+ echo "CONF_CPPFLAGS = -DBACKEND_WAY $(pkg-config --cflags wayland-client wayland-cursor xkbcommon)" >> config.mk
8+ echo "CONF_LDFLAGS = $(pkg-config --libs wayland-client wayland-cursor xkbcommon)" >> config.mk
9 echo "CONF_SRC = source/maus_wayland.c build/xdg-shell-protocol.c" >> config.mk
10 echo "CONF_OBJS = build/maus_wayland.o build/xdg-shell-protocol.o" >> config.mk
11 echo "CONF_LIB_NAME = libmaus_wayland.a" >> config.mk
+8,
-0
1@@ -15,6 +15,8 @@ struct wl_shm;
2 struct wl_seat;
3 struct wl_pointer;
4 struct wl_keyboard;
5+struct wl_cursor_theme;
6+struct wl_cursor;
7
8 struct xdg_wm_base;
9 struct xdg_surface;
10@@ -56,6 +58,12 @@ typedef struct {
11 struct wl_pointer* pointer;
12 struct wl_keyboard* keyboard;
13
14+ struct wl_cursor_theme* cursor_theme;
15+ struct wl_cursor* cursor;
16+ struct wl_surface* cursor_surface;
17+ uint32_t pointer_enter_serial;
18+ int8_t cursor_state;
19+
20 struct xkb_context* xkb_context;
21 struct xkb_keymap* xkb_keymap;
22 struct xkb_state* xkb_state;
+116,
-12
1@@ -6,6 +6,7 @@
2 #include <unistd.h>
3
4 #include <wayland-client.h>
5+#include <wayland-cursor.h>
6 #include <xdg-shell-client-protocol.h>
7 #include <xkbcommon/xkbcommon.h>
8
9@@ -40,6 +41,10 @@ static void keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_
10 static void keyboard_repeat_info(void* data, struct wl_keyboard* keyboard, int32_t rate, int32_t delay);
11 static void registry_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
12
13+static void cursor_destroy(Maus* mw);
14+static void cursor_hide(Maus* mw);
15+static int8_t cursor_init(Maus* mw);
16+static void cursor_show(Maus* mw);
17 static MausKey keysym_to_mauskey(xkb_keysym_t sym);
18 static MausMouseButton wl_button_to_maus(uint32_t button);
19
20@@ -163,7 +168,21 @@ static void seat_capabilities(void* data, struct wl_seat* seat, uint32_t capabil
21 static void seat_name(void* data, struct wl_seat* seat, const char* name) { }
22
23 static void pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial,
24- struct wl_surface* surface, wl_fixed_t sx, wl_fixed_t sy) { }
25+ struct wl_surface* surface, wl_fixed_t sx, wl_fixed_t sy)
26+{
27+ Maus* mw = data;
28+
29+ (void)pointer;
30+ (void)surface;
31+ (void)sx;
32+ (void)sy;
33+
34+ mw->backend.pointer_enter_serial = serial;
35+ if (mw->backend.cursor_state == MAUS_CURSOR_STATE_HIDDEN)
36+ cursor_hide(mw);
37+ else
38+ cursor_show(mw);
39+}
40
41 static void pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial,
42 struct wl_surface* surface) { }
43@@ -348,6 +367,72 @@ static void keyboard_repeat_info(void* data, struct wl_keyboard* keyboard,
44 int32_t rate, int32_t delay) { }
45
46
47+static int8_t cursor_init(Maus* mw)
48+{
49+ MausBackend* be = &mw->backend;
50+
51+ be->cursor_theme = wl_cursor_theme_load(NULL, 24, be->shm);
52+ if (!be->cursor_theme)
53+ return 0;
54+
55+ be->cursor = wl_cursor_theme_get_cursor(be->cursor_theme, "left_ptr");
56+ if (!be->cursor)
57+ return 0;
58+
59+ be->cursor_surface = wl_compositor_create_surface(be->compositor);
60+ if (!be->cursor_surface)
61+ return 0;
62+
63+ return 1;
64+}
65+
66+static void cursor_destroy(Maus* mw)
67+{
68+ MausBackend* be = &mw->backend;
69+
70+ if (be->cursor_surface)
71+ wl_surface_destroy(be->cursor_surface);
72+ if (be->cursor_theme)
73+ wl_cursor_theme_destroy(be->cursor_theme);
74+
75+ be->cursor_surface = NULL;
76+ be->cursor_theme = NULL;
77+ be->cursor = NULL;
78+}
79+
80+static void cursor_hide(Maus* mw)
81+{
82+ MausBackend* be = &mw->backend;
83+
84+ if (!be->pointer)
85+ return;
86+
87+ wl_pointer_set_cursor(be->pointer, be->pointer_enter_serial, NULL, 0, 0);
88+}
89+
90+static void cursor_show(Maus* mw)
91+{
92+ MausBackend* be = &mw->backend;
93+ struct wl_cursor_image* image;
94+ struct wl_buffer* buffer;
95+
96+ if (!be->pointer || !be->cursor || !be->cursor_surface)
97+ return;
98+
99+ image = be->cursor->images[0];
100+ buffer = wl_cursor_image_get_buffer(image);
101+ if (!buffer)
102+ return;
103+
104+ wl_pointer_set_cursor(
105+ be->pointer, be->pointer_enter_serial,
106+ be->cursor_surface, image->hotspot_x, image->hotspot_y
107+ );
108+ wl_surface_attach(be->cursor_surface, buffer, 0, 0);
109+ wl_surface_damage_buffer(be->cursor_surface, 0, 0, image->width, image->height);
110+ wl_surface_commit(be->cursor_surface);
111+}
112+
113 static int8_t fb_create(Maus* mw);
114 static int8_t fb_create_shm(size_t size);
115 static void fb_destroy(Maus* mw);
116@@ -597,6 +682,8 @@ void maus_close(Maus* mw)
117 if (be->xkb_context)
118 xkb_context_unref(be->xkb_context);
119
120+ cursor_destroy(mw);
121+
122 if (be->wm_base)
123 xdg_wm_base_destroy(be->wm_base);
124
125@@ -695,11 +782,8 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
126 wl_display_roundtrip(be->display);
127
128 be->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
129- if (!be->xkb_context) {
130- maus_close(mw);
131- free(mw);
132- return NULL;
133- }
134+ if (!be->xkb_context)
135+ goto close;
136
137 if (!be->compositor || !be->shm || !be->wm_base) {
138 maus_close(mw);
139@@ -707,6 +791,9 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
140 return NULL;
141 }
142
143+ if (!cursor_init(mw))
144+ goto close;
145+
146 mw->frame_time_last = maus_get_time_ns();
147 mw->title = title;
148 mw->x = x;
149@@ -714,15 +801,17 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
150 mw->width = width;
151 mw->height = height;
152 mw->stride = width;
153+ be->cursor_state = MAUS_CURSOR_STATE_VISIBLE;
154
155 mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
156- if (!mw->bfb) {
157- maus_close(mw);
158- free(mw);
159- return NULL;
160- }
161+ if (!mw->bfb)
162+ goto close;
163
164 return mw;
165+close:
166+ maus_close(mw);
167+ free(mw);
168+ return NULL;
169 }
170
171 int8_t maus_event_poll(Maus* mw, MausEvent* ev)
172@@ -831,6 +920,21 @@ int8_t maus_resize(Maus* mw, uint32_t width, uint32_t height)
173
174 void maus_cur_set_mode(Maus* mw, MausCursorState state)
175 {
176-
177+ switch (state) {
178+ case MAUS_CURSOR_STATE_VISIBLE:
179+ cursor_show(mw);
180+ mw->backend.cursor_state = state;
181+ break;
182+ case MAUS_CURSOR_STATE_HIDDEN:
183+ cursor_hide(mw);
184+ mw->backend.cursor_state = state;
185+ break;
186+ case MAUS_CURSOR_STATE_LOCKED:
187+ /* TODO */
188+ case MAUS_CURSOR_STATE_FREE:
189+ /* TODO */
190+ default:
191+ break;
192+ }
193 }
194