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