From 1d755a8a74532d9dfba70239cc3e22281cde2b9e Mon Sep 17 00:00:00 2001 From: Charlotte Meyer Date: Thu, 6 Feb 2020 17:55:05 +0000 Subject: [PATCH] Add object lifetimes (invalidate references, free listeners) --- include/luak/kiwmi_lua_callback.h | 2 - include/luak/luak.h | 22 ++- kiwmi/desktop/.output.c.kak.pRsrnt | 277 +++++++++++++++++++++++++++++ kiwmi/desktop/xdg_shell.c | 7 +- kiwmi/luak/kiwmi_cursor.c | 60 ++++--- kiwmi/luak/kiwmi_keyboard.c | 82 ++++++--- kiwmi/luak/kiwmi_lua_callback.c | 60 +------ kiwmi/luak/kiwmi_output.c | 99 ++++++++--- kiwmi/luak/kiwmi_renderer.c | 13 +- kiwmi/luak/kiwmi_server.c | 96 ++++++---- kiwmi/luak/kiwmi_view.c | 267 ++++++++++++++++++++------- kiwmi/luak/luak.c | 118 ++++++++++-- lua_docs.md | 6 - 13 files changed, 860 insertions(+), 249 deletions(-) create mode 100644 kiwmi/desktop/.output.c.kak.pRsrnt diff --git a/include/luak/kiwmi_lua_callback.h b/include/luak/kiwmi_lua_callback.h index 9250a37..2a10d19 100644 --- a/include/luak/kiwmi_lua_callback.h +++ b/include/luak/kiwmi_lua_callback.h @@ -20,7 +20,5 @@ struct kiwmi_lua_callback { }; int luaK_kiwmi_lua_callback_new(lua_State *L); -int luaK_kiwmi_lua_callback_register(lua_State *L); -void luaK_kiwmi_lua_callback_cleanup(struct kiwmi_lua *lua); #endif /* KIWMI_LUAK_KIWMI_LUA_CALLBACK_H */ diff --git a/include/luak/luak.h b/include/luak/luak.h index 0ca4fab..8efcc59 100644 --- a/include/luak/luak.h +++ b/include/luak/luak.h @@ -16,10 +16,30 @@ struct kiwmi_lua { lua_State *L; - struct wl_list callbacks; // lua_callback::link + int objects; struct wl_global *global; }; +struct kiwmi_object { + struct kiwmi_lua *lua; + + void *object; + size_t refcount; + bool valid; + + struct wl_listener destroy; + struct wl_list callbacks; // struct kiwmi_lua_callback::link + + struct { + struct wl_signal destroy; + } events; +}; + +int luaK_kiwmi_object_gc(lua_State *L); +struct kiwmi_object *luaK_get_kiwmi_object( + struct kiwmi_lua *lua, + void *ptr, + struct wl_signal *destroy); int luaK_callback_register_dispatch(lua_State *L); int luaK_usertype_ref_equal(lua_State *L); struct kiwmi_lua *luaK_create(struct kiwmi_server *server); diff --git a/kiwmi/desktop/.output.c.kak.pRsrnt b/kiwmi/desktop/.output.c.kak.pRsrnt new file mode 100644 index 0000000..2dcdf9d --- /dev/null +++ b/kiwmi/desktop/.output.c.kak.pRsrnt @@ -0,0 +1,277 @@ +wow such kakoune/* Copyright (c), Charlotte 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 "desktop/output.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "desktop/desktop.h" +#include "desktop/layer_shell.h" +#include "desktop/view.h" +#include "input/cursor.h" +#include "input/input.h" +#include "server.h" + +static void +render_layer_surface(struct wlr_surface *surface, int x, int y, void *data) +{ + struct kiwmi_render_data *rdata = data; + struct wlr_output *output = rdata->output; + struct wlr_box *geom = rdata->data; + + struct wlr_texture *texture = wlr_surface_get_texture(surface); + if (!texture) { + return; + } + + int ox = rdata->output_lx + x + geom->x; + int oy = rdata->output_ly + y + geom->y; + + struct wlr_box box = { + .x = ox * output->scale, + .y = oy * output->scale, + .width = surface->current.width * output->scale, + .height = surface->current.height * output->scale, + }; + + float matrix[9]; + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current.transform); + wlr_matrix_project_box( + matrix, &box, transform, 0, output->transform_matrix); + + wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1); + + wlr_surface_send_frame_done(surface, rdata->when); +} + +static void +render_layer(struct wl_list *layer, struct kiwmi_render_data *rdata) +{ + struct kiwmi_layer *surface; + wl_list_for_each (surface, layer, link) { + rdata->data = &surface->geom; + + wlr_layer_surface_v1_for_each_surface( + surface->layer_surface, render_layer_surface, rdata); + } +} + +static void +render_surface(struct wlr_surface *surface, int sx, int sy, void *data) +{ + struct kiwmi_render_data *rdata = data; + struct kiwmi_view *view = rdata->data; + struct wlr_output *output = rdata->output; + + struct wlr_texture *texture = wlr_surface_get_texture(surface); + if (!texture) { + return; + } + + int ox = rdata->output_lx + sx + view->x - view->geom.x; + int oy = rdata->output_ly + sy + view->y - view->geom.y; + + struct wlr_box box = { + .x = ox * output->scale, + .y = oy * output->scale, + .width = surface->current.width * output->scale, + .height = surface->current.height * output->scale, + }; + + float matrix[9]; + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current.transform); + wlr_matrix_project_box( + matrix, &box, transform, 0, output->transform_matrix); + + wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1); + + wlr_surface_send_frame_done(surface, rdata->when); +} + +static void +output_frame_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_output *output = wl_container_of(listener, output, frame); + struct wlr_output *wlr_output = data; + struct kiwmi_desktop *desktop = output->desktop; + struct wlr_output_layout *output_layout = desktop->output_layout; + struct wlr_renderer *renderer = + wlr_backend_get_renderer(wlr_output->backend); + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + if (!wlr_output_attach_render(wlr_output, NULL)) { + wlr_log(WLR_ERROR, "Failed to attach renderer to output"); + return; + } + + int width; + int height; + wlr_output_effective_resolution(wlr_output, &width, &height); + + wlr_renderer_begin(renderer, width, height); + wlr_renderer_clear(renderer, (float[]){0.0f, 1.0f, 0.0f, 1.0f}); + + double output_lx; + double output_ly; + wlr_output_layout_output_coords( + output_layout, wlr_output, &output_lx, &output_ly); + + struct kiwmi_render_data rdata = { + .output = output->wlr_output, + .output_lx = output_lx, + .output_ly = output_ly, + .renderer = renderer, + .when = &now, + }; + + render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &rdata); + render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &rdata); + + struct kiwmi_view *view; + wl_list_for_each_reverse (view, &desktop->views, link) { + if (view->hidden || !view->mapped) { + continue; + } + + rdata.data = view; + + wl_signal_emit(&view->events.pre_render, &rdata); + view_for_each_surface(view, render_surface, &rdata); + wl_signal_emit(&view->events.post_render, &rdata); + } + + render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &rdata); + render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &rdata); + + wlr_output_render_software_cursors(wlr_output, NULL); + wlr_renderer_end(renderer); + + wlr_output_commit(wlr_output); +} + +static void +output_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) +{ + struct kiwmi_output *output = wl_container_of(listener, output, destroy); + + 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); + + free(output); +} + +static void +output_mode_notify(struct wl_listener *listener, void *UNUSED(data)) +{ + struct kiwmi_output *output = wl_container_of(listener, output, mode); + + arrange_layers(output); + + wl_signal_emit(&output->events.resize, output); +} + +static void +output_transform_notify(struct wl_listener *listener, void *UNUSED(data)) +{ + struct kiwmi_output *output = wl_container_of(listener, output, transform); + + arrange_layers(output); + + wl_signal_emit(&output->events.resize, output); +} + +static struct kiwmi_output * +output_create(struct wlr_output *wlr_output, struct kiwmi_desktop *desktop) +{ + struct kiwmi_output *output = calloc(1, sizeof(*output)); + if (!output) { + return NULL; + } + + output->wlr_output = wlr_output; + output->desktop = desktop; + + output->frame.notify = output_frame_notify; + wl_signal_add(&wlr_output->events.frame, &output->frame); + + output->destroy.notify = output_destroy_notify; + wl_signal_add(&wlr_output->events.destroy, &output->destroy); + + output->mode.notify = output_mode_notify; + wl_signal_add(&wlr_output->events.mode, &output->mode); + + output->transform.notify = output_transform_notify; + wl_signal_add(&wlr_output->events.transform, &output->transform); + + return output; +} + +void +new_output_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_desktop *desktop = + wl_container_of(listener, desktop, new_output); + struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + struct wlr_output *wlr_output = data; + + wlr_log(WLR_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); + + if (!wl_list_empty(&wlr_output->modes)) { + struct wlr_output_mode *mode = + wl_container_of(wlr_output->modes.prev, mode, link); + wlr_output_set_mode(wlr_output, mode); + } + + struct kiwmi_output *output = output_create(wlr_output, desktop); + if (!output) { + wlr_log(WLR_ERROR, "Failed to create output"); + return; + } + + wlr_output->data = output; + + struct kiwmi_cursor *cursor = server->input.cursor; + + wlr_xcursor_manager_load(cursor->xcursor_manager, wlr_output->scale); + + wl_list_insert(&desktop->outputs, &output->link); + + wlr_output_layout_add_auto(desktop->output_layout, wlr_output); + + wlr_output_create_global(wlr_output); + + size_t len_outputs = sizeof(output->layers) / sizeof(output->layers[0]); + for (size_t i = 0; i < len_outputs; ++i) { + wl_list_init(&output->layers[i]); + } + + wl_signal_init(&output->events.destroy); + wl_signal_init(&output->events.resize); + + wl_signal_emit(&desktop->events.new_output, output); +} diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index 4a2612c..48148dd 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -33,9 +33,12 @@ static void xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_view *view = wl_container_of(listener, view, unmap); - view->mapped = false; - wl_signal_emit(&view->events.unmap, view); + if (view->mapped) { + view->mapped = false; + + wl_signal_emit(&view->events.unmap, view); + } } static void diff --git a/kiwmi/luak/kiwmi_cursor.c b/kiwmi/luak/kiwmi_cursor.c index 8d30455..f6bf2a1 100644 --- a/kiwmi/luak/kiwmi_cursor.c +++ b/kiwmi/luak/kiwmi_cursor.c @@ -23,8 +23,10 @@ static int l_kiwmi_cursor_pos(lua_State *L) { - struct kiwmi_cursor *cursor = - *(struct kiwmi_cursor **)luaL_checkudata(L, 1, "kiwmi_cursor"); + 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); @@ -35,9 +37,11 @@ l_kiwmi_cursor_pos(lua_State *L) static int l_kiwmi_cursor_view_at_pos(lua_State *L) { - struct kiwmi_cursor *cursor = - *(struct kiwmi_cursor **)luaL_checkudata(L, 1, "kiwmi_cursor"); + 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; @@ -54,8 +58,9 @@ l_kiwmi_cursor_view_at_pos(lua_State *L) if (view) { lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, lua); lua_pushlightuserdata(L, view); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } @@ -130,10 +135,11 @@ kiwmi_cursor_on_motion_notify(struct wl_listener *listener, void *data) static int l_kiwmi_cursor_on_button_down(lua_State *L) { - struct kiwmi_cursor *cursor = - *(struct kiwmi_cursor **)luaL_checkudata(L, 1, "kiwmi_cursor"); + 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); @@ -141,22 +147,24 @@ l_kiwmi_cursor_on_button_down(lua_State *L) 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, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_cursor_on_button_up(lua_State *L) { - struct kiwmi_cursor *cursor = - *(struct kiwmi_cursor **)luaL_checkudata(L, 1, "kiwmi_cursor"); + 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); @@ -164,22 +172,24 @@ l_kiwmi_cursor_on_button_up(lua_State *L) 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, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_cursor_on_motion(lua_State *L) { - struct kiwmi_cursor *cursor = - *(struct kiwmi_cursor **)luaL_checkudata(L, 1, "kiwmi_cursor"); + 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); @@ -187,13 +197,14 @@ l_kiwmi_cursor_on_motion(lua_State *L) 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, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static const luaL_Reg kiwmi_cursor_events[] = { @@ -206,15 +217,19 @@ static const luaL_Reg kiwmi_cursor_events[] = { int luaK_kiwmi_cursor_new(lua_State *L) { - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_cursor + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_lua + luaL_checktype(L, 2, LUA_TLIGHTUSERDATA); // kiwmi_cursor - struct kiwmi_cursor *cursor = lua_touserdata(L, 1); + struct kiwmi_lua *lua = lua_touserdata(L, 1); + struct kiwmi_cursor *cursor = lua_touserdata(L, 2); - struct kiwmi_cursor **cursor_ud = lua_newuserdata(L, sizeof(*cursor_ud)); + struct kiwmi_object *obj = luaK_get_kiwmi_object(lua, cursor, NULL); + + struct kiwmi_object **cursor_ud = lua_newuserdata(L, sizeof(*cursor_ud)); luaL_getmetatable(L, "kiwmi_cursor"); lua_setmetatable(L, -2); - *cursor_ud = cursor; + *cursor_ud = obj; return 1; } @@ -234,5 +249,8 @@ luaK_kiwmi_cursor_register(lua_State *L) 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; } diff --git a/kiwmi/luak/kiwmi_keyboard.c b/kiwmi/luak/kiwmi_keyboard.c index d7c9298..4e5779b 100644 --- a/kiwmi/luak/kiwmi_keyboard.c +++ b/kiwmi/luak/kiwmi_keyboard.c @@ -19,8 +19,14 @@ static int l_kiwmi_keyboard_modifiers(lua_State *L) { - struct kiwmi_keyboard *keyboard = - *(struct kiwmi_keyboard **)luaL_checkudata(L, 1, "kiwmi_keyboard"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_keyboard"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_keyboard no longer valid"); + } + + struct kiwmi_keyboard *keyboard = obj->object; uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); @@ -70,8 +76,9 @@ kiwmi_keyboard_on_destroy_notify(struct wl_listener *listener, void *data) lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); lua_pushcfunction(L, luaK_kiwmi_keyboard_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, keyboard); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -116,8 +123,9 @@ kiwmi_keyboard_on_key_down_or_up_notify( 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, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -138,70 +146,88 @@ kiwmi_keyboard_on_key_down_or_up_notify( static int l_kiwmi_keyboard_on_destroy(lua_State *L) { - struct kiwmi_keyboard *keyboard = - *(struct kiwmi_keyboard **)luaL_checkudata(L, 1, "kiwmi_keyboard"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_keyboard"); luaL_checktype(L, 2, LUA_TFUNCTION); - struct kiwmi_server *server = keyboard->server; + if (!obj->valid) { + return luaL_error(L, "kiwmi_keyboard no longer valid"); + } + + struct kiwmi_keyboard *keyboard = obj->object; + 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_destroy_notify); - lua_pushlightuserdata(L, &keyboard->events.destroy); + lua_pushlightuserdata(L, &obj->events.destroy); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_keyboard_on_key_down(lua_State *L) { - struct kiwmi_keyboard *keyboard = - *(struct kiwmi_keyboard **)luaL_checkudata(L, 1, "kiwmi_keyboard"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_keyboard"); luaL_checktype(L, 2, LUA_TFUNCTION); - struct kiwmi_server *server = keyboard->server; + if (!obj->valid) { + return luaL_error(L, "kiwmi_keyboard no longer valid"); + } + + struct kiwmi_keyboard *keyboard = obj->object; + 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); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_keyboard_on_key_up(lua_State *L) { - struct kiwmi_keyboard *keyboard = - *(struct kiwmi_keyboard **)luaL_checkudata(L, 1, "kiwmi_keyboard"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_keyboard"); luaL_checktype(L, 2, LUA_TFUNCTION); - struct kiwmi_server *server = keyboard->server; + if (!obj->valid) { + return luaL_error(L, "kiwmi_keyboard no longer valid"); + } + + struct kiwmi_keyboard *keyboard = obj->object; + 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); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static const luaL_Reg kiwmi_keyboard_events[] = { @@ -214,16 +240,21 @@ static const luaL_Reg kiwmi_keyboard_events[] = { int luaK_kiwmi_keyboard_new(lua_State *L) { - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_keyboard + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_lua + luaL_checktype(L, 2, LUA_TLIGHTUSERDATA); // kiwmi_keyboard - struct kiwmi_keyboard *keyboard = lua_touserdata(L, 1); + struct kiwmi_lua *lua = lua_touserdata(L, 1); + struct kiwmi_keyboard *keyboard = lua_touserdata(L, 2); - struct kiwmi_keyboard **keyboard_ud = + struct kiwmi_object *obj = + luaK_get_kiwmi_object(lua, keyboard, &keyboard->events.destroy); + + struct kiwmi_object **keyboard_ud = lua_newuserdata(L, sizeof(*keyboard_ud)); luaL_getmetatable(L, "kiwmi_keyboard"); lua_setmetatable(L, -2); - *keyboard_ud = keyboard; + *keyboard_ud = obj; return 1; } @@ -243,5 +274,8 @@ luaK_kiwmi_keyboard_register(lua_State *L) 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; } diff --git a/kiwmi/luak/kiwmi_lua_callback.c b/kiwmi/luak/kiwmi_lua_callback.c index 0202d12..cb3a99a 100644 --- a/kiwmi/luak/kiwmi_lua_callback.c +++ b/kiwmi/luak/kiwmi_lua_callback.c @@ -12,27 +12,6 @@ #include #include -static int -l_kiwmi_lua_callback_cancel(lua_State *L) -{ - struct kiwmi_lua_callback *lc = - *(struct kiwmi_lua_callback **)luaL_checkudata( - L, 1, "kiwmi_lua_callback"); - - wl_list_remove(&lc->listener.link); - wl_list_remove(&lc->link); - - luaL_unref(L, LUA_REGISTRYINDEX, lc->callback_ref); - - free(lc); - return 0; -} - -static const luaL_Reg kiwmi_lua_callback_methods[] = { - {"cancel", l_kiwmi_lua_callback_cancel}, - {NULL, NULL}, -}; - int luaK_kiwmi_lua_callback_new(lua_State *L) { @@ -40,18 +19,13 @@ luaK_kiwmi_lua_callback_new(lua_State *L) luaL_checktype(L, 2, LUA_TFUNCTION); // callback luaL_checktype(L, 3, LUA_TLIGHTUSERDATA); // event_handler luaL_checktype(L, 4, LUA_TLIGHTUSERDATA); // signal - - struct kiwmi_lua_callback **lc_ud = lua_newuserdata(L, sizeof(*lc_ud)); - luaL_getmetatable(L, "kiwmi_lua_callback"); - lua_setmetatable(L, -2); + luaL_checktype(L, 5, LUA_TLIGHTUSERDATA); // object struct kiwmi_lua_callback *lc = malloc(sizeof(*lc)); if (!lc) { return luaL_error(L, "failed to allocate kiwmi_lua_callback"); } - *lc_ud = lc; - struct kiwmi_server *server = lua_touserdata(L, 1); lc->server = server; @@ -62,37 +36,9 @@ luaK_kiwmi_lua_callback_new(lua_State *L) lc->listener.notify = lua_touserdata(L, 3); wl_signal_add(lua_touserdata(L, 4), &lc->listener); - wl_list_insert(&server->lua->callbacks, &lc->link); + struct kiwmi_object *object = lua_touserdata(L, 5); - return 1; -} - -int -luaK_kiwmi_lua_callback_register(lua_State *L) -{ - luaL_newmetatable(L, "kiwmi_lua_callback"); - - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - luaL_setfuncs(L, kiwmi_lua_callback_methods, 0); - - lua_pushcfunction(L, luaK_usertype_ref_equal); - lua_setfield(L, -2, "__eq"); + wl_list_insert(&object->callbacks, &lc->link); return 0; } - -void -luaK_kiwmi_lua_callback_cleanup(struct kiwmi_lua *lua) -{ - struct kiwmi_lua_callback *lc; - struct kiwmi_lua_callback *tmp; - wl_list_for_each_safe (lc, tmp, &lua->callbacks, link) { - wl_list_remove(&lc->listener.link); - wl_list_remove(&lc->link); - - luaL_unref(lua->L, LUA_REGISTRYINDEX, lc->callback_ref); - - free(lc); - } -} diff --git a/kiwmi/luak/kiwmi_output.c b/kiwmi/luak/kiwmi_output.c index 09e829e..8fa53aa 100644 --- a/kiwmi/luak/kiwmi_output.c +++ b/kiwmi/luak/kiwmi_output.c @@ -20,9 +20,14 @@ static int l_kiwmi_output_auto(lua_State *L) { - struct kiwmi_output *output = - *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_output"); + if (!obj->valid) { + return luaL_error(L, "kiwmi_output no longer valid"); + } + + struct kiwmi_output *output = obj->object; struct wlr_output_layout *output_layout = output->desktop->output_layout; wlr_output_layout_add_auto(output_layout, output->wlr_output); @@ -33,11 +38,16 @@ l_kiwmi_output_auto(lua_State *L) static int l_kiwmi_output_move(lua_State *L) { - struct kiwmi_output *output = - *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_output"); luaL_checktype(L, 2, LUA_TNUMBER); // x luaL_checktype(L, 3, LUA_TNUMBER); // y + if (!obj->valid) { + return luaL_error(L, "kiwmi_output no longer valid"); + } + + struct kiwmi_output *output = obj->object; struct wlr_output_layout *output_layout = output->desktop->output_layout; int lx = lua_tonumber(L, 2); @@ -51,8 +61,14 @@ l_kiwmi_output_move(lua_State *L) static int l_kiwmi_output_name(lua_State *L) { - struct kiwmi_output *output = - *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_output"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_output no longer valid"); + } + + struct kiwmi_output *output = obj->object; lua_pushstring(L, output->wlr_output->name); @@ -62,9 +78,14 @@ l_kiwmi_output_name(lua_State *L) static int l_kiwmi_output_pos(lua_State *L) { - struct kiwmi_output *output = - *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_output"); + if (!obj->valid) { + return luaL_error(L, "kiwmi_output no longer valid"); + } + + struct kiwmi_output *output = obj->object; struct wlr_output_layout *output_layout = output->desktop->output_layout; struct wlr_box *box = @@ -79,8 +100,14 @@ l_kiwmi_output_pos(lua_State *L) static int l_kiwmi_output_size(lua_State *L) { - struct kiwmi_output *output = - *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_output"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_output no longer valid"); + } + + struct kiwmi_output *output = obj->object; lua_pushinteger(L, output->wlr_output->width); lua_pushinteger(L, output->wlr_output->height); @@ -109,9 +136,10 @@ kiwmi_output_on_destroy_notify(struct wl_listener *listener, void *data) lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); lua_pushcfunction(L, luaK_kiwmi_output_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, output); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -140,9 +168,10 @@ kiwmi_output_on_resize_notify(struct wl_listener *listener, void *data) lua_newtable(L); lua_pushcfunction(L, luaK_kiwmi_output_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, output); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -165,10 +194,15 @@ kiwmi_output_on_resize_notify(struct wl_listener *listener, void *data) static int l_kiwmi_output_on_destroy(lua_State *L) { - struct kiwmi_output *output = - *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_output"); luaL_checktype(L, 2, LUA_TFUNCTION); + if (!obj->valid) { + return luaL_error(L, "kiwmi_output no longer valid"); + } + + struct kiwmi_output *output = obj->object; struct kiwmi_desktop *desktop = output->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); @@ -176,23 +210,29 @@ l_kiwmi_output_on_destroy(lua_State *L) lua_pushlightuserdata(L, server); lua_pushvalue(L, 2); lua_pushlightuserdata(L, kiwmi_output_on_destroy_notify); - lua_pushlightuserdata(L, &output->events.destroy); + lua_pushlightuserdata(L, &obj->events.destroy); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_output_on_resize(lua_State *L) { - struct kiwmi_output *output = - *(struct kiwmi_output **)luaL_checkudata(L, 1, "kiwmi_output"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_output"); luaL_checktype(L, 2, LUA_TFUNCTION); + if (!obj->valid) { + return luaL_error(L, "kiwmi_output no longer valid"); + } + + struct kiwmi_output *output = obj->object; struct kiwmi_desktop *desktop = output->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); @@ -201,13 +241,14 @@ l_kiwmi_output_on_resize(lua_State *L) lua_pushvalue(L, 2); lua_pushlightuserdata(L, kiwmi_output_on_resize_notify); lua_pushlightuserdata(L, &output->events.resize); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static const luaL_Reg kiwmi_output_events[] = { @@ -219,15 +260,20 @@ static const luaL_Reg kiwmi_output_events[] = { int luaK_kiwmi_output_new(lua_State *L) { - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_output + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_lua + luaL_checktype(L, 2, LUA_TLIGHTUSERDATA); // kiwmi_output - struct kiwmi_output *output = lua_touserdata(L, 1); + struct kiwmi_lua *lua = lua_touserdata(L, 1); + struct kiwmi_output *output = lua_touserdata(L, 2); - struct kiwmi_output **output_ud = lua_newuserdata(L, sizeof(*output_ud)); + struct kiwmi_object *obj = + luaK_get_kiwmi_object(lua, output, &output->events.destroy); + + struct kiwmi_object **output_ud = lua_newuserdata(L, sizeof(*output_ud)); luaL_getmetatable(L, "kiwmi_output"); lua_setmetatable(L, -2); - *output_ud = output; + *output_ud = obj; return 1; } @@ -247,5 +293,8 @@ luaK_kiwmi_output_register(lua_State *L) 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; } diff --git a/kiwmi/luak/kiwmi_renderer.c b/kiwmi/luak/kiwmi_renderer.c index 01c453b..2ab14dd 100644 --- a/kiwmi/luak/kiwmi_renderer.c +++ b/kiwmi/luak/kiwmi_renderer.c @@ -93,11 +93,13 @@ static const luaL_Reg kiwmi_renderer_methods[] = { int luaK_kiwmi_renderer_new(lua_State *L) { - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // wlr_renderer - luaL_checktype(L, 2, LUA_TLIGHTUSERDATA); // wlr_output + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_lua + luaL_checktype(L, 2, LUA_TLIGHTUSERDATA); // wlr_renderer + luaL_checktype(L, 3, LUA_TLIGHTUSERDATA); // wlr_output - struct wlr_renderer *wlr_renderer = lua_touserdata(L, 1); - struct kiwmi_output *output = lua_touserdata(L, 2); + struct kiwmi_lua *UNUSED(lua) = lua_touserdata(L, 1); + struct wlr_renderer *wlr_renderer = lua_touserdata(L, 2); + struct kiwmi_output *output = lua_touserdata(L, 3); struct kiwmi_renderer *renderer_ud = lua_newuserdata(L, sizeof(*renderer_ud)); @@ -122,5 +124,8 @@ luaK_kiwmi_renderer_register(lua_State *L) 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; } diff --git a/kiwmi/luak/kiwmi_server.c b/kiwmi/luak/kiwmi_server.c index abac2cc..0211a51 100644 --- a/kiwmi/luak/kiwmi_server.c +++ b/kiwmi/luak/kiwmi_server.c @@ -30,12 +30,15 @@ static int l_kiwmi_server_cursor(lua_State *L) { - struct kiwmi_server *server = - *(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server"); + + struct kiwmi_server *server = obj->object; lua_pushcfunction(L, luaK_kiwmi_cursor_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, server->input.cursor); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } @@ -46,16 +49,19 @@ l_kiwmi_server_cursor(lua_State *L) static int l_kiwmi_server_focused_view(lua_State *L) { - struct kiwmi_server *server = - *(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server"); + + struct kiwmi_server *server = obj->object; if (!server->input.seat->focused_view) { return 0; } lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, server->input.seat->focused_view); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } @@ -66,8 +72,10 @@ l_kiwmi_server_focused_view(lua_State *L) static int l_kiwmi_server_quit(lua_State *L) { - struct kiwmi_server *server = - *(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server"); + + struct kiwmi_server *server = obj->object; wl_display_terminate(server->wl_display); @@ -101,8 +109,10 @@ l_kiwmi_server_spawn(lua_State *L) static int l_kiwmi_server_stop_interactive(lua_State *L) { - struct kiwmi_server *server = - *(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server"); + + struct kiwmi_server *server = obj->object; server->input.cursor->cursor_mode = KIWMI_CURSOR_PASSTHROUGH; @@ -112,11 +122,13 @@ l_kiwmi_server_stop_interactive(lua_State *L) static int l_kiwmi_server_view_at(lua_State *L) { - struct kiwmi_server *server = - *(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server"); luaL_checktype(L, 2, LUA_TNUMBER); // x luaL_checktype(L, 3, LUA_TNUMBER); // y + struct kiwmi_server *server = obj->object; + double x = lua_tonumber(L, 2); double y = lua_tonumber(L, 3); @@ -129,8 +141,9 @@ l_kiwmi_server_view_at(lua_State *L) if (view) { lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, obj->lua); lua_pushlightuserdata(L, view); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } @@ -163,8 +176,9 @@ kiwmi_server_on_keyboard_notify(struct wl_listener *listener, void *data) lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); lua_pushcfunction(L, luaK_kiwmi_keyboard_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, keyboard); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -187,8 +201,9 @@ kiwmi_server_on_output_notify(struct wl_listener *listener, void *data) lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); lua_pushcfunction(L, luaK_kiwmi_output_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, output); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -211,8 +226,9 @@ kiwmi_server_on_view_notify(struct wl_listener *listener, void *data) lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, view); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -227,64 +243,73 @@ kiwmi_server_on_view_notify(struct wl_listener *listener, void *data) static int l_kiwmi_server_on_keyboard(lua_State *L) { - struct kiwmi_server *server = - *(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server"); luaL_checktype(L, 2, LUA_TFUNCTION); + struct kiwmi_server *server = obj->object; + 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); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_server_on_output(lua_State *L) { - struct kiwmi_server *server = - *(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server"); luaL_checktype(L, 2, LUA_TFUNCTION); + struct kiwmi_server *server = obj->object; + 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); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_server_on_view(lua_State *L) { - struct kiwmi_server *server = - *(struct kiwmi_server **)luaL_checkudata(L, 1, "kiwmi_server"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server"); luaL_checktype(L, 2, LUA_TFUNCTION); + struct kiwmi_server *server = obj->object; + lua_pushcfunction(L, luaK_kiwmi_lua_callback_new); lua_pushlightuserdata(L, server); lua_pushvalue(L, 2); lua_pushlightuserdata(L, kiwmi_server_on_view_notify); lua_pushlightuserdata(L, &server->desktop.events.view_map); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static const luaL_Reg kiwmi_server_events[] = { @@ -297,15 +322,19 @@ static const luaL_Reg kiwmi_server_events[] = { int luaK_kiwmi_server_new(lua_State *L) { - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_server + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_lua + luaL_checktype(L, 2, LUA_TLIGHTUSERDATA); // kiwmi_server - struct kiwmi_server *server = lua_touserdata(L, 1); + struct kiwmi_lua *lua = lua_touserdata(L, 1); + struct kiwmi_server *server = lua_touserdata(L, 2); - struct kiwmi_server **server_ud = lua_newuserdata(L, sizeof(*server_ud)); + struct kiwmi_object *obj = luaK_get_kiwmi_object(lua, server, NULL); + + struct kiwmi_object **server_ud = lua_newuserdata(L, sizeof(*server_ud)); luaL_getmetatable(L, "kiwmi_server"); lua_setmetatable(L, -2); - *server_ud = server; + *server_ud = obj; return 1; } @@ -325,5 +354,8 @@ luaK_kiwmi_server_register(lua_State *L) 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; } diff --git a/kiwmi/luak/kiwmi_view.c b/kiwmi/luak/kiwmi_view.c index c154dc6..125b6c5 100644 --- a/kiwmi/luak/kiwmi_view.c +++ b/kiwmi/luak/kiwmi_view.c @@ -27,8 +27,14 @@ static int l_kiwmi_view_app_id(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; lua_pushstring(L, view_get_app_id(view)); @@ -38,8 +44,14 @@ l_kiwmi_view_app_id(lua_State *L) static int l_kiwmi_view_close(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; view_close(view); @@ -49,10 +61,16 @@ l_kiwmi_view_close(lua_State *L) static int l_kiwmi_view_csd(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); luaL_checktype(L, 2, LUA_TBOOLEAN); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; + struct kiwmi_xdg_decoration *decoration = view->decoration; if (!decoration) { return 0; @@ -73,9 +91,14 @@ l_kiwmi_view_csd(lua_State *L) static int l_kiwmi_view_focus(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; struct kiwmi_desktop *desktop = view->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); struct kiwmi_seat *seat = server->input.seat; @@ -88,8 +111,14 @@ l_kiwmi_view_focus(lua_State *L) static int l_kiwmi_view_hidden(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; lua_pushboolean(L, view->hidden); @@ -99,8 +128,14 @@ l_kiwmi_view_hidden(lua_State *L) static int l_kiwmi_view_hide(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; view->hidden = true; @@ -110,8 +145,14 @@ l_kiwmi_view_hide(lua_State *L) static int l_kiwmi_view_imove(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; view_move(view); @@ -121,10 +162,16 @@ l_kiwmi_view_imove(lua_State *L) static int l_kiwmi_view_iresize(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); luaL_checktype(L, 2, LUA_TTABLE); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; + enum wlr_edges edges = WLR_EDGE_NONE; lua_pushnil(L); @@ -162,8 +209,14 @@ l_kiwmi_view_iresize(lua_State *L) static int l_kiwmi_view_move(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; luaL_checktype(L, 2, LUA_TNUMBER); luaL_checktype(L, 3, LUA_TNUMBER); @@ -177,8 +230,14 @@ l_kiwmi_view_move(lua_State *L) static int l_kiwmi_view_pid(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; lua_pushinteger(L, view_get_pid(view)); @@ -188,8 +247,14 @@ l_kiwmi_view_pid(lua_State *L) static int l_kiwmi_view_pos(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; lua_pushinteger(L, view->x); lua_pushinteger(L, view->y); @@ -200,11 +265,17 @@ l_kiwmi_view_pos(lua_State *L) static int l_kiwmi_view_resize(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); luaL_checktype(L, 2, LUA_TNUMBER); // w luaL_checktype(L, 3, LUA_TNUMBER); // h + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; + double w = lua_tonumber(L, 2); double h = lua_tonumber(L, 3); @@ -216,8 +287,14 @@ l_kiwmi_view_resize(lua_State *L) static int l_kiwmi_view_show(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; view->hidden = false; @@ -227,8 +304,14 @@ l_kiwmi_view_show(lua_State *L) static int l_kiwmi_view_size(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; uint32_t width; uint32_t height; @@ -243,8 +326,14 @@ l_kiwmi_view_size(lua_State *L) static int l_kiwmi_view_tiled(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); + + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; if (lua_isboolean(L, 2)) { enum wlr_edges edges = WLR_EDGE_NONE; @@ -300,10 +389,16 @@ l_kiwmi_view_tiled(lua_State *L) static int l_kiwmi_view_title(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); - lua_pushstring(L, view_get_app_id(view)); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; + + lua_pushstring(L, view_get_title(view)); return 1; } @@ -340,9 +435,10 @@ kiwmi_view_on_destroy_notify(struct wl_listener *listener, void *data) lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, view); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -371,9 +467,10 @@ kiwmi_view_on_render_notify(struct wl_listener *listener, void *data) lua_newtable(L); lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, view); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -382,9 +479,10 @@ kiwmi_view_on_render_notify(struct wl_listener *listener, void *data) lua_setfield(L, -2, "view"); lua_pushcfunction(L, luaK_kiwmi_output_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, output); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -393,10 +491,11 @@ kiwmi_view_on_render_notify(struct wl_listener *listener, void *data) lua_setfield(L, -2, "output"); lua_pushcfunction(L, luaK_kiwmi_renderer_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, renderer); lua_pushlightuserdata(L, output); - if (lua_pcall(L, 2, 1, 0)) { + if (lua_pcall(L, 3, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -421,9 +520,10 @@ kiwmi_view_on_request_move_notify(struct wl_listener *listener, void *data) lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, view); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -450,9 +550,10 @@ kiwmi_view_on_request_resize_notify(struct wl_listener *listener, void *data) lua_newtable(L); lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, server->lua); lua_pushlightuserdata(L, view); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_pop(L, 1); return; @@ -494,10 +595,15 @@ kiwmi_view_on_request_resize_notify(struct wl_listener *listener, void *data) static int l_kiwmi_view_on_destroy(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); luaL_checktype(L, 2, LUA_TFUNCTION); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; struct kiwmi_desktop *desktop = view->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); @@ -505,23 +611,29 @@ l_kiwmi_view_on_destroy(lua_State *L) lua_pushlightuserdata(L, server); lua_pushvalue(L, 2); lua_pushlightuserdata(L, kiwmi_view_on_destroy_notify); - lua_pushlightuserdata(L, &view->events.unmap); + lua_pushlightuserdata(L, &obj->events.destroy); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_view_on_post_render(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); luaL_checktype(L, 2, LUA_TFUNCTION); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; struct kiwmi_desktop *desktop = view->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); @@ -530,22 +642,28 @@ l_kiwmi_view_on_post_render(lua_State *L) lua_pushvalue(L, 2); lua_pushlightuserdata(L, kiwmi_view_on_render_notify); lua_pushlightuserdata(L, &view->events.post_render); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_view_on_pre_render(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); luaL_checktype(L, 2, LUA_TFUNCTION); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; struct kiwmi_desktop *desktop = view->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); @@ -554,22 +672,28 @@ l_kiwmi_view_on_pre_render(lua_State *L) lua_pushvalue(L, 2); lua_pushlightuserdata(L, kiwmi_view_on_render_notify); lua_pushlightuserdata(L, &view->events.pre_render); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_view_on_request_move(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); luaL_checktype(L, 2, LUA_TFUNCTION); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; struct kiwmi_desktop *desktop = view->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); @@ -578,22 +702,28 @@ l_kiwmi_view_on_request_move(lua_State *L) lua_pushvalue(L, 2); lua_pushlightuserdata(L, kiwmi_view_on_request_move_notify); lua_pushlightuserdata(L, &view->events.request_move); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static int l_kiwmi_view_on_request_resize(lua_State *L) { - struct kiwmi_view *view = - *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view"); luaL_checktype(L, 2, LUA_TFUNCTION); + if (!obj->valid) { + return luaL_error(L, "kiwmi_view no longer valid"); + } + + struct kiwmi_view *view = obj->object; struct kiwmi_desktop *desktop = view->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); @@ -602,13 +732,14 @@ l_kiwmi_view_on_request_resize(lua_State *L) lua_pushvalue(L, 2); lua_pushlightuserdata(L, kiwmi_view_on_request_resize_notify); lua_pushlightuserdata(L, &view->events.request_resize); + lua_pushlightuserdata(L, obj); - if (lua_pcall(L, 4, 1, 0)) { + if (lua_pcall(L, 5, 0, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); return 0; } - return 1; + return 0; } static const luaL_Reg kiwmi_view_events[] = { @@ -623,15 +754,20 @@ static const luaL_Reg kiwmi_view_events[] = { int luaK_kiwmi_view_new(lua_State *L) { - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_view + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); // kiwmi_lua + luaL_checktype(L, 2, LUA_TLIGHTUSERDATA); // kiwmi_view - struct kiwmi_view *view = lua_touserdata(L, 1); + struct kiwmi_lua *lua = lua_touserdata(L, 1); + struct kiwmi_view *view = lua_touserdata(L, 2); - struct kiwmi_view **view_ud = lua_newuserdata(L, sizeof(*view_ud)); + struct kiwmi_object *obj = + luaK_get_kiwmi_object(lua, view, &view->events.unmap); + + struct kiwmi_object **view_ud = lua_newuserdata(L, sizeof(*view_ud)); luaL_getmetatable(L, "kiwmi_view"); lua_setmetatable(L, -2); - *view_ud = view; + *view_ud = obj; return 1; } @@ -651,5 +787,8 @@ luaK_kiwmi_view_register(lua_State *L) 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; } diff --git a/kiwmi/luak/luak.c b/kiwmi/luak/luak.c index ffb350c..4964c01 100644 --- a/kiwmi/luak/luak.c +++ b/kiwmi/luak/luak.c @@ -22,10 +22,108 @@ #include "luak/kiwmi_server.h" #include "luak/kiwmi_view.h" +int +luaK_kiwmi_object_gc(lua_State *L) +{ + struct kiwmi_object *obj = *(struct kiwmi_object **)lua_touserdata(L, 1); + + --obj->refcount; + + if (obj->refcount == 0 && wl_list_empty(&obj->callbacks)) { + free(obj); + } + + return 0; +} + +static void +kiwmi_object_destroy_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_object *obj = wl_container_of(listener, obj, destroy); + + wl_signal_emit(&obj->events.destroy, data); + + struct kiwmi_lua_callback *lc; + struct kiwmi_lua_callback *tmp; + wl_list_for_each_safe (lc, tmp, &obj->callbacks, link) { + wl_list_remove(&lc->listener.link); + wl_list_remove(&lc->link); + + luaL_unref(lc->server->lua->L, LUA_REGISTRYINDEX, lc->callback_ref); + + free(lc); + } + + wl_list_remove(&obj->destroy.link); + + lua_State *L = obj->lua->L; + + lua_rawgeti(L, LUA_REGISTRYINDEX, obj->lua->objects); + lua_pushlightuserdata(L, obj->object); + lua_pushnil(L); + lua_settable(L, -3); + lua_pop(L, 1); + + obj->valid = false; + + if (obj->refcount == 0) { + free(obj); + } +} + +struct kiwmi_object * +luaK_get_kiwmi_object( + struct kiwmi_lua *lua, + void *ptr, + struct wl_signal *destroy) +{ + lua_State *L = lua->L; + + lua_rawgeti(L, LUA_REGISTRYINDEX, lua->objects); + lua_pushlightuserdata(L, ptr); + lua_gettable(L, -2); + + struct kiwmi_object *obj = lua_touserdata(L, -1); + + lua_pop(L, 2); + + if (obj) { + ++obj->refcount; + return obj; + } + + obj = malloc(sizeof(*obj)); + if (!obj) { + wlr_log(WLR_ERROR, "Failed to allocate kiwmi_object"); + return NULL; + } + + obj->lua = lua; + obj->object = ptr; + obj->refcount = 1; + obj->valid = true; + + if (destroy) { + obj->destroy.notify = kiwmi_object_destroy_notify; + wl_signal_add(destroy, &obj->destroy); + + wl_signal_init(&obj->events.destroy); + } + + wl_list_init(&obj->callbacks); + + lua_rawgeti(L, LUA_REGISTRYINDEX, lua->objects); + lua_pushlightuserdata(L, ptr); + lua_pushlightuserdata(L, obj); + lua_settable(L, -3); + + return obj; +} + int luaK_callback_register_dispatch(lua_State *L) { - luaL_checktype(L, 1, LUA_TUSERDATA); // server + luaL_checktype(L, 1, LUA_TUSERDATA); // object luaL_checktype(L, 2, LUA_TSTRING); // type luaL_checktype(L, 3, LUA_TFUNCTION); // callback @@ -77,8 +175,14 @@ luaK_create(struct kiwmi_server *server) return NULL; } + lua->L = L; + luaL_openlibs(L); + // init object registry + lua_newtable(L); + lua->objects = luaL_ref(L, LUA_REGISTRYINDEX); + // register types int error = 0; @@ -86,8 +190,6 @@ luaK_create(struct kiwmi_server *server) error |= lua_pcall(L, 0, 0, 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_output_register); error |= lua_pcall(L, 0, 0, 0); lua_pushcfunction(L, luaK_kiwmi_renderer_register); @@ -100,14 +202,14 @@ luaK_create(struct kiwmi_server *server) if (error) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_close(L); - free(lua); return NULL; } // create kiwmi global lua_pushcfunction(L, luaK_kiwmi_server_new); + lua_pushlightuserdata(L, lua); lua_pushlightuserdata(L, server); - if (lua_pcall(L, 1, 1, 0)) { + if (lua_pcall(L, 2, 1, 0)) { wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); lua_close(L); free(lua); @@ -115,10 +217,6 @@ luaK_create(struct kiwmi_server *server) } lua_setglobal(L, "kiwmi"); - lua->L = L; - - wl_list_init(&lua->callbacks); - if (!luaK_ipc_init(server, lua)) { wlr_log(WLR_ERROR, "Failed to initialize IPC"); lua_close(L); @@ -148,8 +246,6 @@ luaK_dofile(struct kiwmi_lua *lua, const char *config_path) void luaK_destroy(struct kiwmi_lua *lua) { - luaK_kiwmi_lua_callback_cleanup(lua); - lua_close(lua->L); free(lua); diff --git a/lua_docs.md b/lua_docs.md index a03e418..9d72425 100644 --- a/lua_docs.md +++ b/lua_docs.md @@ -143,12 +143,6 @@ The compositor will not forward it to the focused view in that case. A handle to a registered callback. -### Methods - -#### callback:cancel() - -Unregisters the callback. - ## kiwmi_output Represents an output (most often a display).