Add keyboard to Lua API, make everything on lua->L balanced

This commit is contained in:
buffet 2020-01-04 23:22:45 +00:00
parent 3df162d3eb
commit 60c1c01616
12 changed files with 316 additions and 18 deletions

View file

@ -15,6 +15,10 @@ struct kiwmi_input {
struct wl_listener new_input;
struct kiwmi_cursor *cursor;
struct wlr_seat *seat;
struct {
struct wl_signal keyboard_new;
} events;
};
bool input_init(struct kiwmi_input *input);

View file

@ -9,6 +9,7 @@
#define KIWMI_INPUT_KEYBOARD_H
#include <wayland-server.h>
#include <xkbcommon/xkbcommon.h>
struct kiwmi_keyboard {
struct wl_list link;
@ -16,6 +17,18 @@ struct kiwmi_keyboard {
struct wlr_input_device *device;
struct wl_listener modifiers;
struct wl_listener key;
struct {
struct wl_signal key_down;
struct wl_signal key_up;
} events;
};
struct kiwmi_keyboard_key_event {
const xkb_keysym_t *syms;
int nsyms;
struct kiwmi_keyboard *keyboard;
bool handled;
};
struct kiwmi_keyboard *

View file

@ -0,0 +1,16 @@
/* Copyright (c), Niclas Meyer <niclas@countingsort.com>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef KIWMI_LUAK_KIWMI_KEYBOARD_H
#define KIWMI_LUAK_KIWMI_KEYBOARD_H
#include <lua.h>
int luaK_kiwmi_keyboard_new(lua_State *L);
int luaK_kiwmi_keyboard_register(lua_State *L);
#endif /* KIWMI_LUAK_KIWMI_KEYBOARD_H */

View file

@ -84,5 +84,7 @@ input_init(struct kiwmi_input *input)
input->new_input.notify = new_input_notify;
wl_signal_add(&server->backend->events.new_input, &input->new_input);
wl_signal_init(&input->events.keyboard_new);
return true;
}

View file

