From 398e0f150fc1131a89da86846099baf5f6d75248 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Fri, 1 Jul 2022 15:26:23 +0000 Subject: [PATCH 01/10] output: While destroying, destroy layers Also handle NULL output in output_damage(). Co-authored-by: Uks2 --- kiwmi/desktop/layer_shell.c | 6 ++++-- kiwmi/desktop/output.c | 21 ++++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/kiwmi/desktop/layer_shell.c b/kiwmi/desktop/layer_shell.c index 78e4a34..3acb3b7 100644 --- a/kiwmi/desktop/layer_shell.c +++ b/kiwmi/desktop/layer_shell.c @@ -24,12 +24,14 @@ kiwmi_layer_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_layer *layer = wl_container_of(listener, layer, destroy); - wl_list_remove(&layer->link); wl_list_remove(&layer->destroy.link); wl_list_remove(&layer->map.link); wl_list_remove(&layer->unmap.link); - arrange_layers(layer->output); + if (layer->output != NULL) { + wl_list_remove(&layer->link); + arrange_layers(layer->output); + } free(layer); } diff --git a/kiwmi/desktop/output.c b/kiwmi/desktop/output.c index eeb62f3..98bf57b 100644 --- a/kiwmi/desktop/output.c +++ b/kiwmi/desktop/output.c @@ -261,13 +261,26 @@ output_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_output *output = wl_container_of(listener, output, destroy); + wl_signal_emit(&output->events.destroy, output); + + int n_layers = sizeof(output->layers) / sizeof(output->layers[0]); + for (int i = 0; i < n_layers; i++) { + struct kiwmi_layer *layer; + struct kiwmi_layer *tmp; + wl_list_for_each_safe (layer, tmp, &output->layers[i], link) { + // Set output to NULL to avoid rearranging the remaining layers. + // Our impl requires that we remove the layer from the list. + layer->output = NULL; + wl_list_remove(&layer->link); + wlr_layer_surface_v1_destroy(layer->layer_surface); + } + } + if (output->desktop->output_layout) { 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->commit.link); @@ -384,5 +397,7 @@ new_output_notify(struct wl_listener *listener, void *data) void output_damage(struct kiwmi_output *output) { - output->damaged = 2; + if (output != NULL) { + output->damaged = 2; + } } From 7c98b5e5dc2a4df0e9af6c617c1db8845574d28b Mon Sep 17 00:00:00 2001 From: tiosgz Date: Wed, 22 Dec 2021 18:15:09 +0000 Subject: [PATCH 02/10] Remove API that relies on our rendering This is a preparation for switching to the wlroots scene-graph. There is no replacement planned for output:redraw() because it will no longer be necessary (as far as i can tell), while scene-compatible replacements for the view pre_render/post_render events are planned. --- include/luak/kiwmi_renderer.h | 16 ----- kiwmi/luak/kiwmi_output.c | 18 ------ kiwmi/luak/kiwmi_renderer.c | 100 ----------------------------- kiwmi/luak/kiwmi_view.c | 114 ++-------------------------------- kiwmi/luak/luak.c | 3 - kiwmi/meson.build | 1 - lua_docs.md | 25 +------- 7 files changed, 6 insertions(+), 271 deletions(-) delete mode 100644 include/luak/kiwmi_renderer.h delete mode 100644 kiwmi/luak/kiwmi_renderer.c diff --git a/include/luak/kiwmi_renderer.h b/include/luak/kiwmi_renderer.h deleted file mode 100644 index 5333fe2..0000000 --- a/include/luak/kiwmi_renderer.h +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (c), Niclas Meyer - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -#ifndef KIWMI_LUAK_KIWMI_RENDERER_H -#define KIWMI_LUAK_KIWMI_RENDERER_H - -#include - -int luaK_kiwmi_renderer_new(lua_State *L); -int luaK_kiwmi_renderer_register(lua_State *L); - -#endif /* KIWMI_LUAK_KIWMI_RENDERER_H */ diff --git a/kiwmi/luak/kiwmi_output.c b/kiwmi/luak/kiwmi_output.c index e76c61c..42740ab 100644 --- a/kiwmi/luak/kiwmi_output.c +++ b/kiwmi/luak/kiwmi_output.c @@ -98,23 +98,6 @@ l_kiwmi_output_pos(lua_State *L) return 2; } -static int -l_kiwmi_output_redraw(lua_State *L) -{ - 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; - - output_damage(output); - - return 0; -} - static int l_kiwmi_output_size(lua_State *L) { @@ -168,7 +151,6 @@ static const luaL_Reg kiwmi_output_methods[] = { {"name", l_kiwmi_output_name}, {"on", luaK_callback_register_dispatch}, {"pos", l_kiwmi_output_pos}, - {"redraw", l_kiwmi_output_redraw}, {"size", l_kiwmi_output_size}, {"usable_area", l_kiwmi_output_usable_area}, {NULL, NULL}, diff --git a/kiwmi/luak/kiwmi_renderer.c b/kiwmi/luak/kiwmi_renderer.c deleted file mode 100644 index 46fcf27..0000000 --- a/kiwmi/luak/kiwmi_renderer.c +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (c), Niclas Meyer - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -#include "luak/kiwmi_renderer.h" - -#include -#include - -#include -#include -#include -#include - -#include "color.h" -#include "desktop/output.h" -#include "luak/lua_compat.h" -#include "luak/luak.h" - -struct kiwmi_renderer { - struct wlr_renderer *wlr_renderer; - struct kiwmi_output *output; -}; - -static int -l_kiwmi_renderer_draw_rect(lua_State *L) -{ - struct kiwmi_renderer *renderer = - (struct kiwmi_renderer *)luaL_checkudata(L, 1, "kiwmi_renderer"); - luaL_checktype(L, 2, LUA_TSTRING); // color - luaL_checktype(L, 3, LUA_TNUMBER); // x - luaL_checktype(L, 4, LUA_TNUMBER); // y - luaL_checktype(L, 5, LUA_TNUMBER); // width - luaL_checktype(L, 6, LUA_TNUMBER); // height - - struct wlr_renderer *wlr_renderer = renderer->wlr_renderer; - struct kiwmi_output *output = renderer->output; - struct wlr_output *wlr_output = output->wlr_output; - - float color[4]; - if (!color_parse(lua_tostring(L, 2), color)) { - return luaL_argerror(L, 2, "not a valid color"); - } - - struct wlr_box box = { - .x = lua_tonumber(L, 3), - .y = lua_tonumber(L, 4), - .width = lua_tonumber(L, 5), - .height = lua_tonumber(L, 6), - }; - - wlr_render_rect(wlr_renderer, &box, color, wlr_output->transform_matrix); - - return 0; -} - -static const luaL_Reg kiwmi_renderer_methods[] = { - {"draw_rect", l_kiwmi_renderer_draw_rect}, - {NULL, NULL}, -}; - -int -luaK_kiwmi_renderer_new(lua_State *L) -{ - 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 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)); - luaL_getmetatable(L, "kiwmi_renderer"); - lua_setmetatable(L, -2); - - renderer_ud->wlr_renderer = wlr_renderer; - renderer_ud->output = output; - - return 1; -} - -int -luaK_kiwmi_renderer_register(lua_State *L) -{ - luaL_newmetatable(L, "kiwmi_renderer"); - - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - luaC_setfuncs(L, kiwmi_renderer_methods, 0); - - lua_pushcfunction(L, luaK_usertype_ref_equal); - lua_setfield(L, -2, "__eq"); - - return 0; -} diff --git a/kiwmi/luak/kiwmi_view.c b/kiwmi/luak/kiwmi_view.c index 791347b..3e691dc 100644 --- a/kiwmi/luak/kiwmi_view.c +++ b/kiwmi/luak/kiwmi_view.c @@ -21,7 +21,6 @@ #include "input/seat.h" #include "luak/kiwmi_lua_callback.h" #include "luak/kiwmi_output.h" -#include "luak/kiwmi_renderer.h" #include "luak/lua_compat.h" #include "server.h" @@ -471,65 +470,6 @@ kiwmi_view_on_destroy_notify(struct wl_listener *listener, void *data) } } -static void -kiwmi_view_on_render_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_render_data *rdata = data; - - struct kiwmi_view *view = rdata->data; - struct wlr_renderer *renderer = rdata->renderer; - struct kiwmi_output *output = rdata->output->data; - - lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); - - lua_newtable(L); - - lua_pushcfunction(L, luaK_kiwmi_view_new); - lua_pushlightuserdata(L, server->lua); - lua_pushlightuserdata(L, view); - - if (lua_pcall(L, 2, 1, 0)) { - wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); - lua_pop(L, 1); - return; - } - - 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, 2, 1, 0)) { - wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); - lua_pop(L, 1); - return; - } - - 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, 3, 1, 0)) { - wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); - lua_pop(L, 1); - return; - } - - lua_setfield(L, -2, "renderer"); - - 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_move_notify(struct wl_listener *listener, void *data) { @@ -644,62 +584,16 @@ l_kiwmi_view_on_destroy(lua_State *L) } static int -l_kiwmi_view_on_post_render(lua_State *L) +l_kiwmi_view_on_post_render(lua_State *UNUSED(L)) { - 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); - - lua_pushcfunction(L, luaK_kiwmi_lua_callback_new); - lua_pushlightuserdata(L, server); - 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, 5, 0, 0)) { - wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); - return 0; - } - + // noop return 0; } static int -l_kiwmi_view_on_pre_render(lua_State *L) +l_kiwmi_view_on_pre_render(lua_State *UNUSED(L)) { - 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); - - lua_pushcfunction(L, luaK_kiwmi_lua_callback_new); - lua_pushlightuserdata(L, server); - 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, 5, 0, 0)) { - wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); - return 0; - } - + // noop return 0; } diff --git a/kiwmi/luak/luak.c b/kiwmi/luak/luak.c index f00a407..0a34b94 100644 --- a/kiwmi/luak/luak.c +++ b/kiwmi/luak/luak.c @@ -18,7 +18,6 @@ #include "luak/kiwmi_keyboard.h" #include "luak/kiwmi_lua_callback.h" #include "luak/kiwmi_output.h" -#include "luak/kiwmi_renderer.h" #include "luak/kiwmi_server.h" #include "luak/kiwmi_view.h" @@ -220,8 +219,6 @@ luaK_create(struct kiwmi_server *server) 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); - error |= lua_pcall(L, 0, 0, 0); lua_pushcfunction(L, luaK_kiwmi_server_register); error |= lua_pcall(L, 0, 0, 0); lua_pushcfunction(L, luaK_kiwmi_view_register); diff --git a/kiwmi/meson.build b/kiwmi/meson.build index 13f7c9b..b61fac3 100644 --- a/kiwmi/meson.build +++ b/kiwmi/meson.build @@ -17,7 +17,6 @@ kiwmi_sources = files( 'luak/kiwmi_keyboard.c', 'luak/kiwmi_lua_callback.c', 'luak/kiwmi_output.c', - 'luak/kiwmi_renderer.c', 'luak/kiwmi_server.c', 'luak/kiwmi_view.c', 'luak/lua_compat.c', diff --git a/lua_docs.md b/lua_docs.md index 3eb0b26..7f63b60 100644 --- a/lua_docs.md +++ b/lua_docs.md @@ -240,10 +240,6 @@ Used to register event listeners. Get the position of the output. Returns two parameters: `x` and `y`. -#### output:redraw() - -Force the output to redraw. Useful e.g. when you know the view `pre_render`/`post_render` callbacks are going to change. - #### output:size() Get the size of the output. @@ -270,17 +266,6 @@ Callback receives a table containing the `output`, the new `width`, and the new The usable area of this output has changed, e.g. because the output was resized or the bars around it changed. Callback receives a table containing the `output` and the new `x`, `y`, `width` and `height`. -## kiwmi_renderer - -Represents a rendering context, to draw on the output. - -### Methods - -#### renderer:draw_rect(color, x, y, w, h) - -Draws a rect at the given position. -Color is a string in the form #rrggbb or #rrggbbaa. - ## kiwmi_view Represents a view (a window in kiwmi terms). @@ -373,17 +358,11 @@ Callback receives the view. #### post_render -The view finished being rendered. -Callback receives a table with the `view`, the `renderer` and the `output`. - -This event occurs once per output the view might be drawn on. +This is a no-op event. Temporarily preserved only to make config migration easier. #### pre_render -The view is about to be rendered. -Callback receives a table with the `view`, the `renderer` and the `output`. - -This event occurs once per output the view might be drawn on. +This is a no-op event. Temporarily preserved only to make config migration easier. #### request_move From 8c191d2d418ad56b5bd48032e93385a0700dc8e7 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Sun, 3 Apr 2022 11:59:31 +0000 Subject: [PATCH 03/10] Introduce kiwmi_strata With the migration to wlr_scene, some objects (desktop, output etc) will no longer have any reason to care about individual shells and similar; handling each one on its own would introduce code that is, from their perspective, over-complicated. Strata (sg. stratum; this name was chosen to avoid confusion with the over-used 'layer') represent logical layers of surfaces on the desktop, such as every layer shell layer, one for xdg shell, another for popups. --- include/desktop/layer_shell.h | 2 +- include/desktop/stratum.h | 33 +++++++++++++++++++++++++++++++++ kiwmi/desktop/stratum.c | 33 +++++++++++++++++++++++++++++++++ kiwmi/meson.build | 1 + 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 include/desktop/stratum.h create mode 100644 kiwmi/desktop/stratum.c diff --git a/include/desktop/layer_shell.h b/include/desktop/layer_shell.h index 837275e..cec4397 100644 --- a/include/desktop/layer_shell.h +++ b/include/desktop/layer_shell.h @@ -19,7 +19,7 @@ struct kiwmi_layer { struct wl_list link; struct wlr_layer_surface_v1 *layer_surface; - uint32_t layer; + uint32_t layer; // enum zwlr_layer_shell_v1_layer struct kiwmi_output *output; diff --git a/include/desktop/stratum.h b/include/desktop/stratum.h new file mode 100644 index 0000000..33ad252 --- /dev/null +++ b/include/desktop/stratum.h @@ -0,0 +1,33 @@ +/* Copyright (c), Niclas Meyer + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef KIWMI_DESKTOP_STRATUM_H +#define KIWMI_DESKTOP_STRATUM_H + +#include + +/** + * A stratum is a layer in the scene-graph (the name was chosen to avoid + * confusion with layer-shell). The root node contains a scene_tree for each + * stratum, which itself contains a scene_tree per output. + */ + +// There are some assumptions made about the values, don't mindlessly change. +enum kiwmi_stratum { + KIWMI_STRATUM_LS_BACKGROUND, // LS == layer_shell + KIWMI_STRATUM_LS_BOTTOM, + KIWMI_STRATUM_NORMAL, + KIWMI_STRATUM_LS_TOP, + KIWMI_STRATUM_LS_OVERLAY, + KIWMI_STRATUM_POPUPS, + KIWMI_STRATA_COUNT, + KIWMI_STRATUM_NONE = KIWMI_STRATA_COUNT, +}; + +enum kiwmi_stratum stratum_from_layer_shell_layer(uint32_t layer); + +#endif /* KIWMI_DESKTOP_STRATUM_H */ diff --git a/kiwmi/desktop/stratum.c b/kiwmi/desktop/stratum.c new file mode 100644 index 0000000..dd9adc0 --- /dev/null +++ b/kiwmi/desktop/stratum.c @@ -0,0 +1,33 @@ +/* Copyright (c), Niclas Meyer + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include "desktop/stratum.h" +#include "wlr-layer-shell-unstable-v1-protocol.h" + +enum kiwmi_stratum +stratum_from_layer_shell_layer(uint32_t layer) +{ + switch (layer) { + case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND: + return KIWMI_STRATUM_LS_BACKGROUND; + case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM: + return KIWMI_STRATUM_LS_BOTTOM; + case ZWLR_LAYER_SHELL_V1_LAYER_TOP: + return KIWMI_STRATUM_LS_TOP; + case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY: + return KIWMI_STRATUM_LS_OVERLAY; + default: + // We should update our codebase to support the layer + wlr_log( + WLR_ERROR, "No matching stratum for layer_shell layer %d", layer); + return KIWMI_STRATUM_NONE; + } +} diff --git a/kiwmi/meson.build b/kiwmi/meson.build index b61fac3..eb3a962 100644 --- a/kiwmi/meson.build +++ b/kiwmi/meson.build @@ -5,6 +5,7 @@ kiwmi_sources = files( 'desktop/desktop.c', 'desktop/layer_shell.c', 'desktop/output.c', + 'desktop/stratum.c', 'desktop/view.c', 'desktop/xdg_shell.c', 'input/cursor.c', From f144eb14382cdd7ee77c9eb1c52921e606ced207 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Wed, 22 Dec 2021 20:46:15 +0000 Subject: [PATCH 04/10] Keep an up-to-date wlr scene-graph At the moment it isn't used at all and a lot of data is duplicated. This is a temporary state introduced for nicer diff separation into several commits. --- include/desktop/desktop.h | 10 +++++ include/desktop/desktop_surface.h | 27 ++++++++++++ include/desktop/layer_shell.h | 3 ++ include/desktop/output.h | 8 +++- include/desktop/popup.h | 20 +++++++++ include/desktop/view.h | 4 ++ kiwmi/desktop/desktop.c | 27 ++++++++++++ kiwmi/desktop/layer_shell.c | 63 +++++++++++++++++++++------ kiwmi/desktop/output.c | 47 +++++++++++++++++++- kiwmi/desktop/popup.c | 71 +++++++++++++++++++++++++++++++ kiwmi/desktop/view.c | 32 ++++++++++++++ kiwmi/desktop/xdg_shell.c | 30 ++++++++++++- kiwmi/input/seat.c | 4 ++ kiwmi/luak/kiwmi_server.c | 5 +++ kiwmi/luak/kiwmi_view.c | 4 +- kiwmi/meson.build | 1 + 16 files changed, 336 insertions(+), 20 deletions(-) create mode 100644 include/desktop/desktop_surface.h create mode 100644 include/desktop/popup.h create mode 100644 kiwmi/desktop/popup.c diff --git a/include/desktop/desktop.h b/include/desktop/desktop.h index 6fbdd35..1019230 100644 --- a/include/desktop/desktop.h +++ b/include/desktop/desktop.h @@ -9,23 +9,33 @@ #define KIWMI_DESKTOP_DESKTOP_H #include +#include + +#include "desktop/stratum.h" 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; struct wl_list outputs; // struct kiwmi_output::link struct wl_list views; // struct kiwmi_view::link float bg_color[4]; + struct wlr_scene *scene; + struct wlr_scene_rect *background_rect; + struct wlr_scene_tree *strata[KIWMI_STRATA_COUNT]; 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; + struct wl_listener output_layout_change; struct { struct wl_signal new_output; diff --git a/include/desktop/desktop_surface.h b/include/desktop/desktop_surface.h new file mode 100644 index 0000000..4efe0cd --- /dev/null +++ b/include/desktop/desktop_surface.h @@ -0,0 +1,27 @@ +/* Copyright (c), Niclas Meyer + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef KIWMI_DESKTOP_DESKTOP_SURFACE_H +#define KIWMI_DESKTOP_DESKTOP_SURFACE_H + +enum kiwmi_desktop_surface_type { + KIWMI_DESKTOP_SURFACE_VIEW, + KIWMI_DESKTOP_SURFACE_LAYER, +}; + +struct kiwmi_desktop_surface { + // The tree is where the config is supposed to put custom decorations (it + // also contains the surface_node) + struct wlr_scene_tree *tree; + struct wlr_scene_node *surface_node; + + struct wlr_scene_tree *popups_tree; + + enum kiwmi_desktop_surface_type type; +}; + +#endif /* KIWMI_DESKTOP_DESKTOP_SURFACE_H */ diff --git a/include/desktop/layer_shell.h b/include/desktop/layer_shell.h index cec4397..83fe3f7 100644 --- a/include/desktop/layer_shell.h +++ b/include/desktop/layer_shell.h @@ -14,10 +14,13 @@ #include #include +#include "desktop/desktop_surface.h" #include "desktop/output.h" struct kiwmi_layer { struct wl_list link; + struct kiwmi_desktop_surface desktop_surface; + struct wlr_layer_surface_v1 *layer_surface; uint32_t layer; // enum zwlr_layer_shell_v1_layer diff --git a/include/desktop/output.h b/include/desktop/output.h index 3f8c034..b3e11a1 100644 --- a/include/desktop/output.h +++ b/include/desktop/output.h @@ -11,16 +11,21 @@ #include #include +#include "desktop/stratum.h" + struct kiwmi_output { struct wl_list link; struct kiwmi_desktop *desktop; struct wlr_output *wlr_output; + struct wl_listener frame; struct wl_listener commit; struct wl_listener destroy; struct wl_listener mode; - struct wl_list layers[4]; // struct kiwmi_layer_surface::link + struct wl_list layers[4]; // struct kiwmi_layer::link + struct wlr_scene_tree *strata[KIWMI_STRATA_COUNT]; + struct wlr_box usable_area; int damaged; @@ -42,6 +47,7 @@ struct kiwmi_render_data { }; void new_output_notify(struct wl_listener *listener, void *data); +void output_layout_change_notify(struct wl_listener *listener, void *data); void output_damage(struct kiwmi_output *output); diff --git a/include/desktop/popup.h b/include/desktop/popup.h new file mode 100644 index 0000000..78ec98a --- /dev/null +++ b/include/desktop/popup.h @@ -0,0 +1,20 @@ +/* Copyright (c), Niclas Meyer + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#ifndef KIWMI_DESKTOP_POPUP_H +#define KIWMI_DESKTOP_POPUP_H + +struct wlr_xdg_popup; +struct kiwmi_desktop_surface; + +struct kiwmi_desktop_surface * +popup_get_desktop_surface(struct wlr_xdg_popup *popup); +void popup_attach( + struct wlr_xdg_popup *popup, + struct kiwmi_desktop_surface *desktop_surface); + +#endif /* KIWMI_DESKTOP_POPUP_H */ diff --git a/include/desktop/view.h b/include/desktop/view.h index 3055304..3a42617 100644 --- a/include/desktop/view.h +++ b/include/desktop/view.h @@ -17,6 +17,8 @@ #include #include +#include "desktop/desktop_surface.h" + enum kiwmi_view_prop { KIWMI_VIEW_PROP_APP_ID, KIWMI_VIEW_PROP_TITLE, @@ -29,6 +31,7 @@ enum kiwmi_view_type { struct kiwmi_view { struct wl_list link; struct wl_list children; // struct kiwmi_view_child::link + struct kiwmi_desktop_surface desktop_surface; struct kiwmi_desktop *desktop; @@ -143,6 +146,7 @@ void view_set_activated(struct kiwmi_view *view, bool activated); void view_set_size(struct kiwmi_view *view, uint32_t width, uint32_t height); void view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y); void view_set_tiled(struct kiwmi_view *view, enum wlr_edges edges); +void view_set_hidden(struct kiwmi_view *view, bool hidden); struct wlr_surface *view_surface_at( struct kiwmi_view *view, double sx, diff --git a/kiwmi/desktop/desktop.c b/kiwmi/desktop/desktop.c index dd9dc83..9bbeb48 100644 --- a/kiwmi/desktop/desktop.c +++ b/kiwmi/desktop/desktop.c @@ -20,9 +20,11 @@ #include #include #include +#include #include "desktop/layer_shell.h" #include "desktop/output.h" +#include "desktop/stratum.h" #include "desktop/view.h" #include "desktop/xdg_shell.h" #include "input/cursor.h" @@ -49,6 +51,25 @@ desktop_init(struct kiwmi_desktop *desktop) desktop->bg_color[2] = 0.1f; desktop->bg_color[3] = 1.0f; + desktop->scene = wlr_scene_create(); + if (!desktop->scene) { + wlr_log(WLR_ERROR, "failed to create scene"); + return false; + } + + const float bg_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + desktop->background_rect = + wlr_scene_rect_create(&desktop->scene->node, 0, 0, bg_color); + // No point in showing black + wlr_scene_node_set_enabled(&desktop->background_rect->node, false); + + // Create a scene-graph tree for each stratum + for (size_t i = 0; i < KIWMI_STRATA_COUNT; ++i) { + desktop->strata[i] = wlr_scene_tree_create(&desktop->scene->node); + } + + wlr_scene_attach_output_layout(desktop->scene, desktop->output_layout); + desktop->xdg_shell = wlr_xdg_shell_create(server->wl_display); desktop->xdg_shell_new_surface.notify = xdg_shell_new_surface_notify; wl_signal_add( @@ -75,6 +96,10 @@ desktop_init(struct kiwmi_desktop *desktop) desktop->new_output.notify = new_output_notify; wl_signal_add(&server->backend->events.new_output, &desktop->new_output); + desktop->output_layout_change.notify = output_layout_change_notify; + wl_signal_add( + &desktop->output_layout->events.change, &desktop->output_layout_change); + wl_signal_init(&desktop->events.new_output); wl_signal_init(&desktop->events.view_map); wl_signal_init(&desktop->events.request_active_output); @@ -87,6 +112,8 @@ desktop_fini(struct kiwmi_desktop *desktop) { wlr_output_layout_destroy(desktop->output_layout); desktop->output_layout = NULL; + wlr_scene_node_destroy(&desktop->scene->node); + desktop->scene = NULL; } struct kiwmi_output * diff --git a/kiwmi/desktop/layer_shell.c b/kiwmi/desktop/layer_shell.c index 3acb3b7..842f7c4 100644 --- a/kiwmi/desktop/layer_shell.c +++ b/kiwmi/desktop/layer_shell.c @@ -15,7 +15,9 @@ #include #include "desktop/desktop.h" +#include "desktop/desktop_surface.h" #include "desktop/output.h" +#include "desktop/stratum.h" #include "input/seat.h" #include "server.h" @@ -24,6 +26,9 @@ kiwmi_layer_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_layer *layer = wl_container_of(listener, layer, destroy); + wlr_scene_node_destroy(&layer->desktop_surface.tree->node); + wlr_scene_node_destroy(&layer->desktop_surface.popups_tree->node); + wl_list_remove(&layer->destroy.link); wl_list_remove(&layer->map.link); wl_list_remove(&layer->unmap.link); @@ -42,25 +47,22 @@ kiwmi_layer_commit_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_layer *layer = wl_container_of(listener, layer, commit); struct kiwmi_output *output = layer->output; - struct wlr_box old_geom = layer->geom; - - if (layer->layer_surface->current.committed != 0) { - arrange_layers(output); - } - - bool layer_changed = layer->layer != layer->layer_surface->current.layer; - bool geom_changed = memcmp(&old_geom, &layer->geom, sizeof(old_geom)) != 0; - bool buffer_changed = pixman_region32_not_empty( - &layer->layer_surface->surface->buffer_damage); - - if (layer_changed) { + if (layer->layer != layer->layer_surface->current.layer) { wl_list_remove(&layer->link); layer->layer = layer->layer_surface->current.layer; wl_list_insert(&output->layers[layer->layer], &layer->link); + + enum kiwmi_stratum new_stratum = + stratum_from_layer_shell_layer(layer->layer); + + wlr_scene_node_reparent( + &layer->desktop_surface.tree->node, + &output->strata[new_stratum]->node); } - if (buffer_changed || layer_changed || geom_changed) { + if (layer->layer_surface->current.committed != 0) { output_damage(layer->output); + arrange_layers(output); } } @@ -69,6 +71,10 @@ kiwmi_layer_map_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_layer *layer = wl_container_of(listener, layer, map); + wlr_scene_node_set_enabled(&layer->desktop_surface.tree->node, true); + wlr_scene_node_set_enabled(&layer->desktop_surface.popups_tree->node, true); + + arrange_layers(layer->output); output_damage(layer->output); } @@ -77,6 +83,11 @@ kiwmi_layer_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_layer *layer = wl_container_of(listener, layer, unmap); + wlr_scene_node_set_enabled(&layer->desktop_surface.tree->node, false); + wlr_scene_node_set_enabled( + &layer->desktop_surface.popups_tree->node, false); + + arrange_layers(layer->output); output_damage(layer->output); } @@ -245,6 +256,13 @@ arrange_layer( layer->geom = arranged_area; + wlr_scene_node_set_position( + &layer->desktop_surface.tree->node, layer->geom.x, layer->geom.y); + wlr_scene_node_set_position( + &layer->desktop_surface.popups_tree->node, + layer->geom.x, + layer->geom.y); + apply_exclusive( usable_area, state->anchor, @@ -415,6 +433,8 @@ layer_shell_new_surface_notify(struct wl_listener *listener, void *data) layer->output = output; layer->layer = layer_surface->current.layer; + layer->desktop_surface.type = KIWMI_DESKTOP_SURFACE_LAYER; + layer->destroy.notify = kiwmi_layer_destroy_notify; wl_signal_add(&layer_surface->events.destroy, &layer->destroy); @@ -427,10 +447,25 @@ layer_shell_new_surface_notify(struct wl_listener *listener, void *data) layer->unmap.notify = kiwmi_layer_unmap_notify; wl_signal_add(&layer_surface->events.unmap, &layer->unmap); + layer_surface->data = layer; + + enum kiwmi_stratum stratum = stratum_from_layer_shell_layer(layer->layer); + + layer->desktop_surface.tree = + wlr_scene_tree_create(&output->strata[stratum]->node); + layer->desktop_surface.popups_tree = + wlr_scene_tree_create(&output->strata[KIWMI_STRATUM_POPUPS]->node); + layer->desktop_surface.surface_node = wlr_scene_subsurface_tree_create( + &layer->desktop_surface.tree->node, layer->layer_surface->surface); + + wlr_scene_node_set_enabled(&layer->desktop_surface.tree->node, false); + wlr_scene_node_set_enabled( + &layer->desktop_surface.popups_tree->node, false); + wl_list_insert(&output->layers[layer->layer], &layer->link); // Temporarily set the layer's current state to pending - // So that we can easily arrange it + // so that we can easily arrange it struct wlr_layer_surface_v1_state old_state = layer_surface->current; layer_surface->current = layer_surface->pending; arrange_layers(output); diff --git a/kiwmi/desktop/output.c b/kiwmi/desktop/output.c index 98bf57b..0ec3468 100644 --- a/kiwmi/desktop/output.c +++ b/kiwmi/desktop/output.c @@ -276,6 +276,12 @@ output_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) } } + if (output->desktop->scene) { + for (size_t i = 0; i < KIWMI_STRATA_COUNT; ++i) { + wlr_scene_node_destroy(&output->strata[i]->node); + } + } + if (output->desktop->output_layout) { wlr_output_layout_remove( output->desktop->output_layout, output->wlr_output); @@ -382,15 +388,23 @@ new_output_notify(struct wl_listener *listener, void *data) 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) { + size_t len_layers = sizeof(output->layers) / sizeof(output->layers[0]); + for (size_t i = 0; i < len_layers; ++i) { wl_list_init(&output->layers[i]); } + for (size_t i = 0; i < KIWMI_STRATA_COUNT; ++i) { + output->strata[i] = wlr_scene_tree_create(&desktop->strata[i]->node); + } + wl_signal_init(&output->events.destroy); wl_signal_init(&output->events.resize); wl_signal_init(&output->events.usable_area_change); + wl_list_insert(&desktop->outputs, &output->link); + + wlr_output_layout_add_auto(desktop->output_layout, wlr_output); + wl_signal_emit(&desktop->events.new_output, output); } @@ -401,3 +415,32 @@ output_damage(struct kiwmi_output *output) output->damaged = 2; } } + +void +output_layout_change_notify(struct wl_listener *listener, void *UNUSED(data)) +{ + struct kiwmi_desktop *desktop = + wl_container_of(listener, desktop, output_layout_change); + + struct wlr_box *ol_box = + wlr_output_layout_get_box(desktop->output_layout, NULL); + wlr_scene_node_set_position( + &desktop->background_rect->node, ol_box->x, ol_box->y); + wlr_scene_rect_set_size( + desktop->background_rect, ol_box->width, ol_box->height); + + struct wlr_output_layout_output *ol_output; + wl_list_for_each (ol_output, &desktop->output_layout->outputs, link) { + struct kiwmi_output *output = ol_output->output->data; + + struct wlr_box *box = wlr_output_layout_get_box( + desktop->output_layout, output->wlr_output); + + for (size_t i = 0; i < KIWMI_STRATA_COUNT; ++i) { + if (output->strata[i]) { + wlr_scene_node_set_position( + &output->strata[i]->node, box->x, box->y); + } + } + } +} diff --git a/kiwmi/desktop/popup.c b/kiwmi/desktop/popup.c new file mode 100644 index 0000000..5afc2bf --- /dev/null +++ b/kiwmi/desktop/popup.c @@ -0,0 +1,71 @@ +/* Copyright (c), Niclas Meyer + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "desktop/popup.h" + +#include +#include +#include +#include + +#include "desktop/desktop_surface.h" +#include "desktop/layer_shell.h" +#include "desktop/view.h" + +struct kiwmi_desktop_surface * +popup_get_desktop_surface(struct wlr_xdg_popup *popup) +{ + struct wlr_surface *parent = popup->parent; + while (parent) { + if (wlr_surface_is_xdg_surface(parent)) { + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(parent); + switch (xdg_surface->role) { + case WLR_XDG_SURFACE_ROLE_POPUP: + parent = xdg_surface->popup->parent; + break; + case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + struct kiwmi_view *view = xdg_surface->data; + return &view->desktop_surface; + default: + return NULL; + } + } else if (wlr_surface_is_layer_surface(parent)) { + struct wlr_layer_surface_v1 *layer_surface = + wlr_layer_surface_v1_from_wlr_surface(parent); + struct kiwmi_layer *layer = layer_surface->data; + return &layer->desktop_surface; + } else { + return NULL; + } + } + return NULL; +} + +void +popup_attach( + struct wlr_xdg_popup *popup, + struct kiwmi_desktop_surface *desktop_surface) +{ + struct wlr_scene_tree *parent_tree = desktop_surface->popups_tree; + if (wlr_surface_is_xdg_surface(popup->parent)) { + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(popup->parent); + if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP + && xdg_surface->data) { + parent_tree = xdg_surface->data; + } + } + + struct wlr_scene_node *node = + wlr_scene_xdg_surface_create(&parent_tree->node, popup->base); + if (!node) { + wlr_log(WLR_ERROR, "failed to attach popup to scene"); + return; + } + popup->base->data = node; +} diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index c741d8d..96066c6 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -11,6 +11,7 @@ #include #include "desktop/output.h" +#include "desktop/stratum.h" #include "input/cursor.h" #include "input/seat.h" #include "server.h" @@ -105,6 +106,9 @@ view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y) view->x = x; view->y = y; + wlr_scene_node_set_position(&view->desktop_surface.tree->node, x, y); + wlr_scene_node_set_position(&view->desktop_surface.popups_tree->node, x, y); + struct kiwmi_view_child *child; wl_list_for_each (child, &view->children, link) { if (child->impl && child->impl->reconfigure) { @@ -131,6 +135,20 @@ view_set_tiled(struct kiwmi_view *view, enum wlr_edges edges) } } +void +view_set_hidden(struct kiwmi_view *view, bool hidden) +{ + view->hidden = hidden; + + if (!view->mapped) { + return; + } + + wlr_scene_node_set_enabled(&view->desktop_surface.tree->node, !hidden); + wlr_scene_node_set_enabled( + &view->desktop_surface.popups_tree->node, !hidden); +} + struct wlr_surface * view_surface_at( struct kiwmi_view *view, @@ -296,12 +314,26 @@ view_create( wl_list_init(&view->children); + view->desktop_surface.type = KIWMI_DESKTOP_SURFACE_VIEW; + wl_signal_init(&view->events.unmap); wl_signal_init(&view->events.request_move); wl_signal_init(&view->events.request_resize); wl_signal_init(&view->events.post_render); wl_signal_init(&view->events.pre_render); + view->desktop_surface.tree = wlr_scene_tree_create( + &view->desktop->strata[KIWMI_STRATUM_NORMAL]->node); + view->desktop_surface.popups_tree = wlr_scene_tree_create( + &view->desktop->strata[KIWMI_STRATUM_POPUPS]->node); + + view_set_hidden(view, true); + wlr_scene_node_lower_to_bottom(&view->desktop_surface.tree->node); + wlr_scene_node_lower_to_bottom(&view->desktop_surface.popups_tree->node); + + wlr_scene_node_set_position(&view->desktop_surface.tree->node, 0, 0); + wlr_scene_node_set_position(&view->desktop_surface.popups_tree->node, 0, 0); + return view; } diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index 337fd5d..fddecfd 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include "desktop/desktop.h" #include "desktop/output.h" +#include "desktop/popup.h" #include "desktop/view.h" #include "input/cursor.h" #include "input/input.h" @@ -191,6 +193,14 @@ xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) if (view->mapped) { view->mapped = false; + wlr_scene_node_set_enabled(&view->desktop_surface.tree->node, false); + wlr_scene_node_set_enabled( + &view->desktop_surface.popups_tree->node, false); + + struct kiwmi_desktop *desktop = view->desktop; + struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); + struct kiwmi_output *output; wl_list_for_each (output, &view->desktop->outputs, link) { output_damage(output); @@ -223,7 +233,11 @@ xdg_surface_commit_notify(struct wl_listener *listener, void *UNUSED(data)) static void xdg_surface_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) { - struct kiwmi_view *view = wl_container_of(listener, view, destroy); + struct kiwmi_view *view = wl_container_of(listener, view, destroy); + + wlr_scene_node_destroy(&view->desktop_surface.tree->node); + wlr_scene_node_destroy(&view->desktop_surface.popups_tree->node); + struct kiwmi_desktop *desktop = view->desktop; struct kiwmi_server *server = wl_container_of(desktop, server, desktop); struct kiwmi_seat *seat = server->input.seat; @@ -380,6 +394,15 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data) if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { wlr_log(WLR_DEBUG, "New xdg_shell popup"); + struct kiwmi_desktop_surface *desktop_surface = + popup_get_desktop_surface(xdg_surface->popup); + if (desktop_surface) { + popup_attach(xdg_surface->popup, desktop_surface); + + struct kiwmi_server *server = + wl_container_of(desktop, server, desktop); + cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); + } return; } @@ -402,6 +425,9 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data) view->xdg_surface = xdg_surface; view->wlr_surface = xdg_surface->surface; + view->desktop_surface.surface_node = wlr_scene_xdg_surface_create( + &view->desktop_surface.tree->node, xdg_surface); + view->map.notify = xdg_surface_map_notify; wl_signal_add(&xdg_surface->events.map, &view->map); @@ -431,6 +457,8 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data) view_init_subsurfaces(NULL, view); + wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom); + wl_list_insert(&desktop->views, &view->link); } diff --git a/kiwmi/input/seat.c b/kiwmi/input/seat.c index a1ac68b..4fe8927 100644 --- a/kiwmi/input/seat.c +++ b/kiwmi/input/seat.c @@ -83,6 +83,10 @@ seat_focus_view(struct kiwmi_seat *seat, struct kiwmi_view *view) // move view to front wl_list_remove(&view->link); wl_list_insert(&desktop->views, &view->link); + + wlr_scene_node_raise_to_top(&view->desktop_surface.tree->node); + wlr_scene_node_raise_to_top(&view->desktop_surface.popups_tree->node); + cursor_refresh_focus(seat->input->cursor, NULL, NULL, NULL); seat->focused_view = view; diff --git a/kiwmi/luak/kiwmi_server.c b/kiwmi/luak/kiwmi_server.c index 4e41d94..f8f61a3 100644 --- a/kiwmi/luak/kiwmi_server.c +++ b/kiwmi/luak/kiwmi_server.c @@ -69,6 +69,11 @@ l_kiwmi_server_bg_color(lua_State *L) server->desktop.bg_color[1] = color[1]; server->desktop.bg_color[2] = color[2]; // ignore alpha + color[3] = 1.0f; + + wlr_scene_rect_set_color(server->desktop.background_rect, color); + bool black = color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f; + wlr_scene_node_set_enabled(&server->desktop.background_rect->node, !black); return 0; } diff --git a/kiwmi/luak/kiwmi_view.c b/kiwmi/luak/kiwmi_view.c index 3e691dc..f5222ad 100644 --- a/kiwmi/luak/kiwmi_view.c +++ b/kiwmi/luak/kiwmi_view.c @@ -137,7 +137,7 @@ l_kiwmi_view_hide(lua_State *L) struct kiwmi_view *view = obj->object; - view->hidden = true; + view_set_hidden(view, true); return 0; } @@ -315,7 +315,7 @@ l_kiwmi_view_show(lua_State *L) struct kiwmi_view *view = obj->object; - view->hidden = false; + view_set_hidden(view, false); return 0; } diff --git a/kiwmi/meson.build b/kiwmi/meson.build index eb3a962..ceb2471 100644 --- a/kiwmi/meson.build +++ b/kiwmi/meson.build @@ -5,6 +5,7 @@ kiwmi_sources = files( 'desktop/desktop.c', 'desktop/layer_shell.c', 'desktop/output.c', + 'desktop/popup.c', 'desktop/stratum.c', 'desktop/view.c', 'desktop/xdg_shell.c', From 670b63b64ae1a75da3b3d20ef9b319d37789d2d6 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Sun, 8 May 2022 08:25:15 +0000 Subject: [PATCH 05/10] Render using wlr_scene Apart from removing a lot of code, this commit also introduces (thanks to wlr_scene) fine-grained damage tracking. The lack of our own rendering code will only be an issue if the need for custom effects (such as blur) arises; however, that's very unlikely and it would probably require a lot of changes anyway. --- include/desktop/output.h | 4 - kiwmi/desktop/layer_shell.c | 3 - kiwmi/desktop/output.c | 225 ++---------------------------------- kiwmi/desktop/view.c | 43 +------ kiwmi/desktop/xdg_shell.c | 21 ---- kiwmi/input/seat.c | 8 -- 6 files changed, 13 insertions(+), 291 deletions(-) diff --git a/include/desktop/output.h b/include/desktop/output.h index b3e11a1..bf96fc6 100644 --- a/include/desktop/output.h +++ b/include/desktop/output.h @@ -28,8 +28,6 @@ struct kiwmi_output { struct wlr_box usable_area; - int damaged; - struct { struct wl_signal destroy; struct wl_signal resize; @@ -49,6 +47,4 @@ struct kiwmi_render_data { void new_output_notify(struct wl_listener *listener, void *data); void output_layout_change_notify(struct wl_listener *listener, void *data); -void output_damage(struct kiwmi_output *output); - #endif /* KIWMI_DESKTOP_OUTPUT_H */ diff --git a/kiwmi/desktop/layer_shell.c b/kiwmi/desktop/layer_shell.c index 842f7c4..f504306 100644 --- a/kiwmi/desktop/layer_shell.c +++ b/kiwmi/desktop/layer_shell.c @@ -61,7 +61,6 @@ kiwmi_layer_commit_notify(struct wl_listener *listener, void *UNUSED(data)) } if (layer->layer_surface->current.committed != 0) { - output_damage(layer->output); arrange_layers(output); } } @@ -75,7 +74,6 @@ kiwmi_layer_map_notify(struct wl_listener *listener, void *UNUSED(data)) wlr_scene_node_set_enabled(&layer->desktop_surface.popups_tree->node, true); arrange_layers(layer->output); - output_damage(layer->output); } static void @@ -88,7 +86,6 @@ kiwmi_layer_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) &layer->desktop_surface.popups_tree->node, false); arrange_layers(layer->output); - output_damage(layer->output); } static void diff --git a/kiwmi/desktop/output.c b/kiwmi/desktop/output.c index 0ec3468..3c38788 100644 --- a/kiwmi/desktop/output.c +++ b/kiwmi/desktop/output.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,216 +31,24 @@ #include "input/pointer.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 *wlr_output = rdata->output; - struct wlr_box *geom = rdata->data; - - struct wlr_texture *texture = wlr_surface_get_texture(surface); - if (!texture) { - return; - } - - int ox = x + geom->x; - int oy = y + geom->y; - - struct wlr_box box = { - .x = ox * wlr_output->scale, - .y = oy * wlr_output->scale, - .width = surface->current.width * wlr_output->scale, - .height = surface->current.height * wlr_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, wlr_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 -send_frame_done_to_layer_surface( - struct wlr_surface *surface, - int UNUSED(x), - int UNUSED(y), - void *data) -{ - struct timespec *now = data; - wlr_surface_send_frame_done(surface, now); -} - -static void -send_frame_done_to_layer(struct wl_list *layer, struct timespec *now) -{ - struct kiwmi_layer *surface; - wl_list_for_each (surface, layer, link) { - wlr_layer_surface_v1_for_each_surface( - surface->layer_surface, send_frame_done_to_layer_surface, now); - } -} - -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 *wlr_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 * wlr_output->scale, - .y = oy * wlr_output->scale, - .width = surface->current.width * wlr_output->scale, - .height = surface->current.height * wlr_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, wlr_output->transform_matrix); - - wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1); - - wlr_surface_send_frame_done(surface, rdata->when); -} - -static void -send_frame_done_to_surface( - struct wlr_surface *surface, - int UNUSED(sx), - int UNUSED(sy), - void *data) -{ - struct timespec *now = data; - wlr_surface_send_frame_done(surface, now); -} - -static bool -render_cursors(struct wlr_output *wlr_output) -{ - pixman_region32_t damage; - pixman_region32_init(&damage); - wlr_output_render_software_cursors(wlr_output, &damage); - bool damaged = pixman_region32_not_empty(&damage); - pixman_region32_fini(&damage); - - return damaged; -} - 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_scene_output *scene_output = + wlr_scene_get_scene_output(output->desktop->scene, wlr_output); + + if (!scene_output) { + return; + } + + wlr_scene_output_commit(scene_output); struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - - int buffer_age; - if (!wlr_output_attach_render(wlr_output, &buffer_age)) { - wlr_log(WLR_ERROR, "Failed to attach renderer to output"); - return; - } - - if (output->damaged == 0 && buffer_age > 0) { - send_frame_done_to_layer( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now); - send_frame_done_to_layer( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now); - send_frame_done_to_layer( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now); - send_frame_done_to_layer( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now); - - struct kiwmi_view *view; - wl_list_for_each (view, &desktop->views, link) { - view_for_each_surface(view, send_frame_done_to_surface, &now); - } - - if (render_cursors(wlr_output)) { - output_damage(output); - } - - wlr_output_commit(wlr_output); - return; - } - - struct wlr_output_layout *output_layout = desktop->output_layout; - struct kiwmi_server *server = wl_container_of(desktop, server, desktop); - struct wlr_renderer *renderer = server->renderer; - - wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); - wlr_renderer_clear(renderer, desktop->bg_color); - - double output_lx = 0; - double output_ly = 0; - 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); - - bool damaged = render_cursors(wlr_output); - wlr_renderer_end(renderer); - - if (damaged) { - output_damage(output); - } else { - --output->damaged; - } - - wlr_output_commit(wlr_output); + wlr_scene_output_send_frame_done(scene_output, &now); } static void @@ -250,7 +59,6 @@ output_commit_notify(struct wl_listener *listener, void *data) if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) { arrange_layers(output); - output_damage(output); wl_signal_emit(&output->events.resize, output); } @@ -304,7 +112,6 @@ output_mode_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_output *output = wl_container_of(listener, output, mode); arrange_layers(output); - output_damage(output); wl_signal_emit(&output->events.resize, output); } @@ -335,8 +142,6 @@ output_create(struct wlr_output *wlr_output, struct kiwmi_desktop *desktop) output->mode.notify = output_mode_notify; wl_signal_add(&wlr_output->events.mode, &output->mode); - output_damage(output); - return output; } @@ -408,14 +213,6 @@ new_output_notify(struct wl_listener *listener, void *data) wl_signal_emit(&desktop->events.new_output, output); } -void -output_damage(struct kiwmi_output *output) -{ - if (output != NULL) { - output->damaged = 2; - } -} - void output_layout_change_notify(struct wl_listener *listener, void *UNUSED(data)) { diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index 96066c6..0f54f26 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -92,11 +92,6 @@ view_set_size(struct kiwmi_view *view, uint32_t width, uint32_t height) child->impl->reconfigure(child); } } - - struct kiwmi_output *output; - wl_list_for_each (output, &view->desktop->outputs, link) { - output_damage(output); - } } } @@ -120,11 +115,6 @@ view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y) struct kiwmi_server *server = wl_container_of(desktop, server, desktop); struct kiwmi_cursor *cursor = server->input.cursor; cursor_refresh_focus(cursor, NULL, NULL, NULL); - - struct kiwmi_output *output; - wl_list_for_each (output, &desktop->outputs, link) { - output_damage(output); - } } void @@ -355,24 +345,9 @@ view_child_is_mapped(struct kiwmi_view_child *child) return child->view->mapped; } -void -view_child_damage(struct kiwmi_view_child *child) -{ - // Note for later: this is supposed to damage the child and all subchildren - struct kiwmi_output *output; - wl_list_for_each (output, &child->view->desktop->outputs, link) { - output_damage(output); - } -} - void view_child_destroy(struct kiwmi_view_child *child) { - bool visible = view_child_is_mapped(child) && !child->view->hidden; - if (visible) { - view_child_damage(child); - } - wl_list_remove(&child->link); child->parent = NULL; @@ -414,12 +389,8 @@ view_child_surface_destroy_notify( } static void -view_child_commit_notify(struct wl_listener *listener, void *UNUSED(data)) +view_child_commit_notify() { - struct kiwmi_view_child *child = wl_container_of(listener, child, commit); - if (view_child_is_mapped(child)) { - view_child_damage(child); - } } static void @@ -436,19 +407,13 @@ view_child_map_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_view_child *child = wl_container_of(listener, child, map); child->mapped = true; - if (view_child_is_mapped(child)) { - view_child_damage(child); - } } static void view_child_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_view_child *child = wl_container_of(listener, child, unmap); - if (view_child_is_mapped(child)) { - view_child_damage(child); - } - child->mapped = false; + child->mapped = false; } struct kiwmi_view_child * @@ -520,10 +485,6 @@ view_child_subsurface_create( child->wlr_subsurface = subsurface; child->mapped = subsurface->mapped; - if (view_child_is_mapped(child)) { - view_child_damage(child); - } - wl_signal_add(&subsurface->events.map, &child->map); wl_signal_add(&subsurface->events.unmap, &child->unmap); diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index fddecfd..16808e6 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -137,10 +137,6 @@ view_child_popup_create( child->wlr_xdg_popup = wlr_popup; child->mapped = wlr_popup->base->mapped; - if (view_child_is_mapped(child)) { - view_child_damage(child); - } - wl_signal_add(&wlr_popup->base->events.map, &child->map); wl_signal_add(&wlr_popup->base->events.unmap, &child->unmap); @@ -177,11 +173,6 @@ xdg_surface_map_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_view *view = wl_container_of(listener, view, map); view->mapped = true; - struct kiwmi_output *output; - wl_list_for_each (output, &view->desktop->outputs, link) { - output_damage(output); - } - wl_signal_emit(&view->desktop->events.view_map, view); } @@ -201,11 +192,6 @@ xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_server *server = wl_container_of(desktop, server, desktop); cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); - struct kiwmi_output *output; - wl_list_for_each (output, &view->desktop->outputs, link) { - output_damage(output); - } - wl_signal_emit(&view->events.unmap, view); } } @@ -220,13 +206,6 @@ xdg_surface_commit_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_cursor *cursor = server->input.cursor; cursor_refresh_focus(cursor, NULL, NULL, NULL); - if (pixman_region32_not_empty(&view->wlr_surface->buffer_damage)) { - struct kiwmi_output *output; - wl_list_for_each (output, &desktop->outputs, link) { - output_damage(output); - } - } - wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom); } diff --git a/kiwmi/input/seat.c b/kiwmi/input/seat.c index 4fe8927..c10a44f 100644 --- a/kiwmi/input/seat.c +++ b/kiwmi/input/seat.c @@ -116,14 +116,6 @@ request_set_cursor_notify(struct wl_listener *listener, void *data) return; } - struct kiwmi_input *input = seat->input; - struct kiwmi_server *server = wl_container_of(input, server, input); - - struct kiwmi_output *output; - wl_list_for_each (output, &server->desktop.outputs, link) { - output_damage(output); - } - wlr_cursor_set_surface( cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y); } From b82e6121c6edd8c32ac569829ec134096cd94203 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Sun, 8 May 2022 09:42:33 +0000 Subject: [PATCH 06/10] Prefer wlr_scene as the source of truth Use it for getting the surface under cursor, position of surfaces, etc. --- include/desktop/desktop_surface.h | 18 +++++ include/desktop/view.h | 14 +--- kiwmi/desktop/desktop.c | 21 +++-- kiwmi/desktop/desktop_surface.c | 87 ++++++++++++++++++++ kiwmi/desktop/layer_shell.c | 13 +++ kiwmi/desktop/view.c | 127 +++++++++++++----------------- kiwmi/desktop/xdg_shell.c | 13 +-- kiwmi/input/cursor.c | 69 +++------------- kiwmi/luak/kiwmi_cursor.c | 13 +-- kiwmi/luak/kiwmi_server.c | 7 +- kiwmi/luak/kiwmi_view.c | 14 +++- kiwmi/meson.build | 1 + 12 files changed, 216 insertions(+), 181 deletions(-) create mode 100644 kiwmi/desktop/desktop_surface.c diff --git a/include/desktop/desktop_surface.h b/include/desktop/desktop_surface.h index 4efe0cd..d0de3ab 100644 --- a/include/desktop/desktop_surface.h +++ b/include/desktop/desktop_surface.h @@ -8,6 +8,9 @@ #ifndef KIWMI_DESKTOP_DESKTOP_SURFACE_H #define KIWMI_DESKTOP_DESKTOP_SURFACE_H +struct wlr_surface; +struct kiwmi_desktop; + enum kiwmi_desktop_surface_type { KIWMI_DESKTOP_SURFACE_VIEW, KIWMI_DESKTOP_SURFACE_LAYER, @@ -22,6 +25,21 @@ struct kiwmi_desktop_surface { struct wlr_scene_tree *popups_tree; enum kiwmi_desktop_surface_type type; + const struct kiwmi_desktop_surface_impl *impl; }; +struct kiwmi_desktop_surface_impl { + struct kiwmi_output *(*get_output)( + struct kiwmi_desktop_surface *desktop_surface); +}; + +struct kiwmi_desktop_surface * +desktop_surface_at(struct kiwmi_desktop *desktop, double lx, double ly); +struct kiwmi_output * +desktop_surface_get_output(struct kiwmi_desktop_surface *desktop_surface); +void desktop_surface_get_pos( + struct kiwmi_desktop_surface *desktop_surface, + int *lx, + int *ly); + #endif /* KIWMI_DESKTOP_DESKTOP_SURFACE_H */ diff --git a/include/desktop/view.h b/include/desktop/view.h index 3a42617..72c9163 100644 --- a/include/desktop/view.h +++ b/include/desktop/view.h @@ -147,21 +147,9 @@ void view_set_size(struct kiwmi_view *view, uint32_t width, uint32_t height); void view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y); void view_set_tiled(struct kiwmi_view *view, enum wlr_edges edges); void view_set_hidden(struct kiwmi_view *view, bool hidden); -struct wlr_surface *view_surface_at( - struct kiwmi_view *view, - double sx, - double sy, - double *sub_x, - double *sub_y); void view_focus(struct kiwmi_view *view); -struct kiwmi_view *view_at( - struct kiwmi_desktop *desktop, - double lx, - double ly, - struct wlr_surface **surface, - double *sx, - double *sy); +struct kiwmi_view *view_at(struct kiwmi_desktop *desktop, double lx, double ly); void view_move(struct kiwmi_view *view); void view_resize(struct kiwmi_view *view, uint32_t edges); struct kiwmi_view *view_create( diff --git a/kiwmi/desktop/desktop.c b/kiwmi/desktop/desktop.c index 9bbeb48..7e3531a 100644 --- a/kiwmi/desktop/desktop.c +++ b/kiwmi/desktop/desktop.c @@ -22,6 +22,7 @@ #include #include +#include "desktop/desktop_surface.h" #include "desktop/layer_shell.h" #include "desktop/output.h" #include "desktop/stratum.h" @@ -29,6 +30,7 @@ #include "desktop/xdg_shell.h" #include "input/cursor.h" #include "input/input.h" +#include "input/seat.h" #include "server.h" bool @@ -127,19 +129,14 @@ desktop_active_output(struct kiwmi_server *server) return output; } - // 2. focused view center - if (!wl_list_empty(&server->desktop.views)) { - struct kiwmi_view *view; - wl_list_for_each (view, &server->desktop.views, link) { - break; // get first element of list + // 2. focused view + struct kiwmi_view *focused_view = server->input.seat->focused_view; + if (focused_view) { + output = desktop_surface_get_output(&focused_view->desktop_surface); + + if (output) { + return output; } - - double lx = view->x + view->geom.width / 2; - double ly = view->y + view->geom.height / 2; - - struct wlr_output *wlr_output = - wlr_output_layout_output_at(server->desktop.output_layout, lx, ly); - return wlr_output->data; } // 3. cursor diff --git a/kiwmi/desktop/desktop_surface.c b/kiwmi/desktop/desktop_surface.c new file mode 100644 index 0000000..452205e --- /dev/null +++ b/kiwmi/desktop/desktop_surface.c @@ -0,0 +1,87 @@ +/* Copyright (c), Niclas Meyer + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "desktop/desktop_surface.h" + +#include +#include +#include +#include + +#include "desktop/desktop.h" +#include "desktop/layer_shell.h" +#include "desktop/output.h" +#include "desktop/popup.h" +#include "desktop/view.h" + +static struct kiwmi_desktop_surface * +desktop_surface_from_wlr_surface(struct wlr_surface *surface) +{ + struct wlr_subsurface *subsurface; + while (wlr_surface_is_subsurface(surface)) { + subsurface = wlr_subsurface_from_wlr_surface(surface); + surface = subsurface->parent; + } + + if (wlr_surface_is_xdg_surface(surface)) { + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(surface); + switch (xdg_surface->role) { + case WLR_XDG_SURFACE_ROLE_TOPLEVEL:; + struct kiwmi_view *view = xdg_surface->data; + return &view->desktop_surface; + break; + case WLR_XDG_SURFACE_ROLE_POPUP: + return popup_get_desktop_surface(xdg_surface->popup); + break; + default: + return NULL; + break; + } + } else if (wlr_surface_is_layer_surface(surface)) { + struct wlr_layer_surface_v1 *layer_surface = + wlr_layer_surface_v1_from_wlr_surface(surface); + struct kiwmi_layer *layer = layer_surface->data; + return &layer->desktop_surface; + } + + return NULL; +} + +struct kiwmi_desktop_surface * +desktop_surface_at(struct kiwmi_desktop *desktop, double lx, double ly) +{ + double sx, sy; // unused + struct wlr_scene_node *node_at = + wlr_scene_node_at(&desktop->scene->node, lx, ly, &sx, &sy); + + if (!node_at || node_at->type != WLR_SCENE_NODE_SURFACE) { + return NULL; + } + + struct wlr_surface *surface = wlr_scene_surface_from_node(node_at)->surface; + return desktop_surface_from_wlr_surface(surface); +} + +struct kiwmi_output * +desktop_surface_get_output(struct kiwmi_desktop_surface *desktop_surface) +{ + if (desktop_surface->impl && desktop_surface->impl->get_output) { + return desktop_surface->impl->get_output(desktop_surface); + } else { + return NULL; + } +} + +void +desktop_surface_get_pos( + struct kiwmi_desktop_surface *desktop_surface, + int *lx, + int *ly) +{ + wlr_scene_node_coords(&desktop_surface->tree->node, lx, ly); +} diff --git a/kiwmi/desktop/layer_shell.c b/kiwmi/desktop/layer_shell.c index f504306..3853c28 100644 --- a/kiwmi/desktop/layer_shell.c +++ b/kiwmi/desktop/layer_shell.c @@ -390,6 +390,18 @@ layer_at( return NULL; } +static struct kiwmi_output * +layer_desktop_surface_get_output(struct kiwmi_desktop_surface *desktop_surface) +{ + struct kiwmi_layer *layer = + wl_container_of(desktop_surface, layer, desktop_surface); + return layer->output; +} + +static const struct kiwmi_desktop_surface_impl layer_desktop_surface_impl = { + .get_output = layer_desktop_surface_get_output, +}; + void layer_shell_new_surface_notify(struct wl_listener *listener, void *data) { @@ -431,6 +443,7 @@ layer_shell_new_surface_notify(struct wl_listener *listener, void *data) layer->layer = layer_surface->current.layer; layer->desktop_surface.type = KIWMI_DESKTOP_SURFACE_LAYER; + layer->desktop_surface.impl = &layer_desktop_surface_impl; layer->destroy.notify = kiwmi_layer_destroy_notify; wl_signal_add(&layer_surface->events.destroy, &layer->destroy); diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index 0f54f26..4bba2ad 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -8,6 +8,7 @@ #include "desktop/view.h" #include +#include #include #include "desktop/output.h" @@ -104,17 +105,13 @@ view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y) wlr_scene_node_set_position(&view->desktop_surface.tree->node, x, y); wlr_scene_node_set_position(&view->desktop_surface.popups_tree->node, x, y); - struct kiwmi_view_child *child; - wl_list_for_each (child, &view->children, link) { - if (child->impl && child->impl->reconfigure) { - child->impl->reconfigure(child); - } + int lx, ly; // unused + // If it is enabled (as well as all its parents) + if (wlr_scene_node_coords(&view->desktop_surface.tree->node, &lx, &ly)) { + struct kiwmi_server *server = + wl_container_of(view->desktop, server, desktop); + cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); } - - struct kiwmi_desktop *desktop = view->desktop; - struct kiwmi_server *server = wl_container_of(desktop, server, desktop); - struct kiwmi_cursor *cursor = server->input.cursor; - cursor_refresh_focus(cursor, NULL, NULL, NULL); } void @@ -139,69 +136,20 @@ view_set_hidden(struct kiwmi_view *view, bool hidden) &view->desktop_surface.popups_tree->node, !hidden); } -struct wlr_surface * -view_surface_at( - struct kiwmi_view *view, - double sx, - double sy, - double *sub_x, - double *sub_y) -{ - if (view->impl->surface_at) { - return view->impl->surface_at(view, sx, sy, sub_x, sub_y); - } - - return NULL; -} - -static bool -surface_at( - struct kiwmi_view *view, - struct wlr_surface **surface, - double lx, - double ly, - double *sx, - double *sy) -{ - double view_sx = lx - view->x + view->geom.x; - double view_sy = ly - view->y + view->geom.y; - - double _sx; - double _sy; - struct wlr_surface *_surface = - view_surface_at(view, view_sx, view_sy, &_sx, &_sy); - - if (_surface) { - *sx = _sx; - *sy = _sy; - *surface = _surface; - return true; - } - - return false; -} - struct kiwmi_view * -view_at( - struct kiwmi_desktop *desktop, - double lx, - double ly, - struct wlr_surface **surface, - double *sx, - double *sy) +view_at(struct kiwmi_desktop *desktop, double lx, double ly) { - struct kiwmi_view *view; - wl_list_for_each (view, &desktop->views, link) { - if (view->hidden || !view->mapped) { - continue; - } + struct kiwmi_desktop_surface *desktop_surface = + desktop_surface_at(desktop, lx, ly); - if (surface_at(view, surface, lx, ly, sx, sy)) { - return view; - } + if (!desktop_surface + || desktop_surface->type != KIWMI_DESKTOP_SURFACE_VIEW) { + return NULL; } - return NULL; + struct kiwmi_view *view = + wl_container_of(desktop_surface, view, desktop_surface); + return view; } static void @@ -228,17 +176,20 @@ view_begin_interactive( cursor->cursor_mode = mode; cursor->grabbed.view = view; + int view_lx, view_ly; + desktop_surface_get_pos(&view->desktop_surface, &view_lx, &view_ly); + if (mode == KIWMI_CURSOR_MOVE) { - cursor->grabbed.orig_x = cursor->cursor->x - view->x; - cursor->grabbed.orig_y = cursor->cursor->y - view->y; + cursor->grabbed.orig_x = cursor->cursor->x - view_lx; + cursor->grabbed.orig_y = cursor->cursor->y - view_ly; } else { cursor->grabbed.orig_x = cursor->cursor->x; cursor->grabbed.orig_y = cursor->cursor->y; cursor->grabbed.resize_edges = edges; } - cursor->grabbed.orig_geom.x = view->x; - cursor->grabbed.orig_geom.y = view->y; + cursor->grabbed.orig_geom.x = view_lx; + cursor->grabbed.orig_geom.y = view_ly; cursor->grabbed.orig_geom.width = width; cursor->grabbed.orig_geom.height = height; } @@ -280,6 +231,37 @@ view_init_subsurfaces(struct kiwmi_view_child *child, struct kiwmi_view *view) } } +static struct kiwmi_output * +view_desktop_surface_get_output(struct kiwmi_desktop_surface *desktop_surface) +{ + struct kiwmi_view *view = + wl_container_of(desktop_surface, view, desktop_surface); + + int lx, ly; + desktop_surface_get_pos(&view->desktop_surface, &lx, &ly); + + // Prefer view center + struct wlr_output *output = wlr_output_layout_output_at( + view->desktop->output_layout, + lx + view->geom.width / 2, + ly + view->geom.height / 2); + if (output) { + return (struct kiwmi_output *)output->data; + } + + // Retry top-left corner + output = wlr_output_layout_output_at(view->desktop->output_layout, lx, ly); + if (output) { + return (struct kiwmi_output *)output->data; + } + + return NULL; +} + +static const struct kiwmi_desktop_surface_impl view_desktop_surface_impl = { + .get_output = view_desktop_surface_get_output, +}; + struct kiwmi_view * view_create( struct kiwmi_desktop *desktop, @@ -305,6 +287,7 @@ view_create( wl_list_init(&view->children); view->desktop_surface.type = KIWMI_DESKTOP_SURFACE_VIEW; + view->desktop_surface.impl = &view_desktop_surface_impl; wl_signal_init(&view->events.unmap); wl_signal_init(&view->events.request_move); diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index 16808e6..d44a53e 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -181,19 +181,20 @@ 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; + view->mapped = false; + int lx, ly; // unused + if (wlr_scene_node_coords(&view->desktop_surface.tree->node, &lx, &ly)) { wlr_scene_node_set_enabled(&view->desktop_surface.tree->node, false); wlr_scene_node_set_enabled( &view->desktop_surface.popups_tree->node, false); - struct kiwmi_desktop *desktop = view->desktop; - struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + struct kiwmi_server *server = + wl_container_of(view->desktop, server, desktop); cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); - - wl_signal_emit(&view->events.unmap, view); } + + wl_signal_emit(&view->events.unmap, view); } static void diff --git a/kiwmi/input/cursor.c b/kiwmi/input/cursor.c index 7fce94a..beda260 100644 --- a/kiwmi/input/cursor.c +++ b/kiwmi/input/cursor.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -284,72 +285,24 @@ cursor_refresh_focus( struct kiwmi_desktop *desktop = &cursor->server->desktop; struct wlr_seat *seat = cursor->server->input.seat->seat; - double ox = cursor->cursor->x; - double oy = cursor->cursor->y; - struct wlr_output *wlr_output = wlr_output_layout_output_at( - desktop->output_layout, cursor->cursor->x, cursor->cursor->y); - - wlr_output_layout_output_coords( - desktop->output_layout, wlr_output, &ox, &oy); - - struct kiwmi_output *output = wlr_output->data; - struct wlr_surface *surface = NULL; double sx; double sy; - struct kiwmi_layer *layer = layer_at( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], - &surface, - ox, - oy, - &sx, - &sy); - struct kiwmi_view *view; + struct wlr_scene_node *node_at = wlr_scene_node_at( + &desktop->scene->node, cursor->cursor->x, cursor->cursor->y, &sx, &sy); - if (!layer) { - layer = layer_at( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], - &surface, - ox, - oy, - &sx, - &sy); - } + if (node_at && node_at->type == WLR_SCENE_NODE_SURFACE) { + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_from_node(node_at); + surface = scene_surface->surface; - if (!layer) { - view = view_at( - desktop, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); - } - - if (!layer) { - layer = layer_at( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], - &surface, - ox, - oy, - &sx, - &sy); - } - - if (!layer) { - layer = layer_at( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], - &surface, - ox, - oy, - &sx, - &sy); - } - - if (!layer && !view) { + if (surface != seat->pointer_state.focused_surface) { + wlr_seat_pointer_notify_enter(seat, surface, sx, sy); + } + } else { wlr_xcursor_manager_set_cursor_image( cursor->xcursor_manager, "left_ptr", cursor->cursor); - } - - if (surface && surface != seat->pointer_state.focused_surface) { - wlr_seat_pointer_notify_enter(seat, surface, sx, sy); - } else if (!surface) { wlr_seat_pointer_clear_focus(seat); } diff --git a/kiwmi/luak/kiwmi_cursor.c b/kiwmi/luak/kiwmi_cursor.c index 89dcf07..edd8c00 100644 --- a/kiwmi/luak/kiwmi_cursor.c +++ b/kiwmi/luak/kiwmi_cursor.c @@ -73,17 +73,8 @@ l_kiwmi_cursor_view_at_pos(lua_State *L) struct kiwmi_cursor *cursor = obj->object; struct kiwmi_server *server = cursor->server; - struct wlr_surface *surface; - double sx; - double sy; - - struct kiwmi_view *view = view_at( - &server->desktop, - cursor->cursor->x, - cursor->cursor->y, - &surface, - &sx, - &sy); + struct kiwmi_view *view = + view_at(&server->desktop, cursor->cursor->x, cursor->cursor->y); if (view) { lua_pushcfunction(L, luaK_kiwmi_view_new); diff --git a/kiwmi/luak/kiwmi_server.c b/kiwmi/luak/kiwmi_server.c index f8f61a3..ec0bccc 100644 --- a/kiwmi/luak/kiwmi_server.c +++ b/kiwmi/luak/kiwmi_server.c @@ -313,12 +313,7 @@ l_kiwmi_server_view_at(lua_State *L) double lx = lua_tonumber(L, 2); double ly = lua_tonumber(L, 3); - struct wlr_surface *surface; - double sx; - double sy; - - struct kiwmi_view *view = - view_at(&server->desktop, lx, ly, &surface, &sx, &sy); + struct kiwmi_view *view = view_at(&server->desktop, lx, ly); if (view) { lua_pushcfunction(L, luaK_kiwmi_view_new); diff --git a/kiwmi/luak/kiwmi_view.c b/kiwmi/luak/kiwmi_view.c index f5222ad..84f9f4c 100644 --- a/kiwmi/luak/kiwmi_view.c +++ b/kiwmi/luak/kiwmi_view.c @@ -15,6 +15,7 @@ #include #include +#include "desktop/desktop_surface.h" #include "desktop/output.h" #include "desktop/view.h" #include "desktop/xdg_shell.h" @@ -120,7 +121,11 @@ l_kiwmi_view_hidden(lua_State *L) struct kiwmi_view *view = obj->object; - lua_pushboolean(L, view->hidden); + int lx, ly; // unused + bool enabled = + wlr_scene_node_coords(&view->desktop_surface.tree->node, &lx, &ly); + + lua_pushboolean(L, !enabled); return 1; } @@ -275,8 +280,11 @@ l_kiwmi_view_pos(lua_State *L) struct kiwmi_view *view = obj->object; - lua_pushinteger(L, view->x); - lua_pushinteger(L, view->y); + int lx, ly; + desktop_surface_get_pos(&view->desktop_surface, &lx, &ly); + + lua_pushinteger(L, lx); + lua_pushinteger(L, ly); return 2; } diff --git a/kiwmi/meson.build b/kiwmi/meson.build index ceb2471..d05e559 100644 --- a/kiwmi/meson.build +++ b/kiwmi/meson.build @@ -3,6 +3,7 @@ kiwmi_sources = files( 'server.c', 'color.c', 'desktop/desktop.c', + 'desktop/desktop_surface.c', 'desktop/layer_shell.c', 'desktop/output.c', 'desktop/popup.c', From a8a82826c3515d0894771352b8576c4bbb22e44c Mon Sep 17 00:00:00 2001 From: tiosgz Date: Sun, 8 May 2022 09:48:44 +0000 Subject: [PATCH 07/10] Move popup unconstraining logic --- kiwmi/desktop/popup.c | 48 +++++++++++++++++++++++++++++++ kiwmi/desktop/xdg_shell.c | 59 --------------------------------------- 2 files changed, 48 insertions(+), 59 deletions(-) diff --git a/kiwmi/desktop/popup.c b/kiwmi/desktop/popup.c index 5afc2bf..9544b3c 100644 --- a/kiwmi/desktop/popup.c +++ b/kiwmi/desktop/popup.c @@ -8,12 +8,15 @@ #include "desktop/popup.h" #include +#include #include #include #include +#include "desktop/desktop.h" #include "desktop/desktop_surface.h" #include "desktop/layer_shell.h" +#include "desktop/output.h" #include "desktop/view.h" struct kiwmi_desktop_surface * @@ -46,6 +49,49 @@ popup_get_desktop_surface(struct wlr_xdg_popup *popup) return NULL; } +static void +popup_unconstrain( + struct wlr_xdg_popup *popup, + struct kiwmi_desktop_surface *desktop_surface) +{ + struct kiwmi_output *output = desktop_surface_get_output(desktop_surface); + if (!output) { + return; + } + + struct wlr_output *wlr_output = output->wlr_output; + + int lx, ly; + desktop_surface_get_pos(desktop_surface, &lx, &ly); + + if (desktop_surface->type == KIWMI_DESKTOP_SURFACE_VIEW) { + // wlroots expects surface-local, not view-local coords + struct kiwmi_view *view = + wl_container_of(desktop_surface, view, desktop_surface); + lx -= view->geom.x; + ly -= view->geom.y; + } + + double ox = lx; + double oy = ly; + wlr_output_layout_output_coords( + output->desktop->output_layout, wlr_output, &ox, &oy); + + int output_width; + int output_height; + wlr_output_effective_resolution(wlr_output, &output_width, &output_height); + + // Relative to the desktop_surface + struct wlr_box output_box = { + .x = -ox, + .y = -oy, + .width = output_width, + .height = output_height, + }; + + wlr_xdg_popup_unconstrain_from_box(popup, &output_box); +} + void popup_attach( struct wlr_xdg_popup *popup, @@ -61,6 +107,8 @@ popup_attach( } } + popup_unconstrain(popup, desktop_surface); + struct wlr_scene_node *node = wlr_scene_xdg_surface_create(&parent_tree->node, popup->base); if (!node) { diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index d44a53e..36feaca 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -48,54 +48,6 @@ popup_extension_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) view_child_destroy(popup); } -static void -popup_unconstrain(struct kiwmi_view_child *popup) -{ - if (popup->type != KIWMI_VIEW_CHILD_XDG_POPUP) { - wlr_log(WLR_ERROR, "Expected an xdg_popup kiwmi_view_child"); - return; - } - - struct kiwmi_view *view = popup->view; - - // Prefer output at view center - struct wlr_output *output = wlr_output_layout_output_at( - view->desktop->output_layout, - view->x + view->geom.width / 2, - view->y + view->geom.height / 2); - - if (!output) { - // Retry with view top-left corner (if its center is off-screen) - output = wlr_output_layout_output_at( - view->desktop->output_layout, view->x, view->y); - } - - if (!output) { - wlr_log( - WLR_ERROR, "View's output not found, popups may end up invisible"); - return; - } - - double view_ox = view->x; - double view_oy = view->y; - wlr_output_layout_output_coords( - view->desktop->output_layout, output, &view_ox, &view_oy); - - int output_width; - int output_height; - wlr_output_effective_resolution(output, &output_width, &output_height); - - // relative to the view - struct wlr_box output_box = { - .x = -view_ox, - .y = -view_oy, - .width = output_width, - .height = output_height, - }; - - wlr_xdg_popup_unconstrain_from_box(popup->wlr_xdg_popup, &output_box); -} - static void popup_reconfigure(struct kiwmi_view_child *popup) { @@ -103,15 +55,6 @@ popup_reconfigure(struct kiwmi_view_child *popup) wlr_log(WLR_ERROR, "Expected an xdg_popup view_child"); return; } - - popup_unconstrain(popup); - - struct kiwmi_view_child *subchild; - wl_list_for_each (subchild, &popup->children, link) { - if (subchild->impl && subchild->impl->reconfigure) { - subchild->impl->reconfigure(subchild); - } - } } static const struct kiwmi_view_child_impl xdg_popup_view_child_impl = { @@ -146,8 +89,6 @@ view_child_popup_create( child->extension_destroy.notify = popup_extension_destroy_notify; wl_signal_add(&wlr_popup->base->events.destroy, &child->extension_destroy); - popup_unconstrain(child); - return child; } From ac0f6b7e8b93c615825e540ed534ebef2655d713 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Sun, 8 May 2022 10:01:18 +0000 Subject: [PATCH 08/10] Cleanup unneeded code after switching to wlr_scene --- include/desktop/desktop.h | 1 - include/desktop/layer_shell.h | 9 -- include/desktop/view.h | 73 ----------- kiwmi/desktop/desktop.c | 5 - kiwmi/desktop/layer_shell.c | 40 +----- kiwmi/desktop/view.c | 222 ---------------------------------- kiwmi/desktop/xdg_shell.c | 148 +++-------------------- kiwmi/luak/kiwmi_server.c | 5 +- 8 files changed, 21 insertions(+), 482 deletions(-) diff --git a/include/desktop/desktop.h b/include/desktop/desktop.h index 1019230..9247219 100644 --- a/include/desktop/desktop.h +++ b/include/desktop/desktop.h @@ -26,7 +26,6 @@ struct kiwmi_desktop { struct wl_list outputs; // struct kiwmi_output::link struct wl_list views; // struct kiwmi_view::link - float bg_color[4]; struct wlr_scene *scene; struct wlr_scene_rect *background_rect; struct wlr_scene_tree *strata[KIWMI_STRATA_COUNT]; diff --git a/include/desktop/layer_shell.h b/include/desktop/layer_shell.h index 83fe3f7..f17bfd9 100644 --- a/include/desktop/layer_shell.h +++ b/include/desktop/layer_shell.h @@ -30,19 +30,10 @@ struct kiwmi_layer { struct wl_listener commit; struct wl_listener map; struct wl_listener unmap; - - struct wlr_box geom; }; void arrange_layers(struct kiwmi_output *output); -struct kiwmi_layer *layer_at( - struct wl_list *layers, - struct wlr_surface **surface, - double ox, - double oy, - double *sx, - double *sy); void layer_shell_new_surface_notify(struct wl_listener *listener, void *data); #endif /* KIWMI_DESKTOP_LAYER_SHELL_H */ diff --git a/include/desktop/view.h b/include/desktop/view.h index 72c9163..5ada1bb 100644 --- a/include/desktop/view.h +++ b/include/desktop/view.h @@ -30,7 +30,6 @@ enum kiwmi_view_type { struct kiwmi_view { struct wl_list link; - struct wl_list children; // struct kiwmi_view_child::link struct kiwmi_desktop_surface desktop_surface; struct kiwmi_desktop *desktop; @@ -50,16 +49,10 @@ struct kiwmi_view { struct wl_listener unmap; struct wl_listener commit; struct wl_listener destroy; - struct wl_listener new_popup; - struct wl_listener new_subsurface; struct wl_listener request_move; struct wl_listener request_resize; - int x; - int y; - bool mapped; - bool hidden; struct { struct wl_signal unmap; @@ -74,58 +67,12 @@ struct kiwmi_view { struct kiwmi_view_impl { void (*close)(struct kiwmi_view *view); - void (*for_each_surface)( - struct kiwmi_view *view, - wlr_surface_iterator_func_t callback, - void *user_data); pid_t (*get_pid)(struct kiwmi_view *view); void (*set_activated)(struct kiwmi_view *view, bool activated); void (*set_size)(struct kiwmi_view *view, uint32_t width, uint32_t height); const char *( *get_string_prop)(struct kiwmi_view *view, enum kiwmi_view_prop prop); void (*set_tiled)(struct kiwmi_view *view, enum wlr_edges edges); - struct wlr_surface *(*surface_at)( - struct kiwmi_view *view, - double sx, - double sy, - double *sub_x, - double *sub_y); -}; - -enum kiwmi_view_child_type { - KIWMI_VIEW_CHILD_SUBSURFACE, - KIWMI_VIEW_CHILD_XDG_POPUP, -}; - -struct kiwmi_view_child { - struct wl_list link; - struct wl_list children; // struct kiwmi_view_child::link - - struct kiwmi_view *view; - struct kiwmi_view_child *parent; - - enum kiwmi_view_child_type type; - const struct kiwmi_view_child_impl *impl; - - struct wlr_surface *wlr_surface; - union { - struct wlr_subsurface *wlr_subsurface; - struct wlr_xdg_popup *wlr_xdg_popup; - }; - - bool mapped; - - struct wl_listener commit; - struct wl_listener map; - struct wl_listener unmap; - struct wl_listener new_popup; - struct wl_listener new_subsurface; - struct wl_listener extension_destroy; // the union'ed object destroy - struct wl_listener surface_destroy; // wlr_surface::events.destroy -}; - -struct kiwmi_view_child_impl { - void (*reconfigure)(struct kiwmi_view_child *child); }; struct kiwmi_request_resize_event { @@ -134,10 +81,6 @@ struct kiwmi_request_resize_event { }; void view_close(struct kiwmi_view *view); -void view_for_each_surface( - struct kiwmi_view *view, - wlr_surface_iterator_func_t callback, - void *user_data); pid_t view_get_pid(struct kiwmi_view *view); void view_get_size(struct kiwmi_view *view, uint32_t *width, uint32_t *height); const char *view_get_app_id(struct kiwmi_view *view); @@ -157,20 +100,4 @@ struct kiwmi_view *view_create( enum kiwmi_view_type type, const struct kiwmi_view_impl *impl); -void -view_init_subsurfaces(struct kiwmi_view_child *child, struct kiwmi_view *view); -bool view_child_is_mapped(struct kiwmi_view_child *child); -void view_child_damage(struct kiwmi_view_child *child); -void view_child_destroy(struct kiwmi_view_child *child); -struct kiwmi_view_child *view_child_create( - struct kiwmi_view_child *parent, - struct kiwmi_view *view, - struct wlr_surface *wlr_surface, - enum kiwmi_view_child_type type, - const struct kiwmi_view_child_impl *impl); -struct kiwmi_view_child *view_child_subsurface_create( - struct kiwmi_view_child *parent, - struct kiwmi_view *view, - struct wlr_subsurface *subsurface); - #endif /* KIWMI_DESKTOP_VIEW_H */ diff --git a/kiwmi/desktop/desktop.c b/kiwmi/desktop/desktop.c index 7e3531a..5fd4ba7 100644 --- a/kiwmi/desktop/desktop.c +++ b/kiwmi/desktop/desktop.c @@ -48,11 +48,6 @@ desktop_init(struct kiwmi_desktop *desktop) wlr_xdg_output_manager_v1_create( server->wl_display, desktop->output_layout); - desktop->bg_color[0] = 0.1f; - desktop->bg_color[1] = 0.1f; - desktop->bg_color[2] = 0.1f; - desktop->bg_color[3] = 1.0f; - desktop->scene = wlr_scene_create(); if (!desktop->scene) { wlr_log(WLR_ERROR, "failed to create scene"); diff --git a/kiwmi/desktop/layer_shell.c b/kiwmi/desktop/layer_shell.c index 3853c28..3b77a0c 100644 --- a/kiwmi/desktop/layer_shell.c +++ b/kiwmi/desktop/layer_shell.c @@ -251,14 +251,14 @@ arrange_layer( continue; } - layer->geom = arranged_area; - wlr_scene_node_set_position( - &layer->desktop_surface.tree->node, layer->geom.x, layer->geom.y); + &layer->desktop_surface.tree->node, + arranged_area.x, + arranged_area.y); wlr_scene_node_set_position( &layer->desktop_surface.popups_tree->node, - layer->geom.x, - layer->geom.y); + arranged_area.x, + arranged_area.y); apply_exclusive( usable_area, @@ -360,36 +360,6 @@ arrange_layers(struct kiwmi_output *output) seat_focus_layer(seat, topmost); } -struct kiwmi_layer * -layer_at( - struct wl_list *layers, - struct wlr_surface **surface, - double ox, - double oy, - double *sx, - double *sy) -{ - struct kiwmi_layer *layer; - wl_list_for_each_reverse (layer, layers, link) { - double layer_sx = ox - layer->geom.x; - double layer_sy = oy - layer->geom.y; - - double _sx; - double _sy; - struct wlr_surface *_surface = wlr_layer_surface_v1_surface_at( - layer->layer_surface, layer_sx, layer_sy, &_sx, &_sy); - - if (_surface) { - *sx = _sx; - *sy = _sy; - *surface = _surface; - return layer; - } - } - - return NULL; -} - static struct kiwmi_output * layer_desktop_surface_get_output(struct kiwmi_desktop_surface *desktop_surface) { diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index 4bba2ad..fdc5cc0 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -25,17 +25,6 @@ view_close(struct kiwmi_view *view) } } -void -view_for_each_surface( - struct kiwmi_view *view, - wlr_surface_iterator_func_t callback, - void *user_data) -{ - if (view->impl->for_each_surface) { - view->impl->for_each_surface(view, callback, user_data); - } -} - pid_t view_get_pid(struct kiwmi_view *view) { @@ -86,22 +75,12 @@ view_set_size(struct kiwmi_view *view, uint32_t width, uint32_t height) { if (view->impl->set_size) { view->impl->set_size(view, width, height); - - struct kiwmi_view_child *child; - wl_list_for_each (child, &view->children, link) { - if (child->impl && child->impl->reconfigure) { - child->impl->reconfigure(child); - } - } } } void view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y) { - view->x = x; - view->y = y; - wlr_scene_node_set_position(&view->desktop_surface.tree->node, x, y); wlr_scene_node_set_position(&view->desktop_surface.popups_tree->node, x, y); @@ -125,8 +104,6 @@ view_set_tiled(struct kiwmi_view *view, enum wlr_edges edges) void view_set_hidden(struct kiwmi_view *view, bool hidden) { - view->hidden = hidden; - if (!view->mapped) { return; } @@ -206,31 +183,6 @@ view_resize(struct kiwmi_view *view, uint32_t edges) view_begin_interactive(view, KIWMI_CURSOR_RESIZE, edges); } -/** - * Creates a kiwmi_view_child for each subsurface of either the 'child' or the - * 'view'. 'child' can be NULL, 'view' should never be. - */ -void -view_init_subsurfaces(struct kiwmi_view_child *child, struct kiwmi_view *view) -{ - struct wlr_surface *surface = - child ? child->wlr_surface : view->wlr_surface; - if (!surface) { - wlr_log(WLR_ERROR, "Attempting to init_subsurfaces without a surface"); - return; - } - - struct wlr_subsurface *subsurface; - wl_list_for_each ( - subsurface, &surface->current.subsurfaces_below, current.link) { - view_child_subsurface_create(child, view, subsurface); - } - wl_list_for_each ( - subsurface, &surface->current.subsurfaces_above, current.link) { - view_child_subsurface_create(child, view, subsurface); - } -} - static struct kiwmi_output * view_desktop_surface_get_output(struct kiwmi_desktop_surface *desktop_surface) { @@ -278,14 +230,8 @@ view_create( view->type = type; view->impl = impl; view->mapped = false; - view->hidden = true; view->decoration = NULL; - view->x = 0; - view->y = 0; - - wl_list_init(&view->children); - view->desktop_surface.type = KIWMI_DESKTOP_SURFACE_VIEW; view->desktop_surface.impl = &view_desktop_surface_impl; @@ -309,171 +255,3 @@ view_create( return view; } - -bool -view_child_is_mapped(struct kiwmi_view_child *child) -{ - if (!child->mapped) { - return false; - } - - struct kiwmi_view_child *parent = child->parent; - while (parent) { - if (!parent->mapped) { - return false; - } - parent = parent->parent; - } - - return child->view->mapped; -} - -void -view_child_destroy(struct kiwmi_view_child *child) -{ - wl_list_remove(&child->link); - child->parent = NULL; - - struct kiwmi_view_child *subchild, *tmpchild; - wl_list_for_each_safe (subchild, tmpchild, &child->children, link) { - subchild->mapped = false; - view_child_destroy(subchild); - } - - wl_list_remove(&child->commit.link); - wl_list_remove(&child->map.link); - wl_list_remove(&child->unmap.link); - wl_list_remove(&child->new_popup.link); - wl_list_remove(&child->new_subsurface.link); - wl_list_remove(&child->surface_destroy.link); - wl_list_remove(&child->extension_destroy.link); - - free(child); -} - -static void -view_child_subsurface_extension_destroy_notify( - struct wl_listener *listener, - void *UNUSED(data)) -{ - struct kiwmi_view_child *child = - wl_container_of(listener, child, extension_destroy); - view_child_destroy(child); -} - -static void -view_child_surface_destroy_notify( - struct wl_listener *listener, - void *UNUSED(data)) -{ - struct kiwmi_view_child *child = - wl_container_of(listener, child, surface_destroy); - view_child_destroy(child); -} - -static void -view_child_commit_notify() -{ -} - -static void -view_child_new_subsurface_notify(struct wl_listener *listener, void *data) -{ - struct kiwmi_view_child *child = - wl_container_of(listener, child, new_subsurface); - struct wlr_subsurface *subsurface = data; - view_child_subsurface_create(child, child->view, subsurface); -} - -static void -view_child_map_notify(struct wl_listener *listener, void *UNUSED(data)) -{ - struct kiwmi_view_child *child = wl_container_of(listener, child, map); - child->mapped = true; -} - -static void -view_child_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) -{ - struct kiwmi_view_child *child = wl_container_of(listener, child, unmap); - child->mapped = false; -} - -struct kiwmi_view_child * -view_child_create( - struct kiwmi_view_child *parent, - struct kiwmi_view *view, - struct wlr_surface *wlr_surface, - enum kiwmi_view_child_type type, - const struct kiwmi_view_child_impl *impl) -{ - struct kiwmi_view_child *child = calloc(1, sizeof(*child)); - if (!child) { - wlr_log(WLR_ERROR, "Failed to allocate view_child"); - return NULL; - } - - child->type = type; - child->impl = impl; - child->view = view; - child->wlr_surface = wlr_surface; - child->mapped = false; - - if (parent) { - child->parent = parent; - wl_list_insert(&parent->children, &child->link); - } else { - wl_list_insert(&view->children, &child->link); - } - - wl_list_init(&child->children); - - child->commit.notify = view_child_commit_notify; - wl_signal_add(&wlr_surface->events.commit, &child->commit); - - child->map.notify = view_child_map_notify; - child->unmap.notify = view_child_unmap_notify; - - // wlr_surface doesn't have these events, but its extensions usually do - wl_list_init(&child->map.link); - wl_list_init(&child->unmap.link); - - child->new_subsurface.notify = view_child_new_subsurface_notify; - wl_signal_add(&wlr_surface->events.new_subsurface, &child->new_subsurface); - - child->surface_destroy.notify = view_child_surface_destroy_notify; - wl_signal_add(&wlr_surface->events.destroy, &child->surface_destroy); - - // Possibly unused - wl_list_init(&child->new_popup.link); - wl_list_init(&child->extension_destroy.link); - - view_init_subsurfaces(child, child->view); - - return child; -} - -struct kiwmi_view_child * -view_child_subsurface_create( - struct kiwmi_view_child *parent, - struct kiwmi_view *view, - struct wlr_subsurface *subsurface) -{ - struct kiwmi_view_child *child = view_child_create( - parent, view, subsurface->surface, KIWMI_VIEW_CHILD_SUBSURFACE, NULL); - if (!child) { - return NULL; - } - - child->wlr_subsurface = subsurface; - child->mapped = subsurface->mapped; - - wl_signal_add(&subsurface->events.map, &child->map); - wl_signal_add(&subsurface->events.unmap, &child->unmap); - - child->extension_destroy.notify = - view_child_subsurface_extension_destroy_notify; - wl_signal_add(&subsurface->events.destroy, &child->extension_destroy); - - return child; -} diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index 36feaca..eac3839 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -26,88 +26,6 @@ #include "input/seat.h" #include "server.h" -static struct kiwmi_view_child *view_child_popup_create( - struct kiwmi_view_child *parent, - struct kiwmi_view *view, - struct wlr_xdg_popup *wlr_popup); - -static void -popup_new_popup_notify(struct wl_listener *listener, void *data) -{ - struct kiwmi_view_child *popup = - wl_container_of(listener, popup, new_popup); - struct wlr_xdg_popup *wlr_popup = data; - view_child_popup_create(popup, popup->view, wlr_popup); -} - -static void -popup_extension_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) -{ - struct kiwmi_view_child *popup = - wl_container_of(listener, popup, extension_destroy); - view_child_destroy(popup); -} - -static void -popup_reconfigure(struct kiwmi_view_child *popup) -{ - if (popup->type != KIWMI_VIEW_CHILD_XDG_POPUP) { - wlr_log(WLR_ERROR, "Expected an xdg_popup view_child"); - return; - } -} - -static const struct kiwmi_view_child_impl xdg_popup_view_child_impl = { - .reconfigure = popup_reconfigure, -}; - -static struct kiwmi_view_child * -view_child_popup_create( - struct kiwmi_view_child *parent, - struct kiwmi_view *view, - struct wlr_xdg_popup *wlr_popup) -{ - struct kiwmi_view_child *child = view_child_create( - parent, - view, - wlr_popup->base->surface, - KIWMI_VIEW_CHILD_XDG_POPUP, - &xdg_popup_view_child_impl); - if (!child) { - return NULL; - } - - child->wlr_xdg_popup = wlr_popup; - child->mapped = wlr_popup->base->mapped; - - wl_signal_add(&wlr_popup->base->events.map, &child->map); - wl_signal_add(&wlr_popup->base->events.unmap, &child->unmap); - - child->new_popup.notify = popup_new_popup_notify; - wl_signal_add(&wlr_popup->base->events.new_popup, &child->new_popup); - - child->extension_destroy.notify = popup_extension_destroy_notify; - wl_signal_add(&wlr_popup->base->events.destroy, &child->extension_destroy); - - return child; -} - -static void -xdg_surface_new_popup_notify(struct wl_listener *listener, void *data) -{ - struct kiwmi_view *view = wl_container_of(listener, view, new_popup); - struct wlr_xdg_popup *wlr_popup = data; - view_child_popup_create(NULL, view, wlr_popup); -} - -static void -xdg_surface_new_subsurface_notify(struct wl_listener *listener, void *data) -{ - struct kiwmi_view *view = wl_container_of(listener, view, new_subsurface); - struct wlr_subsurface *subsurface = data; - view_child_subsurface_create(NULL, view, subsurface); -} - static void xdg_surface_map_notify(struct wl_listener *listener, void *UNUSED(data)) { @@ -143,12 +61,16 @@ xdg_surface_commit_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_view *view = wl_container_of(listener, view, commit); - struct kiwmi_desktop *desktop = view->desktop; - struct kiwmi_server *server = wl_container_of(desktop, server, desktop); - struct kiwmi_cursor *cursor = server->input.cursor; - cursor_refresh_focus(cursor, NULL, NULL, NULL); + struct wlr_box geom; + wlr_xdg_surface_get_geometry(view->xdg_surface, &geom); - wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom); + if (memcmp(&view->geom, &geom, sizeof(geom)) != 0) { + memcpy(&view->geom, &geom, sizeof(geom)); + + struct kiwmi_desktop *desktop = view->desktop; + struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); + } } static void @@ -168,24 +90,15 @@ xdg_surface_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) } cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); - struct kiwmi_view_child *child, *tmpchild; - wl_list_for_each_safe (child, tmpchild, &view->children, link) { - child->mapped = false; - view_child_destroy(child); - } - if (view->decoration) { view->decoration->view = NULL; } wl_list_remove(&view->link); - wl_list_remove(&view->children); wl_list_remove(&view->map.link); wl_list_remove(&view->unmap.link); wl_list_remove(&view->commit.link); wl_list_remove(&view->destroy.link); - wl_list_remove(&view->new_popup.link); - wl_list_remove(&view->new_subsurface.link); wl_list_remove(&view->request_move.link); wl_list_remove(&view->request_resize.link); @@ -228,15 +141,6 @@ xdg_shell_view_close(struct kiwmi_view *view) } } -static void -xdg_shell_view_for_each_surface( - struct kiwmi_view *view, - wlr_surface_iterator_func_t callback, - void *user_data) -{ - wlr_xdg_surface_for_each_surface(view->xdg_surface, callback, user_data); -} - static pid_t xdg_shell_view_get_pid(struct kiwmi_view *view) { @@ -284,26 +188,13 @@ xdg_shell_view_set_tiled(struct kiwmi_view *view, enum wlr_edges edges) wlr_xdg_toplevel_set_tiled(view->xdg_surface, edges); } -struct wlr_surface * -xdg_shell_view_surface_at( - struct kiwmi_view *view, - double sx, - double sy, - double *sub_x, - double *sub_y) -{ - return wlr_xdg_surface_surface_at(view->xdg_surface, sx, sy, sub_x, sub_y); -} - static const struct kiwmi_view_impl xdg_shell_view_impl = { - .close = xdg_shell_view_close, - .for_each_surface = xdg_shell_view_for_each_surface, - .get_pid = xdg_shell_view_get_pid, - .get_string_prop = xdg_shell_view_get_string_prop, - .set_activated = xdg_shell_view_set_activated, - .set_size = xdg_shell_view_set_size, - .set_tiled = xdg_shell_view_set_tiled, - .surface_at = xdg_shell_view_surface_at, + .close = xdg_shell_view_close, + .get_pid = xdg_shell_view_get_pid, + .get_string_prop = xdg_shell_view_get_string_prop, + .set_activated = xdg_shell_view_set_activated, + .set_size = xdg_shell_view_set_size, + .set_tiled = xdg_shell_view_set_tiled, }; void @@ -361,13 +252,6 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data) view->destroy.notify = xdg_surface_destroy_notify; wl_signal_add(&xdg_surface->events.destroy, &view->destroy); - view->new_popup.notify = xdg_surface_new_popup_notify; - wl_signal_add(&xdg_surface->events.new_popup, &view->new_popup); - - view->new_subsurface.notify = xdg_surface_new_subsurface_notify; - wl_signal_add( - &xdg_surface->surface->events.new_subsurface, &view->new_subsurface); - view->request_move.notify = xdg_toplevel_request_move_notify; wl_signal_add( &xdg_surface->toplevel->events.request_move, &view->request_move); @@ -376,8 +260,6 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data) wl_signal_add( &xdg_surface->toplevel->events.request_resize, &view->request_resize); - view_init_subsurfaces(NULL, view); - wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom); wl_list_insert(&desktop->views, &view->link); diff --git a/kiwmi/luak/kiwmi_server.c b/kiwmi/luak/kiwmi_server.c index ec0bccc..cf44ea2 100644 --- a/kiwmi/luak/kiwmi_server.c +++ b/kiwmi/luak/kiwmi_server.c @@ -65,10 +65,7 @@ l_kiwmi_server_bg_color(lua_State *L) return luaL_argerror(L, 2, "not a valid color"); } - server->desktop.bg_color[0] = color[0]; - server->desktop.bg_color[1] = color[1]; - server->desktop.bg_color[2] = color[2]; - // ignore alpha + // Ignore alpha (color channels are already premultiplied) color[3] = 1.0f; wlr_scene_rect_set_color(server->desktop.background_rect, color); From 8dcfffbdaa804ac42eb599cbde9eb186b9caae91 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Wed, 22 Dec 2021 21:17:30 +0000 Subject: [PATCH 09/10] Support protocols made easy by wlr_scene --- kiwmi/desktop/desktop.c | 5 +++++ kiwmi/server.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/kiwmi/desktop/desktop.c b/kiwmi/desktop/desktop.c index 5fd4ba7..7d1c1b8 100644 --- a/kiwmi/desktop/desktop.c +++ b/kiwmi/desktop/desktop.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,10 @@ desktop_init(struct kiwmi_desktop *desktop) wlr_scene_attach_output_layout(desktop->scene, desktop->output_layout); + struct wlr_presentation *presentation = + wlr_presentation_create(server->wl_display, server->backend); + wlr_scene_set_presentation(desktop->scene, presentation); + desktop->xdg_shell = wlr_xdg_shell_create(server->wl_display); desktop->xdg_shell_new_surface.notify = xdg_shell_new_surface_notify; wl_signal_add( diff --git a/kiwmi/server.c b/kiwmi/server.c index ba0e74c..2b55371 100644 --- a/kiwmi/server.c +++ b/kiwmi/server.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "luak/luak.h" @@ -67,6 +68,7 @@ server_init(struct kiwmi_server *server, char *config_path) wlr_data_control_manager_v1_create(server->wl_display); wlr_gamma_control_manager_v1_create(server->wl_display); wlr_primary_selection_v1_device_manager_create(server->wl_display); + wlr_viewporter_create(server->wl_display); server->socket = wl_display_add_socket_auto(server->wl_display); if (!server->socket) { From 37312b908d1b1966fe03d6664e9d47b2ecf30ec2 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Sun, 8 May 2022 10:02:25 +0000 Subject: [PATCH 10/10] (Un)focus logic improvements --- kiwmi/desktop/view.c | 7 +++++++ kiwmi/desktop/xdg_shell.c | 14 +++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index fdc5cc0..efd0d66 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -111,6 +111,13 @@ view_set_hidden(struct kiwmi_view *view, bool hidden) wlr_scene_node_set_enabled(&view->desktop_surface.tree->node, !hidden); wlr_scene_node_set_enabled( &view->desktop_surface.popups_tree->node, !hidden); + + struct kiwmi_server *server = + wl_container_of(view->desktop, server, desktop); + struct kiwmi_seat *seat = server->input.seat; + if (seat->focused_view == view) { + seat->focused_view = NULL; + } } struct kiwmi_view * diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index eac3839..733de40 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -51,6 +51,11 @@ xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_server *server = wl_container_of(view->desktop, server, desktop); cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); + + struct kiwmi_seat *seat = server->input.seat; + if (seat->focused_view == view) { + seat->focused_view = NULL; + } } wl_signal_emit(&view->events.unmap, view); @@ -81,15 +86,6 @@ xdg_surface_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) wlr_scene_node_destroy(&view->desktop_surface.tree->node); wlr_scene_node_destroy(&view->desktop_surface.popups_tree->node); - struct kiwmi_desktop *desktop = view->desktop; - struct kiwmi_server *server = wl_container_of(desktop, server, desktop); - struct kiwmi_seat *seat = server->input.seat; - - if (seat->focused_view == view) { - seat->focused_view = NULL; - } - cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); - if (view->decoration) { view->decoration->view = NULL; }