Differentiate between raw and translated keysyms
This commit is contained in:
parent
a736f0281b
commit
34f5f1fc37
4 changed files with 104 additions and 48 deletions
|
@ -8,6 +8,8 @@
|
||||||
#ifndef KIWMI_INPUT_KEYBOARD_H
|
#ifndef KIWMI_INPUT_KEYBOARD_H
|
||||||
#define KIWMI_INPUT_KEYBOARD_H
|
#define KIWMI_INPUT_KEYBOARD_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
@ -27,8 +29,11 @@ struct kiwmi_keyboard {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kiwmi_keyboard_key_event {
|
struct kiwmi_keyboard_key_event {
|
||||||
const xkb_keysym_t *syms;
|
const xkb_keysym_t *raw_syms;
|
||||||
int nsyms;
|
const xkb_keysym_t *translated_syms;
|
||||||
|
int raw_syms_len;
|
||||||
|
int translated_syms_len;
|
||||||
|
uint32_t keycode;
|
||||||
struct kiwmi_keyboard *keyboard;
|
struct kiwmi_keyboard *keyboard;
|
||||||
bool handled;
|
bool handled;
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,24 +59,36 @@ keyboard_key_notify(struct wl_listener *listener, void *data)
|
||||||
struct kiwmi_keyboard *keyboard = wl_container_of(listener, keyboard, key);
|
struct kiwmi_keyboard *keyboard = wl_container_of(listener, keyboard, key);
|
||||||
struct kiwmi_server *server = keyboard->server;
|
struct kiwmi_server *server = keyboard->server;
|
||||||
struct wlr_event_keyboard_key *event = data;
|
struct wlr_event_keyboard_key *event = data;
|
||||||
|
struct wlr_input_device *device = keyboard->device;
|
||||||
|
|
||||||
uint32_t keycode = event->keycode + 8;
|
uint32_t keycode = event->keycode + 8;
|
||||||
const xkb_keysym_t *syms;
|
|
||||||
int nsyms = xkb_state_key_get_syms(
|
const xkb_keysym_t *raw_syms;
|
||||||
keyboard->device->keyboard->xkb_state, keycode, &syms);
|
xkb_layout_index_t layout_index =
|
||||||
|
xkb_state_key_get_layout(device->keyboard->xkb_state, keycode);
|
||||||
|
int raw_syms_len = xkb_keymap_key_get_syms_by_level(
|
||||||
|
device->keyboard->keymap, keycode, layout_index, 0, &raw_syms);
|
||||||
|
|
||||||
|
const xkb_keysym_t *translated_syms;
|
||||||
|
int translated_syms_len = xkb_state_key_get_syms(
|
||||||
|
keyboard->device->keyboard->xkb_state, keycode, &translated_syms);
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
if (event->state == WLR_KEY_PRESSED) {
|
if (event->state == WLR_KEY_PRESSED) {
|
||||||
handled = switch_vt(syms, nsyms, server->backend);
|
handled =
|
||||||
|
switch_vt(translated_syms, translated_syms_len, server->backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
struct kiwmi_keyboard_key_event data = {
|
struct kiwmi_keyboard_key_event data = {
|
||||||
.syms = syms,
|
.raw_syms = raw_syms,
|
||||||
.nsyms = nsyms,
|
.translated_syms = translated_syms,
|
||||||
.keyboard = keyboard,
|
.raw_syms_len = raw_syms_len,
|
||||||
.handled = false,
|
.translated_syms_len = translated_syms_len,
|
||||||
|
.keycode = keycode,
|
||||||
|
.keyboard = keyboard,
|
||||||
|
.handled = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (event->state == WLR_KEY_PRESSED) {
|
if (event->state == WLR_KEY_PRESSED) {
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include "luak/kiwmi_keyboard.h"
|
#include "luak/kiwmi_keyboard.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <wlr/types/wlr_input_device.h>
|
#include <wlr/types/wlr_input_device.h>
|
||||||
|
@ -145,56 +147,88 @@ kiwmi_keyboard_on_destroy_notify(struct wl_listener *listener, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
send_key_event(
|
||||||
|
struct kiwmi_lua_callback *lc,
|
||||||
|
xkb_keysym_t sym,
|
||||||
|
uint32_t keycode,
|
||||||
|
struct kiwmi_keyboard *keyboard,
|
||||||
|
bool raw)
|
||||||
|
{
|
||||||
|
struct kiwmi_server *server = lc->server;
|
||||||
|
lua_State *L = server->lua->L;
|
||||||
|
|
||||||
|
static char keysym_name[64];
|
||||||
|
size_t namelen = xkb_keysym_get_name(sym, keysym_name, sizeof(keysym_name));
|
||||||
|
|
||||||
|
namelen = namelen > sizeof(keysym_name) ? sizeof(keysym_name) : namelen;
|
||||||
|
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
|
||||||
|
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
lua_pushlstring(L, keysym_name, namelen);
|
||||||
|
lua_setfield(L, -2, "key");
|
||||||
|
|
||||||
|
lua_pushnumber(L, keycode);
|
||||||
|
lua_setfield(L, -2, "keycode");
|
||||||
|
|
||||||
|
lua_pushboolean(L, raw);
|
||||||
|
lua_setfield(L, -2, "raw");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, luaK_kiwmi_keyboard_new);
|
||||||
|
lua_pushlightuserdata(L, server->lua);
|
||||||
|
lua_pushlightuserdata(L, keyboard);
|
||||||
|
if (lua_pcall(L, 2, 1, 0)) {
|
||||||
|
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lua_setfield(L, -2, "keyboard");
|
||||||
|
|
||||||
|
if (lua_pcall(L, 1, 1, 0)) {
|
||||||
|
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handled = lua_toboolean(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kiwmi_keyboard_on_key_down_or_up_notify(
|
kiwmi_keyboard_on_key_down_or_up_notify(
|
||||||
struct wl_listener *listener,
|
struct wl_listener *listener,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct kiwmi_lua_callback *lc = wl_container_of(listener, lc, listener);
|
struct kiwmi_lua_callback *lc = wl_container_of(listener, lc, listener);
|
||||||
struct kiwmi_server *server = lc->server;
|
|
||||||
lua_State *L = server->lua->L;
|
|
||||||
struct kiwmi_keyboard_key_event *event = data;
|
struct kiwmi_keyboard_key_event *event = data;
|
||||||
struct kiwmi_keyboard *keyboard = event->keyboard;
|
struct kiwmi_keyboard *keyboard = event->keyboard;
|
||||||
|
|
||||||
const xkb_keysym_t *syms = event->syms;
|
const xkb_keysym_t *raw_syms = event->raw_syms;
|
||||||
int nsyms = event->nsyms;
|
int raw_syms_len = event->raw_syms_len;
|
||||||
|
|
||||||
char keysym_name[64];
|
const xkb_keysym_t *translated_syms = event->translated_syms;
|
||||||
|
int translated_syms_len = event->translated_syms_len;
|
||||||
|
|
||||||
for (int i = 0; i < nsyms; ++i) {
|
uint32_t keycode = event->keycode;
|
||||||
xkb_keysym_t sym = syms[i];
|
|
||||||
|
|
||||||
size_t namelen =
|
bool handled = false;
|
||||||
xkb_keysym_get_name(sym, keysym_name, sizeof(keysym_name));
|
|
||||||
|
|
||||||
namelen = namelen > sizeof(keysym_name) ? sizeof(keysym_name) : namelen;
|
for (int i = 0; i < translated_syms_len; ++i) {
|
||||||
|
xkb_keysym_t sym = translated_syms[i];
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
|
handled |= send_key_event(lc, sym, keycode, keyboard, false);
|
||||||
|
|
||||||
lua_newtable(L);
|
|
||||||
|
|
||||||
lua_pushlstring(L, keysym_name, namelen);
|
|
||||||
lua_setfield(L, -2, "key");
|
|
||||||
|
|
||||||
lua_pushcfunction(L, luaK_kiwmi_keyboard_new);
|
|
||||||
lua_pushlightuserdata(L, server->lua);
|
|
||||||
lua_pushlightuserdata(L, keyboard);
|
|
||||||
if (lua_pcall(L, 2, 1, 0)) {
|
|
||||||
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lua_setfield(L, -2, "keyboard");
|
|
||||||
|
|
||||||
if (lua_pcall(L, 1, 1, 0)) {
|
|
||||||
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event->handled |= lua_toboolean(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
for (int i = 0; i < raw_syms_len; ++i) {
|
||||||
|
xkb_keysym_t sym = raw_syms[i];
|
||||||
|
handled |= send_key_event(lc, sym, keycode, keyboard, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event->handled = handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -139,7 +139,10 @@ Callback receives the keyboard.
|
||||||
#### key_down
|
#### key_down
|
||||||
|
|
||||||
A key got pressed.
|
A key got pressed.
|
||||||
Callback receives a table containing the `key` and the `keyboard`).
|
|
||||||
|
Callback receives a table containing the `key`, `keycode`, `raw`, and the `keyboard`.
|
||||||
|
|
||||||
|
This event gets triggered twice, once with mods applied (i.e. `Shift+3` is `#`) and `raw` set to `false`, and then again with no mods applied and `raw` set to `true`.
|
||||||
|
|
||||||
The callback is supposed to return `true` if the event was handled.
|
The callback is supposed to return `true` if the event was handled.
|
||||||
The compositor will not forward it to the focused view in that case.
|
The compositor will not forward it to the focused view in that case.
|
||||||
|
@ -147,7 +150,9 @@ The compositor will not forward it to the focused view in that case.
|
||||||
#### key_up
|
#### key_up
|
||||||
|
|
||||||
A key got released.
|
A key got released.
|
||||||
Callback receives a table containing the `key` and the `keyboard`).
|
Callback receives a table containing the `key`, `keycode`, `raw`, and the `keyboard`.
|
||||||
|
|
||||||
|
This event gets triggered twice, once with mods applied (i.e. `Shift+3` is `#`) and `raw` set to `false`, and then again with no mods applied and `raw` set to `true`.
|
||||||
|
|
||||||
The callback is supposed to return `true` if the event was handled.
|
The callback is supposed to return `true` if the event was handled.
|
||||||
The compositor will not forward it to the focused view in that case.
|
The compositor will not forward it to the focused view in that case.
|
||||||
|
|
Loading…
Reference in a new issue