@ -62,25 +62,28 @@ keyboard_key_notify(struct wl_listener *listener, void *data)
const xkb_keysym_t *syms;
int nsyms = xkb_state_key_get_syms(
keyboard->device->keyboard->xkb_state, keycode, &syms);
uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
bool handled = false;
if (event->state == WLR_KEY_PRESSED) {
handled = switch_vt(syms, nsyms, server->backend);
}
if (!handled && (modifiers & WLR_MODIFIER_LOGO)) {
for (int i = 0; i < nsyms; ++i) {
xkb_keysym_t sym = syms[i];
if (!handled) {
struct kiwmi_keyboard_key_event data = {
.syms = syms,
.nsyms = nsyms,
.keyboard = keyboard,
.handled = false,
};
switch (sym) {
case XKB_KEY_Escape:
wl_display_terminate(server->wl_display);
handled = true;
break;
}
}
if (event->state == WLR_KEY_PRESSED) {
wl_signal_emit(&keyboard->events.key_down, &data);
} else {
wl_signal_emit(&keyboard->events.key_up, &data);
}
handled = data.handled;
}
if (!handled) {
@ -121,5 +124,10 @@ keyboard_create(struct kiwmi_server *server, struct wlr_input_device *device)
wlr_seat_set_keyboard(server->input.seat, device);
wl_signal_init(&keyboard->events.key_down);
wl_signal_init(&keyboard->events.key_up);
wl_signal_emit(&server->input.events.keyboard_new, keyboard);
return keyboard;
}

View file

@ -32,6 +32,7 @@ ipc_eval(
wlr_log(WLR_ERROR, "Error running IPC command: %s", error);
kiwmi_command_send_done(
command_resource, KIWMI_COMMAND_ERROR_FAILURE, error);
lua_pop(L, 1);
return;
}
@ -44,6 +45,8 @@ ipc_eval(
kiwmi_command_send_done(
command_resource, KIWMI_COMMAND_ERROR_SUCCESS, lua_tostring(L, -1));
}
lua_pop(L, results);
}
static const struct kiwmi_ipc_interface kiwmi_ipc_implementation = {

191
kiwmi/luak/kiwmi_keyboard.c Normal file
View file

@ -0,0 +1,191 @@
/* Copyright (c), Niclas Meyer <niclas@countingsort.com>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "luak/kiwmi_keyboard.h"
#include <lauxlib.h>
#include <wayland-server.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/util/log.h>
#include "input/keyboard.h"
#include "luak/kiwmi_lua_callback.h"
static int
l_kiwmi_keyboard_modifiers(lua_State *L)
{
struct kiwmi_keyboard *keyboard =
*(struct kiwmi_keyboard **)luaL_checkudata(L, 1, "kiwmi_keyboard");
uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
lua_newtable(L);
lua_pushboolean(L, modifiers & WLR_MODIFIER_SHIFT);
lua_setfield(L, -2, "shift");
lua_pushboolean(L, modifiers & WLR_MODIFIER_CAPS);
lua_setfield(L, -2, "caps");
lua_pushboolean(L, modifiers & WLR_MODIFIER_CTRL);
lua_setfield(L, -2, "ctrl");
lua_pushboolean(L, modifiers & WLR_MODIFIER_ALT);
lua_setfield(L, -2, "alt");
lua_pushboolean(L, modifiers & WLR_MODIFIER_MOD2);
lua_setfield(L, -2, "mod2");
lua_pushboolean(L, modifiers & WLR_MODIFIER_MOD3);
lua_setfield(L, -2, "mod3");
lua_pushboolean(L, modifiers & WLR_MODIFIER_LOGO);
lua_setfield(L, -2, "super");
lua_pushboolean(L, modifiers & WLR_MODIFIER_MOD5);
lua_setfield(L, -2, "mod5");
return 1;
}
static const luaL_Reg kiwmi_keyboard_methods[] = {
{"modifiers", l_kiwmi_keyboard_modifiers},
{"on", luaK_callback_register_dispatch},
{NULL, NULL},
};
static void
kiwmi_keyboard_on_key_down_or_up_notify(
struct wl_listener *listener,
void *data)
{
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 *keyboard = event->keyboard;
const xkb_keysym_t *syms = event->syms;
int nsyms = event->nsyms;
char keysym_name[64];
for (int i = 0; i < nsyms; ++i) {
xkb_keysym_t sym = syms[i];
int namelen =
xkb_keysym_get_name(sym, keysym_name, sizeof(keysym_name));
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
lua_newtable(L);
lua_pushlstring(L, keysym_name, namelen);
lua_setfield(L, -2, "key");
lua_pushcfunction(L, luaK_kiwmi_keyboard_new);
lua_pushlightuserdata(L, keyboard);
if (lua_pcall(L, 1, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
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);
}
event->handled |= lua_toboolean(L, -1);
lua_pop(L, 1);
}
}
static int
l_kiwmi_keyboard_on_key_down(lua_State *L)
{
struct kiwmi_keyboard *keyboard =
*(struct kiwmi_keyboard **)luaL_checkudata(L, 1, "kiwmi_keyboard");
luaL_checktype(L, 2, LUA_TFUNCTION);
struct kiwmi_server *server = keyboard->server;
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_keyboard_on_key_down_or_up_notify);
lua_pushlightuserdata(L, &keyboard->events.key_down);
if (lua_pcall(L, 4, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 1;
}
static int
l_kiwmi_keyboard_on_key_up(lua_State *L)
{
struct kiwmi_keyboard *keyboard =
*(struct kiwmi_keyboard **)luaL_checkudata(L, 1, "kiwmi_keyboard");
luaL_checktype(L, 2, LUA_TFUNCTION);
struct kiwmi_server *server = keyboard->server;
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_keyboard_on_key_down_or_up_notify);
lua_pushlightuserdata(L, &keyboard->events.key_up);
if (lua_pcall(L, 4, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 1;
}
static const luaL_Reg kiwmi_keyboard_events[] = {
{"key_down", l_kiwmi_keyboard_on_key_down},
{"key_up", l_kiwmi_keyboard_on_key_up},
{NULL, NULL},
};
int
luaK_kiwmi_keyboard_new(lua_State *L)
{
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_keyboard
struct kiwmi_keyboard *keyboard = lua_touserdata(L, 1);
struct kiwmi_keyboard **keyboard_ud =
lua_newuserdata(L, sizeof(*keyboard_ud));
luaL_getmetatable(L, "kiwmi_keyboard");
lua_setmetatable(L, -2);
*keyboard_ud = keyboard;
return 1;
}
int
luaK_kiwmi_keyboard_register(lua_State *L)
{
luaL_newmetatable(L, "kiwmi_keyboard");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
luaL_setfuncs(L, kiwmi_keyboard_methods, 0);
luaL_newlib(L, kiwmi_keyboard_events);
lua_setfield(L, -2, "__events");
return 0;
}

View file

@ -18,6 +18,7 @@
#include "desktop/view.h"
#include "input/cursor.h"
#include "luak/kiwmi_keyboard.h"
#include "luak/kiwmi_lua_callback.h"
#include "luak/kiwmi_view.h"
#include "server.h"
@ -118,6 +119,30 @@ static const luaL_Reg kiwmi_server_methods[] = {
{NULL, NULL},
};
static void
kiwmi_server_on_keyboard_notify(struct wl_listener *listener, void *data)
{
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 *keyboard = data;
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
lua_pushcfunction(L, luaK_kiwmi_keyboard_new);
lua_pushlightuserdata(L, keyboard);
if (lua_pcall(L, 1, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
return;
}
if (lua_pcall(L, 1, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
}
static void
kiwmi_server_on_view_notify(struct wl_listener *listener, void *data)
{
@ -132,13 +157,37 @@ kiwmi_server_on_view_notify(struct wl_listener *listener, void *data)
lua_pushlightuserdata(L, view);
if (lua_pcall(L, 1, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
return;
}
if (lua_pcall(L, 1, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
}
static int
l_kiwmi_server_on_keyboard(lua_State *L)
{
struct kiwmi_server *server =
*(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server");
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_server_on_keyboard_notify);
lua_pushlightuserdata(L, &server->input.events.keyboard_new);
if (lua_pcall(L, 4, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 1;
}
static int
l_kiwmi_server_on_view(lua_State *L)
{
@ -161,6 +210,7 @@ l_kiwmi_server_on_view(lua_State *L)
}
static const luaL_Reg kiwmi_server_events[] = {
{"keyboard", l_kiwmi_server_on_keyboard},
{"view", l_kiwmi_server_on_view},
{NULL, NULL},
};

View file

@ -110,10 +110,13 @@ kiwmi_view_on_destroy_notify(struct wl_listener *listener, void *data)
if (lua_pcall(L, 1, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
return;
}
if (lua_pcall(L, 1, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
}

View file

@ -14,6 +14,7 @@
#include <wlr/util/log.h>
#include "luak/ipc.h"
#include "luak/kiwmi_keyboard.h"
#include "luak/kiwmi_lua_callback.h"
#include "luak/kiwmi_server.h"
#include "luak/kiwmi_view.h"
@ -64,12 +65,14 @@ luaK_create(struct kiwmi_server *server)
// register types
int error = 0;
lua_pushcfunction(L, luaK_kiwmi_keyboard_register);
error |= lua_pcall(L, 0, 0, 0);
lua_pushcfunction(L, luaK_kiwmi_lua_callback_register);
error |= lua_pcall(L, 0, 0, 0);
lua_pushcfunction(L, luaK_kiwmi_view_register);
error |= lua_pcall(L, 0, 0, 0);
lua_pushcfunction(L, luaK_kiwmi_server_register);
error |= lua_pcall(L, 0, 0, 0);
lua_pushcfunction(L, luaK_kiwmi_view_register);
error |= lua_pcall(L, 0, 0, 0);
if (error) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
@ -106,12 +109,16 @@ luaK_create(struct kiwmi_server *server)
bool
luaK_dofile(struct kiwmi_lua *lua, const char *config_path)
{
int top = lua_gettop(lua->L);
if (luaL_dofile(lua->L, config_path)) {
wlr_log(
WLR_ERROR, "Error running config: %s", lua_tostring(lua->L, -1));
return false;
}
lua_pop(lua->L, top - lua_gettop(lua->L));
return true;
}

View file

@ -9,6 +9,7 @@ kiwmi_sources = files(
'input/input.c',
'input/keyboard.c',
'luak/ipc.c',
'luak/kiwmi_keyboard.c',
'luak/kiwmi_lua_callback.c',
'luak/kiwmi_server.c',
'luak/kiwmi_view.c',

View file

@ -102,15 +102,15 @@ server_run(struct kiwmi_server *server)
wlr_log(
WLR_DEBUG, "Running Wayland server on display '%s'", server->socket);
if (!wlr_backend_start(server->backend)) {
wlr_log(WLR_ERROR, "Failed to start backend");
setenv("WAYLAND_DISPLAY", server->socket, true);
if (!luaK_dofile(server->lua, server->config_path)) {
wl_display_destroy(server->wl_display);
return false;
}
setenv("WAYLAND_DISPLAY", server->socket, true);
if (!luaK_dofile(server->lua, server->config_path)) {
if (!wlr_backend_start(server->backend)) {
wlr_log(WLR_ERROR, "Failed to start backend");
wl_display_destroy(server->wl_display);
return false;
}