eufon/kiwmi/kiwmi/luak/kiwmi_cursor.c

400 lines
10 KiB
C

/* 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_cursor.h"
#include <linux/input-event-codes.h>
#include <lauxlib.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_pointer.h>
#include <wlr/util/log.h>
#include "desktop/view.h"
#include "input/cursor.h"
#include "luak/kiwmi_lua_callback.h"
#include "luak/kiwmi_output.h"
#include "luak/kiwmi_view.h"
#include "luak/lua_compat.h"
#include "luak/luak.h"
static int
l_kiwmi_cursor_output_at_pos(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
struct kiwmi_cursor *cursor = obj->object;
struct kiwmi_server *server = cursor->server;
struct wlr_output *wlr_output = wlr_output_layout_output_at(
server->desktop.output_layout, cursor->cursor->x, cursor->cursor->y);
if (wlr_output) {
lua_pushcfunction(L, luaK_kiwmi_output_new);
lua_pushlightuserdata(L, obj->lua);
lua_pushlightuserdata(L, wlr_output->data);
if (lua_pcall(L, 2, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
} else {
lua_pushnil(L);
}
return 1;
}
static int
l_kiwmi_cursor_pos(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
struct kiwmi_cursor *cursor = obj->object;
lua_pushnumber(L, cursor->cursor->x);
lua_pushnumber(L, cursor->cursor->y);
return 2;
}
static int
l_kiwmi_cursor_view_at_pos(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
struct kiwmi_lua *lua = obj->lua;
struct kiwmi_cursor *cursor = obj->object;
struct kiwmi_server *server = cursor->server;
struct wlr_surface *surface;
double sx;
double sy;
struct kiwmi_view *view = view_at(
&server->desktop,
cursor->cursor->x,
cursor->cursor->y,
&surface,
&sx,
&sy);
if (view) {
lua_pushcfunction(L, luaK_kiwmi_view_new);
lua_pushlightuserdata(L, lua);
lua_pushlightuserdata(L, view);
if (lua_pcall(L, 2, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
} else {
lua_pushnil(L);
}
return 1;
}
static const luaL_Reg kiwmi_cursor_methods[] = {
{"on", luaK_callback_register_dispatch},
{"output_at_pos", l_kiwmi_cursor_output_at_pos},
{"pos", l_kiwmi_cursor_pos},
{"view_at_pos", l_kiwmi_cursor_view_at_pos},
{NULL, NULL},
};
static void
kiwmi_cursor_on_button_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_cursor_button_event *event = data;
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
lua_pushinteger(L, event->wlr_event->button - BTN_LEFT + 1);
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);
}
static void
kiwmi_cursor_on_motion_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_cursor_motion_event *event = data;
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
lua_newtable(L);
lua_pushnumber(L, event->oldx);
lua_setfield(L, -2, "oldx");
lua_pushnumber(L, event->oldy);
lua_setfield(L, -2, "oldy");
lua_pushnumber(L, event->newx);
lua_setfield(L, -2, "newx");
lua_pushnumber(L, event->newy);
lua_setfield(L, -2, "newy");
if (lua_pcall(L, 1, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
}
static void
kiwmi_cursor_on_touch_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_cursor_touch_event *event = data;
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
lua_newtable(L);
lua_pushnumber(L, event->x);
lua_setfield(L, -2, "x");
lua_pushnumber(L, event->y);
lua_setfield(L, -2, "y");
lua_pushnumber(L, event->id);
lua_setfield(L, -2, "id");
lua_pushstring(L, event->event);
lua_setfield(L, -2, "name");
if (lua_pcall(L, 1, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
}
static void
kiwmi_cursor_on_scroll_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_cursor_scroll_event *event = data;
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
lua_newtable(L);
lua_pushstring(L, event->device_name);
lua_setfield(L, -2, "device");
lua_pushnumber(L, event->is_vertical);
lua_setfield(L, -2, "vertical");
lua_pushnumber(L, event->length);
lua_setfield(L, -2, "length");
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_cursor_on_button_down(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
luaL_checktype(L, 2, LUA_TFUNCTION);
struct kiwmi_cursor *cursor = obj->object;
struct kiwmi_server *server = cursor->server;
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_cursor_on_button_down_or_up_notify);
lua_pushlightuserdata(L, &cursor->events.button_down);
lua_pushlightuserdata(L, obj);
if (lua_pcall(L, 5, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 0;
}
static int
l_kiwmi_cursor_on_button_up(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
luaL_checktype(L, 2, LUA_TFUNCTION);
struct kiwmi_cursor *cursor = obj->object;
struct kiwmi_server *server = cursor->server;
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_cursor_on_button_down_or_up_notify);
lua_pushlightuserdata(L, &cursor->events.button_up);
lua_pushlightuserdata(L, obj);
if (lua_pcall(L, 5, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 0;
}
static int
l_kiwmi_cursor_on_motion(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
luaL_checktype(L, 2, LUA_TFUNCTION);
struct kiwmi_cursor *cursor = obj->object;
struct kiwmi_server *server = cursor->server;
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_cursor_on_motion_notify);
lua_pushlightuserdata(L, &cursor->events.motion);
lua_pushlightuserdata(L, obj);
if (lua_pcall(L, 5, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 0;
}
static int
l_kiwmi_cursor_on_touch(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
luaL_checktype(L, 2, LUA_TFUNCTION);
struct kiwmi_cursor *cursor = obj->object;
struct kiwmi_server *server = cursor->server;
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_cursor_on_touch_notify);
lua_pushlightuserdata(L, &cursor->events.touch);
lua_pushlightuserdata(L, obj);
if (lua_pcall(L, 5, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 0;
}
static int
l_kiwmi_cursor_on_scroll(lua_State *L)
{
struct kiwmi_object *obj =
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
luaL_checktype(L, 2, LUA_TFUNCTION);
struct kiwmi_cursor *cursor = obj->object;
struct kiwmi_server *server = cursor->server;
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
lua_pushlightuserdata(L, server);
lua_pushvalue(L, 2);
lua_pushlightuserdata(L, kiwmi_cursor_on_scroll_notify);
lua_pushlightuserdata(L, &cursor->events.scroll);
lua_pushlightuserdata(L, obj);
if (lua_pcall(L, 5, 0, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
return 0;
}
return 0;
}
static const luaL_Reg kiwmi_cursor_events[] = {
{"button_down", l_kiwmi_cursor_on_button_down},
{"button_up", l_kiwmi_cursor_on_button_up},
{"motion", l_kiwmi_cursor_on_motion},
{"touch", l_kiwmi_cursor_on_touch},
{"scroll", l_kiwmi_cursor_on_scroll},
{NULL, NULL},
};
int
luaK_kiwmi_cursor_new(lua_State *L)
{
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_lua
luaL_checktype(L, 2, LUA_TLIGHTUSERDATA); // kiwmi_cursor
struct kiwmi_lua *lua = lua_touserdata(L, 1);
struct kiwmi_cursor *cursor = lua_touserdata(L, 2);
struct kiwmi_object *obj =
luaK_get_kiwmi_object(lua, cursor, &cursor->events.destroy);
struct kiwmi_object **cursor_ud = lua_newuserdata(L, sizeof(*cursor_ud));
luaL_getmetatable(L, "kiwmi_cursor");
lua_setmetatable(L, -2);
*cursor_ud = obj;
return 1;
}
int
luaK_kiwmi_cursor_register(lua_State *L)
{
luaL_newmetatable(L, "kiwmi_cursor");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
luaC_setfuncs(L, kiwmi_cursor_methods, 0);
luaC_newlib(L, kiwmi_cursor_events);
lua_setfield(L, -2, "__events");
lua_pushcfunction(L, luaK_usertype_ref_equal);
lua_setfield(L, -2, "__eq");
lua_pushcfunction(L, luaK_kiwmi_object_gc);
lua_setfield(L, -2, "__gc");
return 0;
}