Add object lifetimes (invalidate references, free listeners)

This commit is contained in:
buffet 2020-02-06 17:55:05 +00:00
parent a0f53a31ce
commit 1d755a8a74
13 changed files with 860 additions and 249 deletions

View file

@ -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 */

View file

@ -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);

View file

@ -0,0 +1,277 @@
wow such kakoune/* Copyright (c), Charlotte Meyer <dev@buffet.sh>
*
* 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 <stdlib.h>
#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/util/log.h>
#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);
}

View file

@ -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);
if (view->mapped) {
view->mapped = false;
wl_signal_emit(&view->events.unmap, view);
}
}
static void

View file

@ -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;
}

View file

@ -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,33 +146,44 @@ 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);
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);
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);
@ -172,22 +191,28 @@ l_kiwmi_keyboard_on_key_down(lua_State *L)
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);
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);
@ -195,13 +220,14 @@ l_kiwmi_keyboard_on_key_up(lua_State *L)
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;
}

View file

@ -12,27 +12,6 @@
#include <lauxlib.h>
#include <wayland-server.h>
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);
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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).