ref: dd03ed16b32bb83bca47fa916291102f9cc78f4b
parent: 4d482dfbd85fd0e4311d14566cbc6b49240e7b95
author: Jacob Moody <moody@posixcafe.org>
date: Tue Oct 12 05:21:32 EDT 2021
wayland: handle arrow keys and key repeat
--- a/gui-wl/wl-cb.c
+++ b/gui-wl/wl-cb.c
@@ -112,7 +112,59 @@
qunlock(&wl->clip.lk);
}
+static struct {
+ Rendez z;
+ QLock lk;
+ int active;
+ int32_t key;
+ int32_t rate;
+ int32_t delay;
+} repeatstate;
+
+static int
+isactive(void *arg)
+{
+ return repeatstate.active;
+}
+
+void
+repeatproc(void*)
+{
+ int ms;
+ int32_t key;
+
+ for(;;){
+ ksleep(&repeatstate.z, isactive, 0);
+ qlock(&repeatstate.lk);
+ key = repeatstate.key;
+ qunlock(&repeatstate.lk);
+ osmsleep(repeatstate.delay);
+
+repeat:
+ qlock(&repeatstate.lk);
+ if(repeatstate.active == 0 || key != repeatstate.key){
+ qunlock(&repeatstate.lk);
+ continue;
+ }
+ ms = 1000/repeatstate.rate;
+ kbdkey(repeatstate.key, 0);
+ kbdkey(repeatstate.key, 1);
+ qunlock(&repeatstate.lk);
+ osmsleep(ms);
+ goto repeat;
+ }
+}
+
static void
+keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay)
+{
+ qlock(&repeatstate.lk);
+ repeatstate.rate = rate;
+ repeatstate.delay = delay;
+ qunlock(&repeatstate.lk);
+}
+
+static void
keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
{
}
@@ -132,16 +184,35 @@
case XKB_KEY_Tab:
utf32 = '\t';
break;
+ case XKB_KEY_Up:
+ utf32 = Kup;
+ break;
+ case XKB_KEY_Down:
+ utf32 = Kdown;
+ break;
+ case XKB_KEY_Left:
+ utf32 = Kleft;
+ break;
+ case XKB_KEY_Right:
+ utf32 = Kright;
+ break;
default:
utf32 = xkb_keysym_to_utf32(keysym);
break;
}
+ if(utf32 == 0)
+ return;
+
if(xkb_state_mod_name_is_active(wl->xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0)
if(utf32 >= 'a' && utf32 <= 'z')
utf32 -= ('a' - 1);
- if(utf32){
- kbdkey(utf32, state);
- }
+
+ kbdkey(utf32, state);
+ qlock(&repeatstate.lk);
+ repeatstate.active = state;
+ repeatstate.key = utf32;
+ qunlock(&repeatstate.lk);
+ wakeup(&repeatstate.z);
}
static void
@@ -158,11 +229,12 @@
};
static struct wl_keyboard_listener keyboard_listener = {
- &keyboard_keymap,
- &keyboard_enter,
- &keyboard_leave,
- &keyboard_key,
- &keyboard_modifiers
+ .keymap = keyboard_keymap,
+ .enter = keyboard_enter,
+ .leave = keyboard_leave,
+ .key = keyboard_key,
+ .modifiers = keyboard_modifiers,
+ .repeat_info = keyboard_repeat_info,
};
enum{
@@ -229,6 +301,8 @@
wl = data;
wl->pointerserial = serial;
+ if(wl->cursorsurface == nil)
+ return;
wl_pointer_set_cursor(wl->pointer, wl->pointerserial, wl->cursorsurface, 0, 0);
}
@@ -282,8 +356,15 @@
}
}
+static void
+seat_handle_name(void *data, struct wl_seat *seat, const char *name)
+{
+
+}
+
static const struct wl_seat_listener seat_listener = {
.capabilities = seat_handle_capabilities,
+ .name = seat_handle_name,
};
static void
@@ -391,7 +472,7 @@
if(strcmp(interface, wl_shm_interface.name) == 0) {
wl->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
} else if(strcmp(interface, wl_seat_interface.name) == 0) {
- wl->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1);
+ wl->seat = wl_registry_bind(registry, name, &wl_seat_interface, 4);
wl_seat_add_listener(wl->seat, &seat_listener, wl);
} else if(strcmp(interface, wl_compositor_interface.name) == 0) {
wl->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
@@ -422,6 +503,13 @@
struct xdg_surface *xdg_surface;
struct wl_callback *cb;
struct zxdg_toplevel_decoration_v1 *deco;
+
+ //Wayland doesn't do keyboard repeat, but also may
+ //not tell us what the user would like, so we
+ //pick some sane defaults.
+ repeatstate.delay = 200;
+ repeatstate.rate = 20;
+ kproc("keyboard repeat", repeatproc, 0);
registry = wl_display_get_registry(wl->display);
wl_registry_add_listener(registry, ®istry_listener, wl);