untested keyboard support

This commit is contained in:
IoIxD 2025-12-08 17:11:42 -07:00
commit 36ed559da1
2 changed files with 108 additions and 19 deletions

View file

@ -44,6 +44,8 @@ struct _MwLLWaylandTopLevel {
struct xdg_surface_listener xdg_surface_listener;
struct xkb_context* xkb_context;
struct xkb_keymap* xkb_keymap;
struct xkb_state* xkb_state;
MwBool compositor_created;
MwBool xdg_wm_base_created;

View file

@ -16,13 +16,12 @@
#else
#include <linux/input.h>
#endif
/*
callback todo:
void (*key)(MwLL handle, void* data);
void (*key_released)(MwLL handle, void* data);
void (*focus_in)(MwLL handle, void* data);
void (*focus_out)(MwLL handle, void* data);
*/
* GENERAL TODO:
* comment the file lmao
* make sure MwLLDestroy is finished (+ handle dropdown bug that results from it)
*/
static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer);
@ -50,9 +49,11 @@ static void protocol_removed(void* data,
static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 serial,
struct wl_surface* surface, wl_fixed_t surface_x,
wl_fixed_t surface_y) {};
wl_fixed_t surface_y) {
};
static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial,
struct wl_surface* surface) {};
struct wl_surface* surface) {
};
static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time,
wl_fixed_t surface_x, wl_fixed_t surface_y) {
MwLL self = data;
@ -103,6 +104,102 @@ struct wl_pointer_listener pointer_listener = {
.axis = pointer_axis,
};
static void keyboard_keymap(void* data,
struct wl_keyboard* wl_keyboard,
uint32_t format,
int32_t fd,
uint32_t size) {
MwLL self = data;
if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
struct _MwLLWaylandTopLevel* wayland = self->wayland.toplevel;
assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
char* map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
assert(map_shm != MAP_FAILED);
struct xkb_keymap* xkb_keymap = xkb_keymap_new_from_string(
wayland->xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(map_shm, size);
close(fd);
struct xkb_state* xkb_state = xkb_state_new(xkb_keymap);
xkb_keymap_unref(wayland->xkb_keymap);
xkb_state_unref(wayland->xkb_state);
wayland->xkb_keymap = xkb_keymap;
wayland->xkb_state = xkb_state;
}
};
static void keyboard_enter(void* data,
struct wl_keyboard* wl_keyboard,
uint32_t serial,
struct wl_surface* surface,
struct wl_array* keys) {
MwLL self = data;
MwLLDispatch(self, focus_in, NULL);
};
static void keyboard_leave(void* data,
struct wl_keyboard* wl_keyboard,
uint32_t serial,
struct wl_surface* surface) {
MwLL self = data;
MwLLDispatch(self, focus_out, NULL);
};
static void keyboard_key(void* data,
struct wl_keyboard* wl_keyboard,
uint32_t serial,
uint32_t time,
uint32_t key,
uint32_t state) {
MwLL self = data;
if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
struct _MwLLWaylandTopLevel* wayland = self->wayland.toplevel;
xkb_layout_index_t layout;
xkb_level_index_t level;
const xkb_keysym_t* syms_out;
MwU32 keycode = key + 8;
MwU64 syms_num;
int i;
if(!wayland->xkb_keymap) {
return;
}
layout = xkb_state_key_get_layout(wayland->xkb_state, keycode);
level =
xkb_keymap_num_levels_for_key(wayland->xkb_keymap, keycode, layout) - 1;
syms_num = xkb_keymap_key_get_syms_by_level(wayland->xkb_keymap, keycode, layout, level, &syms_out);
if(syms_out == NULL) {
return;
}
for(i = 0; i < syms_num; i++) {
int sym = syms_out[i];
if(state == WL_KEYBOARD_KEY_STATE_PRESSED) {
MwLLDispatch(self, key, &sym);
} else {
MwLLDispatch(self, key_released, &sym);
}
}
}
};
static void keyboard_modifiers(void* data,
struct wl_keyboard* wl_keyboard,
uint32_t serial,
uint32_t mods_depressed,
uint32_t mods_latched,
uint32_t mods_locked,
uint32_t group) {};
struct wl_keyboard_listener keyboard_listener = {
.keymap = keyboard_keymap,
.enter = keyboard_enter,
.leave = keyboard_leave,
.key = keyboard_key,
.modifiers = keyboard_modifiers,
};
static void
wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {};
static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
@ -110,7 +207,7 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
MwLL self = data;
if(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
struct wl_keyboard* keyboard = wl_seat_get_keyboard(wl_seat);
// wl_keyboard_add_listener(keyboard, const struct wl_keyboard_listener* listener, data);
wl_keyboard_add_listener(keyboard, &keyboard_listener, data);
}
if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) {
self->wayland.pointer = wl_seat_get_pointer(wl_seat);
@ -490,16 +587,6 @@ static void setup_toplevel(MwLL r, int x, int y) {
return;
}
// Check that all globals we require are available
if(
r->wayland.compositor == NULL ||
WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context == NULL) {
printf("no xdg_wm_base support\n");
raise(SIGTRAP);
return;
}
r->wayland.toplevel->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
// Create a wl_surface, a xdg_surface and a xdg_toplevel