diff --git a/include/desktop/desktop.h b/include/desktop/desktop.h index ad22516..1995b0c 100644 --- a/include/desktop/desktop.h +++ b/include/desktop/desktop.h @@ -24,6 +24,7 @@ struct kiwmi_desktop { struct wl_listener new_output; struct { + struct wl_signal new_output; struct wl_signal view_map; } events; }; diff --git a/include/desktop/output.h b/include/desktop/output.h index 006ecdd..f789bc2 100644 --- a/include/desktop/output.h +++ b/include/desktop/output.h @@ -16,6 +16,10 @@ struct kiwmi_output { struct wlr_output *wlr_output; struct wl_listener frame; struct wl_listener destroy; + + struct { + struct wl_signal destroy; + } events; }; void new_output_notify(struct wl_listener *listener, void *data); diff --git a/include/luak/kiwmi_output.h b/include/luak/kiwmi_output.h new file mode 100644 index 0000000..85a664a --- /dev/null +++ b/include/luak/kiwmi_output.h @@ -0,0 +1,16 @@ +/* Copyright (c), Niclas Meyer + * + * 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_OUTPUT_H +#define KIWMI_LUAK_KIWMI_OUTPUT_H + +#include + +int luaK_kiwmi_output_new(lua_State *L); +int luaK_kiwmi_output_register(lua_State *L); + +#endif /* KIWMI_LUAK_KIWMI_OUTPUT_H */ diff --git a/kiwmi/desktop/desktop.c b/kiwmi/desktop/desktop.c index 6399958..f9b9c5d 100644 --- a/kiwmi/desktop/desktop.c +++ b/kiwmi/desktop/desktop.c @@ -49,6 +49,7 @@ desktop_init(struct kiwmi_desktop *desktop, struct wlr_renderer *renderer) desktop->new_output.notify = new_output_notify; wl_signal_add(&server->backend->events.new_output, &desktop->new_output); + wl_signal_init(&desktop->events.new_output); wl_signal_init(&desktop->events.view_map); return true; diff --git a/kiwmi/desktop/output.c b/kiwmi/desktop/output.c index 379d93e..11fcefb 100644 --- a/kiwmi/desktop/output.c +++ b/kiwmi/desktop/output.c @@ -125,6 +125,8 @@ output_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) wlr_output_layout_remove( output->desktop->output_layout, output->wlr_output); + wl_signal_emit(&output->events.destroy, output); + wl_list_remove(&output->link); wl_list_remove(&output->frame.link); wl_list_remove(&output->destroy.link); @@ -183,4 +185,8 @@ new_output_notify(struct wl_listener *listener, void *data) wlr_output_layout_add_auto(desktop->output_layout, wlr_output); wlr_output_create_global(wlr_output); + + wl_signal_init(&output->events.destroy); + + wl_signal_emit(&desktop->events.new_output, output); } diff --git a/kiwmi/luak/kiwmi_output.c b/kiwmi/luak/kiwmi_output.c new file mode 100644 index 0000000..37926e7 --- /dev/null +++ b/kiwmi/luak/kiwmi_output.c @@ -0,0 +1,183 @@ +/* Copyright (c), Niclas Meyer + * + * 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_output.h" + +#include +#include +#include +#include +#include + +#include "desktop/output.h" +#include "luak/kiwmi_lua_callback.h" +#include "server.h" + +static int +l_kiwmi_output_auto(lua_State *L) +{ + struct kiwmi_output *output = + *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + + struct wlr_output_layout *output_layout = output->desktop->output_layout; + + wlr_output_layout_add_auto(output_layout, output->wlr_output); + + return 0; +} + +static int +l_kiwmi_output_move(lua_State *L) +{ + struct kiwmi_output *output = + *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + luaL_checktype(L, 2, LUA_TNUMBER); // x + luaL_checktype(L, 3, LUA_TNUMBER); // y + + struct wlr_output_layout *output_layout = output->desktop->output_layout; + + int lx = lua_tointeger(L, 2); + int ly = lua_tointeger(L, 3); + + wlr_output_layout_move(output_layout, output->wlr_output, lx, ly); + + return 0; +} + +static int +l_kiwmi_output_name(lua_State *L) +{ + struct kiwmi_output *output = + *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + + lua_pushstring(L, output->wlr_output->name); + + return 1; +} + +static int +l_kiwmi_output_pos(lua_State *L) +{ + struct kiwmi_output *output = + *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + + struct wlr_output_layout *output_layout = output->desktop->output_layout; + + struct wlr_box *box = + wlr_output_layout_get_box(output_layout, output->wlr_output); + + lua_pushinteger(L, box->x); + lua_pushinteger(L, box->y); + + return 2; +} + +static int +l_kiwmi_output_size(lua_State *L) +{ + struct kiwmi_output *output = + *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + + lua_pushinteger(L, output->wlr_output->width); + lua_pushinteger(L, output->wlr_output->height); + + return 2; +} + +static const luaL_Reg kiwmi_output_methods[] = { + {"auto", l_kiwmi_output_auto}, + {"move", l_kiwmi_output_move}, + {"name", l_kiwmi_output_name}, + {"pos", l_kiwmi_output_pos}, + {"size", l_kiwmi_output_size}, + {NULL, NULL}, +}; + +static void +kiwmi_output_on_destroy_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_output *output = data; + + lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); + + lua_pushcfunction(L, luaK_kiwmi_output_new); + lua_pushlightuserdata(L, output); + + 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_output_on_destroy(lua_State *L) +{ + struct kiwmi_output *output = + *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + luaL_checktype(L, 2, LUA_TFUNCTION); + + struct kiwmi_desktop *desktop = output->desktop; + struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + + lua_pushcfunction(L, luaK_kiwmi_lua_callback_new); + lua_pushlightuserdata(L, server); + lua_pushvalue(L, 2); + lua_pushlightuserdata(L, kiwmi_output_on_destroy_notify); + lua_pushlightuserdata(L, &output->events.destroy); + + 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_output_events[] = { + {"destroy", l_kiwmi_output_on_destroy}, + {NULL, NULL}, +}; + +int +luaK_kiwmi_output_new(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_output + + struct kiwmi_output *output = lua_touserdata(L, 1); + + struct kiwmi_output **output_ud = lua_newuserdata(L, sizeof(*output_ud)); + luaL_getmetatable(L, "kiwmi_output"); + lua_setmetatable(L, -2); + + *output_ud = output; + + return 1; +} + +int +luaK_kiwmi_output_register(lua_State *L) +{ + luaL_newmetatable(L, "kiwmi_output"); + + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + luaL_setfuncs(L, kiwmi_output_methods, 0); + + luaL_newlib(L, kiwmi_output_events); + lua_setfield(L, -2, "__events"); + + return 0; +} diff --git a/kiwmi/luak/kiwmi_server.c b/kiwmi/luak/kiwmi_server.c index 537c0e2..0cb01aa 100644 --- a/kiwmi/luak/kiwmi_server.c +++ b/kiwmi/luak/kiwmi_server.c @@ -20,6 +20,7 @@ #include "input/cursor.h" #include "luak/kiwmi_keyboard.h" #include "luak/kiwmi_lua_callback.h" +#include "luak/kiwmi_output.h" #include "luak/kiwmi_view.h" #include "server.h" @@ -143,6 +144,30 @@ kiwmi_server_on_keyboard_notify(struct wl_listener *listener, void *data) } } +static void +kiwmi_server_on_output_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_output *output = data; + + lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); + + lua_pushcfunction(L, luaK_kiwmi_output_new); + lua_pushlightuserdata(L, output); + 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) { @@ -188,6 +213,27 @@ l_kiwmi_server_on_keyboard(lua_State *L) return 1; } +static int +l_kiwmi_server_on_output(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_output_notify); + lua_pushlightuserdata(L, &server->desktop.events.new_output); + + 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) { @@ -211,6 +257,7 @@ l_kiwmi_server_on_view(lua_State *L) static const luaL_Reg kiwmi_server_events[] = { {"keyboard", l_kiwmi_server_on_keyboard}, + {"output", l_kiwmi_server_on_output}, {"view", l_kiwmi_server_on_view}, {NULL, NULL}, }; diff --git a/kiwmi/luak/luak.c b/kiwmi/luak/luak.c index a647be7..25dc06e 100644 --- a/kiwmi/luak/luak.c +++ b/kiwmi/luak/luak.c @@ -16,6 +16,7 @@ #include "luak/ipc.h" #include "luak/kiwmi_keyboard.h" #include "luak/kiwmi_lua_callback.h" +#include "luak/kiwmi_output.h" #include "luak/kiwmi_server.h" #include "luak/kiwmi_view.h" @@ -69,6 +70,8 @@ luaK_create(struct kiwmi_server *server) 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_output_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); diff --git a/kiwmi/meson.build b/kiwmi/meson.build index 2e27441..642ad37 100644 --- a/kiwmi/meson.build +++ b/kiwmi/meson.build @@ -11,6 +11,7 @@ kiwmi_sources = files( 'luak/ipc.c', 'luak/kiwmi_keyboard.c', 'luak/kiwmi_lua_callback.c', + 'luak/kiwmi_output.c', 'luak/kiwmi_server.c', 'luak/kiwmi_view.c', 'luak/luak.c',