Skip to content

Commit dafa33f

Browse files
committed
Add keyboard listener callback for wayland
Signed-off-by: gujie <jie.gu@leica-geosystems.com.cn>
1 parent 5eb1be5 commit dafa33f

File tree

2 files changed

+140
-3
lines changed

2 files changed

+140
-3
lines changed

src/wayland/wl_seat.c

Lines changed: 136 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
#include "../settings.h"
2020
#include "wl_ctx.h"
2121

22+
#include <xkbcommon/xkbcommon.h>
23+
#include <sys/mman.h>
24+
#include <unistd.h>
25+
26+
static struct xkb_context *xkb_context = NULL;
27+
static struct xkb_state *xkb_state = NULL;
28+
2229
static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
2330
uint32_t time, int32_t id,
2431
wl_fixed_t surface_x, wl_fixed_t surface_y) {
@@ -46,7 +53,6 @@ static void touch_handle_down(void *data, struct wl_touch *wl_touch,
4653
static void touch_handle_up(void *data, struct wl_touch *wl_touch,
4754
uint32_t serial, uint32_t time, int32_t id) {
4855
struct dunst_seat *seat = data;
49-
5056
if (id >= MAX_TOUCHPOINTS) {
5157
return;
5258
}
@@ -99,7 +105,6 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
99105
uint32_t serial, uint32_t time, uint32_t button,
100106
uint32_t button_state) {
101107
struct dunst_seat *seat = data;
102-
103108
input_handle_click(button, button_state, seat->pointer.x, seat->pointer.y);
104109
}
105110

@@ -119,6 +124,116 @@ static const struct wl_pointer_listener pointer_listener = {
119124
.axis = pointer_handle_axis,
120125
};
121126

127+
static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
128+
uint32_t format, int32_t fd, uint32_t size) {
129+
130+
struct dunst_seat *seat = data;
131+
(void)seat;
132+
133+
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
134+
close(fd);
135+
return;
136+
}
137+
138+
char *keymap_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
139+
if (keymap_str == MAP_FAILED) {
140+
close(fd);
141+
return;
142+
}
143+
144+
if (!xkb_context)
145+
xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
146+
147+
struct xkb_keymap *keymap = xkb_keymap_new_from_string(xkb_context,
148+
keymap_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
149+
150+
munmap(keymap_str, size);
151+
close(fd);
152+
153+
if (!keymap)
154+
return;
155+
156+
if (xkb_state)
157+
xkb_state_unref(xkb_state);
158+
159+
xkb_state = xkb_state_new(keymap);
160+
xkb_keymap_unref(keymap);
161+
}
162+
163+
static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
164+
uint32_t serial, struct wl_surface *surface,
165+
struct wl_array *keys) {
166+
167+
struct dunst_seat *seat = data;
168+
(void)seat;
169+
}
170+
171+
static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
172+
uint32_t serial, struct wl_surface *surface) {
173+
174+
struct dunst_seat *seat = data;
175+
(void)seat;
176+
}
177+
178+
static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
179+
uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
180+
181+
struct dunst_seat *seat = data;
182+
(void)seat;
183+
184+
if (!xkb_state)
185+
return;
186+
187+
uint32_t keycode = key + 8; // XKB uses evdev + 8 keycode convention
188+
xkb_keysym_t keysym = xkb_state_key_get_one_sym(xkb_state, keycode);
189+
190+
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
191+
input_handle_key(keysym, true);
192+
} else {
193+
input_handle_key(keysym, false);
194+
}
195+
}
196+
197+
static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
198+
uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
199+
uint32_t mods_locked, uint32_t group) {
200+
if (!xkb_state)
201+
return;
202+
203+
xkb_state_update_mask(xkb_state, mods_depressed, mods_latched,
204+
mods_locked, 0, 0, group);
205+
}
206+
207+
static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
208+
int32_t rate, int32_t delay) {
209+
// store the repeat info if needed
210+
// rate: repeat times per second
211+
// delay: delay in milliseconds
212+
LOG_D("Keyboard repeat info - rate: %d, delay: %d", rate, delay);
213+
}
214+
215+
static const struct wl_keyboard_listener keyboard_listener = {
216+
.keymap = keyboard_handle_keymap,
217+
.enter = keyboard_handle_enter,
218+
.leave = keyboard_handle_leave,
219+
.key = keyboard_handle_key,
220+
.modifiers = keyboard_handle_modifiers,
221+
.repeat_info = keyboard_handle_repeat_info,
222+
};
223+
224+
// cleanup xkb resources
225+
void cleanup_keyboard_resources(void) {
226+
if (xkb_state) {
227+
xkb_state_unref(xkb_state);
228+
xkb_state = NULL;
229+
}
230+
231+
if (xkb_context) {
232+
xkb_context_unref(xkb_context);
233+
xkb_context = NULL;
234+
}
235+
}
236+
122237
static void destroy_seat_pointer(struct dunst_seat *seat) {
123238
wl_pointer_release(seat->pointer.wl_pointer);
124239
seat->pointer.wl_pointer = NULL;
@@ -129,6 +244,11 @@ static void destroy_seat_touch(struct dunst_seat *seat) {
129244
seat->touch.wl_touch = NULL;
130245
}
131246

247+
static void destroy_seat_keyboard(struct dunst_seat *seat) {
248+
wl_keyboard_release(seat->keyboard.wl_keyboard);
249+
seat->keyboard.wl_keyboard = NULL;
250+
}
251+
132252
void destroy_seat(struct dunst_seat *seat) {
133253
if (seat == NULL) {
134254
return;
@@ -170,12 +290,15 @@ void destroy_seat(struct dunst_seat *seat) {
170290
seat->name = NULL;
171291

172292
g_free(seat);
293+
294+
if (wl_list_empty(&ctx.seats)) {
295+
cleanup_keyboard_resources();
296+
}
173297
}
174298

175299
static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
176300
uint32_t capabilities) {
177301
struct dunst_seat *seat = data;
178-
179302
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
180303
if (seat->pointer.wl_pointer == NULL) {
181304
seat->pointer.wl_pointer = wl_seat_get_pointer(wl_seat);
@@ -195,6 +318,16 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
195318
} else if (seat->touch.wl_touch != NULL) {
196319
destroy_seat_touch(seat);
197320
}
321+
322+
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
323+
if(seat->keyboard.wl_keyboard == NULL) {
324+
seat->keyboard.wl_keyboard = wl_seat_get_keyboard(wl_seat);
325+
wl_keyboard_add_listener(seat->keyboard.wl_keyboard,
326+
&keyboard_listener, seat);
327+
}
328+
} else if (seat->keyboard.wl_keyboard != NULL) {
329+
destroy_seat_keyboard(seat);
330+
}
198331
}
199332

200333
static void seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name) {

src/wayland/wl_seat.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ struct dunst_seat {
4141
int32_t x, y;
4242
} pts[MAX_TOUCHPOINTS];
4343
} touch;
44+
45+
struct {
46+
struct wl_keyboard *wl_keyboard;
47+
} keyboard;
4448
};
4549

4650
void create_seat(struct wl_registry *registry, uint32_t global_name, uint32_t version);

0 commit comments

Comments
 (0)