diff --git a/include/desktop/view.h b/include/desktop/view.h index e95fbf7..b9fe85b 100644 --- a/include/desktop/view.h +++ b/include/desktop/view.h @@ -57,6 +57,8 @@ struct kiwmi_view { struct { struct wl_signal unmap; + struct wl_signal request_move; + struct wl_signal request_resize; } events; }; @@ -82,6 +84,11 @@ struct kiwmi_view_impl { double *sub_y); }; +struct kiwmi_request_resize_event { + struct kiwmi_view *view; + uint32_t edges; +}; + void view_close(struct kiwmi_view *view); void view_for_each_surface( struct kiwmi_view *view, diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index eba8dc3..483b8e4 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -234,6 +234,8 @@ view_create( view->y = 0; wl_signal_init(&view->events.unmap); + wl_signal_init(&view->events.request_move); + wl_signal_init(&view->events.request_resize); return view; } diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index d095c94..8230e23 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -75,7 +75,7 @@ xdg_toplevel_request_move_notify( { struct kiwmi_view *view = wl_container_of(listener, view, request_move); - view_move(view); + wl_signal_emit(&view->events.request_move, view); } static void @@ -84,7 +84,12 @@ xdg_toplevel_request_resize_notify(struct wl_listener *listener, void *data) struct kiwmi_view *view = wl_container_of(listener, view, request_resize); struct wlr_xdg_toplevel_resize_event *event = data; - view_resize(view, event->edges); + struct kiwmi_request_resize_event new_event = { + .view = view, + .edges = event->edges, + }; + + wl_signal_emit(&view->events.request_resize, &new_event); } static void diff --git a/kiwmi/luak/kiwmi_view.c b/kiwmi/luak/kiwmi_view.c index 00f330c..81e2338 100644 --- a/kiwmi/luak/kiwmi_view.c +++ b/kiwmi/luak/kiwmi_view.c @@ -78,6 +78,58 @@ l_kiwmi_view_hide(lua_State *L) return 0; } +static int +l_kiwmi_view_imove(lua_State *L) +{ + struct kiwmi_view *view = + *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + + view_move(view); + + return 0; +} + +static int +l_kiwmi_view_iresize(lua_State *L) +{ + struct kiwmi_view *view = + *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + luaL_checktype(L, 2, LUA_TTABLE); + + enum wlr_edges edges = WLR_EDGE_NONE; + + lua_pushnil(L); + while (lua_next(L, 2)) { + if (!lua_isstring(L, -1)) { + lua_pop(L, 1); + continue; + } + + const char *edge = lua_tostring(L, -1); + + switch (edge[0]) { + case 't': + edges |= WLR_EDGE_TOP; + break; + case 'b': + edges |= WLR_EDGE_BOTTOM; + break; + case 'l': + edges |= WLR_EDGE_LEFT; + break; + case 'r': + edges |= WLR_EDGE_RIGHT; + break; + } + + lua_pop(L, 1); + } + + view_resize(view, edges); + + return 0; +} + static int l_kiwmi_view_move(lua_State *L) { @@ -233,6 +285,8 @@ static const luaL_Reg kiwmi_view_methods[] = { {"focus", l_kiwmi_view_focus}, {"hidden", l_kiwmi_view_hidden}, {"hide", l_kiwmi_view_hide}, + {"imove", l_kiwmi_view_imove}, + {"iresize", l_kiwmi_view_iresize}, {"move", l_kiwmi_view_move}, {"on", luaK_callback_register_dispatch}, {"pid", l_kiwmi_view_pid}, @@ -270,6 +324,87 @@ kiwmi_view_on_destroy_notify(struct wl_listener *listener, void *data) } } +static void +kiwmi_view_on_request_move_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_lua_callback *lc = wl_container_of(listener, lc, listener); + struct kiwmi_server *server = lc->server; + lua_State *L = server->lua->L; + struct kiwmi_view *view = data; + + lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); + + lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, view); + + if (lua_pcall(L, 1, 1, 0)) { + wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); + lua_pop(L, 1); + return; + } + + if (lua_pcall(L, 1, 0, 0)) { + wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); + lua_pop(L, 1); + } +} + +static void +kiwmi_view_on_request_resize_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_lua_callback *lc = wl_container_of(listener, lc, listener); + struct kiwmi_server *server = lc->server; + lua_State *L = server->lua->L; + + struct kiwmi_request_resize_event *event = data; + struct kiwmi_view *view = event->view; + + lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); + + lua_newtable(L); + + lua_pushcfunction(L, luaK_kiwmi_view_new); + lua_pushlightuserdata(L, view); + + if (lua_pcall(L, 1, 1, 0)) { + wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); + lua_pop(L, 1); + return; + } + + lua_setfield(L, -2, "view"); + + lua_newtable(L); + int idx = 1; + + if (event->edges & WLR_EDGE_TOP) { + lua_pushstring(L, "top"); + lua_rawseti(L, -2, idx++); + } + + if (event->edges & WLR_EDGE_BOTTOM) { + lua_pushstring(L, "bottom"); + lua_rawseti(L, -2, idx++); + } + + if (event->edges & WLR_EDGE_LEFT) { + lua_pushstring(L, "left"); + lua_rawseti(L, -2, idx++); + } + + if (event->edges & WLR_EDGE_RIGHT) { + lua_pushstring(L, "right"); + lua_rawseti(L, -2, idx++); + } + + lua_setfield(L, -2, "edges"); + + if (lua_pcall(L, 1, 0, 0)) { + wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); + lua_pop(L, 1); + } +} + static int l_kiwmi_view_on_destroy(lua_State *L) { @@ -294,8 +429,58 @@ l_kiwmi_view_on_destroy(lua_State *L) return 1; } +static int +l_kiwmi_view_on_request_move(lua_State *L) +{ + struct kiwmi_view *view = + *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + luaL_checktype(L, 2, LUA_TFUNCTION); + + struct kiwmi_desktop *desktop = view->desktop; + struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + + lua_pushcfunction(L, luaK_kiwmi_lua_callback_new); + lua_pushlightuserdata(L, server); + lua_pushvalue(L, 2); + lua_pushlightuserdata(L, kiwmi_view_on_request_move_notify); + lua_pushlightuserdata(L, &view->events.request_move); + + if (lua_pcall(L, 4, 1, 0)) { + wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); + return 0; + } + + return 1; +} + +static int +l_kiwmi_view_on_request_resize(lua_State *L) +{ + struct kiwmi_view *view = + *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + luaL_checktype(L, 2, LUA_TFUNCTION); + + struct kiwmi_desktop *desktop = view->desktop; + struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + + lua_pushcfunction(L, luaK_kiwmi_lua_callback_new); + lua_pushlightuserdata(L, server); + lua_pushvalue(L, 2); + lua_pushlightuserdata(L, kiwmi_view_on_request_resize_notify); + lua_pushlightuserdata(L, &view->events.request_resize); + + if (lua_pcall(L, 4, 1, 0)) { + wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); + return 0; + } + + return 1; +} + static const luaL_Reg kiwmi_view_events[] = { {"destroy", l_kiwmi_view_on_destroy}, + {"request_move", l_kiwmi_view_on_request_move}, + {"request_resize", l_kiwmi_view_on_request_resize}, {NULL, NULL}, }; diff --git a/lua_docs.md b/lua_docs.md index 503c5f2..ef2a659 100644 --- a/lua_docs.md +++ b/lua_docs.md @@ -217,6 +217,15 @@ Returns `true` if the view is hidden, `false` otherwise. Hides the view. +#### view:imove() + +Starts an interactive move. + +#### view:iresize(edges) + +Starts an interactive resize. +Takes a table containing the edges, that the resize is happening on. + #### view:move(x, y) Moves the view to the specified position. @@ -261,3 +270,13 @@ Returns the title of the view. The view is being destroyed. Callback receives the view. + +#### request_move + +The view wants to start an interactive move. +Callback receives the view. + +#### request_resize + +The view wants to start an interactive resize. +Callback receives a table containing the `view`, and `edges`, containing the edges.