Add keyboard to Lua API, make everything on lua->L balanced
This commit is contained in:
parent
3df162d3eb
commit
60c1c01616
12 changed files with 316 additions and 18 deletions
|
@ -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);
|
||||
|
|
|
@ -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 *
|
||||
|
|
16
include/luak/kiwmi_keyboard.h
Normal file
16
include/luak/kiwmi_keyboard.h
Normal 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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
191
kiwmi/luak/kiwmi_keyboard.c
Normal 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;
|
||||
}
|
|
@ -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},
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue