diff --git a/include/desktop/desktop.h b/include/desktop/desktop.h index 196e1d8..17f7bdd 100644 --- a/include/desktop/desktop.h +++ b/include/desktop/desktop.h @@ -14,6 +14,7 @@ struct kiwmi_desktop { struct wlr_compositor *compositor; struct wlr_xdg_shell *xdg_shell; + struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager; struct wlr_layer_shell_v1 *layer_shell; struct wlr_data_device_manager *data_device_manager; struct wlr_output_layout *output_layout; @@ -21,6 +22,7 @@ struct kiwmi_desktop { struct wl_list views; // struct kiwmi_view::link struct wl_listener xdg_shell_new_surface; + struct wl_listener xdg_toplevel_new_decoration; struct wl_listener layer_shell_new_surface; struct wl_listener new_output; diff --git a/include/desktop/view.h b/include/desktop/view.h index 7fc388d..9bd85a8 100644 --- a/include/desktop/view.h +++ b/include/desktop/view.h @@ -60,6 +60,8 @@ struct kiwmi_view { struct wl_signal request_move; struct wl_signal request_resize; } events; + + struct kiwmi_xdg_decoration *decoration; }; struct kiwmi_view_impl { diff --git a/include/desktop/xdg_shell.h b/include/desktop/xdg_shell.h index 7b85275..ddfd742 100644 --- a/include/desktop/xdg_shell.h +++ b/include/desktop/xdg_shell.h @@ -10,6 +10,16 @@ #include +struct kiwmi_xdg_decoration { + struct kiwmi_view *view; + struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration; + + struct wl_listener destroy; + struct wl_listener request_mode; +}; + void xdg_shell_new_surface_notify(struct wl_listener *listener, void *data); +void +xdg_toplevel_new_decoration_notify(struct wl_listener *listener, void *data); #endif /* KIWMI_DESKTOP_XDG_SHELL_H */ diff --git a/kiwmi/desktop/desktop.c b/kiwmi/desktop/desktop.c index d4e96e6..81d93b4 100644 --- a/kiwmi/desktop/desktop.c +++ b/kiwmi/desktop/desktop.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,14 @@ desktop_init(struct kiwmi_desktop *desktop, struct wlr_renderer *renderer) &desktop->xdg_shell->events.new_surface, &desktop->xdg_shell_new_surface); + desktop->xdg_decoration_manager = + wlr_xdg_decoration_manager_v1_create(server->wl_display); + desktop->xdg_toplevel_new_decoration.notify = + xdg_toplevel_new_decoration_notify; + wl_signal_add( + &desktop->xdg_decoration_manager->events.new_toplevel_decoration, + &desktop->xdg_toplevel_new_decoration); + desktop->layer_shell = wlr_layer_shell_v1_create(server->wl_display); desktop->layer_shell_new_surface.notify = layer_shell_new_surface_notify; wl_signal_add( diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index 22432d2..92bcecc 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -224,11 +224,12 @@ view_create( return NULL; } - view->desktop = desktop; - view->type = type; - view->impl = impl; - view->mapped = false; - view->hidden = true; + view->desktop = desktop; + view->type = type; + view->impl = impl; + view->mapped = false; + view->hidden = true; + view->decoration = NULL; view->x = 0; view->y = 0; diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index 4a469b4..b579f60 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -219,6 +220,8 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data) return; } + xdg_surface->data = view; + view->xdg_surface = xdg_surface; view->wlr_surface = xdg_surface->surface; @@ -244,3 +247,64 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data) wl_list_insert(&desktop->views, &view->link); } + +static void +xdg_decoration_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) +{ + struct kiwmi_xdg_decoration *decoration = + wl_container_of(listener, decoration, destroy); + + decoration->view->decoration = NULL; + + wl_list_remove(&decoration->destroy.link); + wl_list_remove(&decoration->request_mode.link); + + free(decoration); +} + +static void +xdg_decoration_request_mode_notify( + struct wl_listener *listener, + void *UNUSED(data)) +{ + struct kiwmi_xdg_decoration *decoration = + wl_container_of(listener, decoration, request_mode); + + enum wlr_xdg_toplevel_decoration_v1_mode mode = + decoration->wlr_decoration->client_pending_mode; + if (mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_NONE) { + mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + } + + wlr_xdg_toplevel_decoration_v1_set_mode(decoration->wlr_decoration, mode); +} + +void +xdg_toplevel_new_decoration_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_desktop *desktop = + wl_container_of(listener, desktop, xdg_toplevel_new_decoration); + struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration = data; + + wlr_log(WLR_DEBUG, "New xdg_toplevel decoration"); + + struct kiwmi_view *view = wlr_decoration->surface->data; + + struct kiwmi_xdg_decoration *decoration = malloc(sizeof(*decoration)); + if (!decoration) { + wlr_log(WLR_ERROR, "Failed to allocate xdg_decoration"); + return; + } + + view->decoration = decoration; + + decoration->view = view; + decoration->wlr_decoration = wlr_decoration; + + decoration->destroy.notify = xdg_decoration_destroy_notify; + wl_signal_add(&wlr_decoration->events.destroy, &decoration->destroy); + + decoration->request_mode.notify = xdg_decoration_request_mode_notify; + wl_signal_add( + &wlr_decoration->events.request_mode, &decoration->request_mode); +} diff --git a/kiwmi/luak/kiwmi_view.c b/kiwmi/luak/kiwmi_view.c index bd63486..0d8c93e 100644 --- a/kiwmi/luak/kiwmi_view.c +++ b/kiwmi/luak/kiwmi_view.c @@ -11,10 +11,12 @@ #include #include +#include #include #include #include "desktop/view.h" +#include "desktop/xdg_shell.h" #include "input/seat.h" #include "luak/kiwmi_lua_callback.h" #include "server.h" @@ -41,6 +43,30 @@ l_kiwmi_view_close(lua_State *L) return 0; } +static int +l_kiwmi_view_csd(lua_State *L) +{ + struct kiwmi_view *view = + *(struct kiwmi_view **)luaL_checkudata(L, 1, "kiwmi_view"); + luaL_checktype(L, 2, LUA_TBOOLEAN); + + struct kiwmi_xdg_decoration *decoration = view->decoration; + if (!decoration) { + return 0; + } + + enum wlr_xdg_toplevel_decoration_v1_mode mode; + if (lua_toboolean(L, 2)) { + mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + } else { + mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + } + + wlr_xdg_toplevel_decoration_v1_set_mode(decoration->wlr_decoration, mode); + + return 0; +} + static int l_kiwmi_view_focus(lua_State *L) { @@ -282,6 +308,7 @@ l_kiwmi_view_title(lua_State *L) static const luaL_Reg kiwmi_view_methods[] = { {"app_id", l_kiwmi_view_app_id}, {"close", l_kiwmi_view_close}, + {"csd", l_kiwmi_view_csd}, {"focus", l_kiwmi_view_focus}, {"hidden", l_kiwmi_view_hidden}, {"hide", l_kiwmi_view_hide}, diff --git a/lua_docs.md b/lua_docs.md index ff1dd1a..ad89749 100644 --- a/lua_docs.md +++ b/lua_docs.md @@ -209,6 +209,10 @@ This is comparable to the window class of X windows. Closes the view. +#### view:csd(client_draws) + +Set whether the client is supposed to draw their own client decoration. + #### view:focus() Focuses the view.