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.
This commit is contained in:
tiosgz 2021-12-22 20:46:15 +00:00
parent 8c191d2d41
commit f144eb1438
16 changed files with 336 additions and 20 deletions

View file

@ -9,23 +9,33 @@
#define KIWMI_DESKTOP_DESKTOP_H #define KIWMI_DESKTOP_DESKTOP_H
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/types/wlr_scene.h>
#include "desktop/stratum.h"
struct kiwmi_desktop { struct kiwmi_desktop {
struct wlr_compositor *compositor; struct wlr_compositor *compositor;
struct wlr_xdg_shell *xdg_shell; struct wlr_xdg_shell *xdg_shell;
struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager; struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager;
struct wlr_layer_shell_v1 *layer_shell; struct wlr_layer_shell_v1 *layer_shell;
struct wlr_data_device_manager *data_device_manager; struct wlr_data_device_manager *data_device_manager;
struct wlr_output_layout *output_layout; struct wlr_output_layout *output_layout;
struct wl_list outputs; // struct kiwmi_output::link struct wl_list outputs; // struct kiwmi_output::link
struct wl_list views; // struct kiwmi_view::link struct wl_list views; // struct kiwmi_view::link
float bg_color[4]; 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_shell_new_surface;
struct wl_listener xdg_toplevel_new_decoration; struct wl_listener xdg_toplevel_new_decoration;
struct wl_listener layer_shell_new_surface; struct wl_listener layer_shell_new_surface;
struct wl_listener new_output; struct wl_listener new_output;
struct wl_listener output_layout_change;
struct { struct {
struct wl_signal new_output; struct wl_signal new_output;

View file

@ -0,0 +1,27 @@
/* Copyright (c), Niclas Meyer <niclas@countingsort.com>
*
* 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 */

View file

@ -14,10 +14,13 @@
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_surface.h>
#include <wlr/util/box.h> #include <wlr/util/box.h>
#include "desktop/desktop_surface.h"
#include "desktop/output.h" #include "desktop/output.h"
struct kiwmi_layer { struct kiwmi_layer {
struct wl_list link; struct wl_list link;
struct kiwmi_desktop_surface desktop_surface;
struct wlr_layer_surface_v1 *layer_surface; struct wlr_layer_surface_v1 *layer_surface;
uint32_t layer; // enum zwlr_layer_shell_v1_layer uint32_t layer; // enum zwlr_layer_shell_v1_layer

View file

@ -11,16 +11,21 @@
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/util/box.h> #include <wlr/util/box.h>
#include "desktop/stratum.h"
struct kiwmi_output { struct kiwmi_output {
struct wl_list link; struct wl_list link;
struct kiwmi_desktop *desktop; struct kiwmi_desktop *desktop;
struct wlr_output *wlr_output; struct wlr_output *wlr_output;
struct wl_listener frame; struct wl_listener frame;
struct wl_listener commit; struct wl_listener commit;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener mode; 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; struct wlr_box usable_area;
int damaged; int damaged;
@ -42,6 +47,7 @@ struct kiwmi_render_data {
}; };
void new_output_notify(struct wl_listener *listener, void *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); void output_damage(struct kiwmi_output *output);

20
include/desktop/popup.h Normal file
View file

@ -0,0 +1,20 @@
/* Copyright (c), Niclas Meyer <niclas@countingsort.com>
*
* 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 */

View file

@ -17,6 +17,8 @@
#include <wlr/types/wlr_xdg_shell.h> #include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/edges.h> #include <wlr/util/edges.h>
#include "desktop/desktop_surface.h"
enum kiwmi_view_prop { enum kiwmi_view_prop {
KIWMI_VIEW_PROP_APP_ID, KIWMI_VIEW_PROP_APP_ID,
KIWMI_VIEW_PROP_TITLE, KIWMI_VIEW_PROP_TITLE,
@ -29,6 +31,7 @@ enum kiwmi_view_type {
struct kiwmi_view { struct kiwmi_view {
struct wl_list link; struct wl_list link;
struct wl_list children; // struct kiwmi_view_child::link struct wl_list children; // struct kiwmi_view_child::link
struct kiwmi_desktop_surface desktop_surface;
struct kiwmi_desktop *desktop; 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_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_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_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 wlr_surface *view_surface_at(
struct kiwmi_view *view, struct kiwmi_view *view,
double sx, double sx,

View file

@ -20,9 +20,11 @@
#include <wlr/types/wlr_xdg_decoration_v1.h> #include <wlr/types/wlr_xdg_decoration_v1.h>
#include <wlr/types/wlr_xdg_output_v1.h> #include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_shell.h> #include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
#include "desktop/layer_shell.h" #include "desktop/layer_shell.h"
#include "desktop/output.h" #include "desktop/output.h"
#include "desktop/stratum.h"
#include "desktop/view.h" #include "desktop/view.h"
#include "desktop/xdg_shell.h" #include "desktop/xdg_shell.h"
#include "input/cursor.h" #include "input/cursor.h"
@ -49,6 +51,25 @@ desktop_init(struct kiwmi_desktop *desktop)
desktop->bg_color[2] = 0.1f; desktop->bg_color[2] = 0.1f;
desktop->bg_color[3] = 1.0f; 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 = wlr_xdg_shell_create(server->wl_display);
desktop->xdg_shell_new_surface.notify = xdg_shell_new_surface_notify; desktop->xdg_shell_new_surface.notify = xdg_shell_new_surface_notify;
wl_signal_add( wl_signal_add(
@ -75,6 +96,10 @@ desktop_init(struct kiwmi_desktop *desktop)
desktop->new_output.notify = new_output_notify; desktop->new_output.notify = new_output_notify;
wl_signal_add(&server->backend->events.new_output, &desktop->new_output); 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.new_output);
wl_signal_init(&desktop->events.view_map); wl_signal_init(&desktop->events.view_map);
wl_signal_init(&desktop->events.request_active_output); 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); wlr_output_layout_destroy(desktop->output_layout);
desktop->output_layout = NULL; desktop->output_layout = NULL;
wlr_scene_node_destroy(&desktop->scene->node);
desktop->scene = NULL;
} }
struct kiwmi_output * struct kiwmi_output *

View file

@ -15,7 +15,9 @@
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "desktop/desktop.h" #include "desktop/desktop.h"
#include "desktop/desktop_surface.h"
#include "desktop/output.h" #include "desktop/output.h"
#include "desktop/stratum.h"
#include "input/seat.h" #include "input/seat.h"
#include "server.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); 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->destroy.link);
wl_list_remove(&layer->map.link); wl_list_remove(&layer->map.link);
wl_list_remove(&layer->unmap.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_layer *layer = wl_container_of(listener, layer, commit);
struct kiwmi_output *output = layer->output; struct kiwmi_output *output = layer->output;
struct wlr_box old_geom = layer->geom; if (layer->layer != layer->layer_surface->current.layer) {
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) {
wl_list_remove(&layer->link); wl_list_remove(&layer->link);
layer->layer = layer->layer_surface->current.layer; layer->layer = layer->layer_surface->current.layer;
wl_list_insert(&output->layers[layer->layer], &layer->link); 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); 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); 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); 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); 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); output_damage(layer->output);
} }
@ -245,6 +256,13 @@ arrange_layer(
layer->geom = arranged_area; 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( apply_exclusive(
usable_area, usable_area,
state->anchor, state->anchor,
@ -415,6 +433,8 @@ layer_shell_new_surface_notify(struct wl_listener *listener, void *data)
layer->output = output; layer->output = output;
layer->layer = layer_surface->current.layer; layer->layer = layer_surface->current.layer;
layer->desktop_surface.type = KIWMI_DESKTOP_SURFACE_LAYER;
layer->destroy.notify = kiwmi_layer_destroy_notify; layer->destroy.notify = kiwmi_layer_destroy_notify;
wl_signal_add(&layer_surface->events.destroy, &layer->destroy); 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; layer->unmap.notify = kiwmi_layer_unmap_notify;
wl_signal_add(&layer_surface->events.unmap, &layer->unmap); 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); wl_list_insert(&output->layers[layer->layer], &layer->link);
// Temporarily set the layer's current state to pending // 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; struct wlr_layer_surface_v1_state old_state = layer_surface->current;
layer_surface->current = layer_surface->pending; layer_surface->current = layer_surface->pending;
arrange_layers(output); arrange_layers(output);

View file

@ -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) { if (output->desktop->output_layout) {
wlr_output_layout_remove( wlr_output_layout_remove(
output->desktop->output_layout, output->wlr_output); 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); wlr_output_create_global(wlr_output);
size_t len_outputs = sizeof(output->layers) / sizeof(output->layers[0]); size_t len_layers = sizeof(output->layers) / sizeof(output->layers[0]);
for (size_t i = 0; i < len_outputs; ++i) { for (size_t i = 0; i < len_layers; ++i) {
wl_list_init(&output->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.destroy);
wl_signal_init(&output->events.resize); wl_signal_init(&output->events.resize);
wl_signal_init(&output->events.usable_area_change); 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); wl_signal_emit(&desktop->events.new_output, output);
} }
@ -401,3 +415,32 @@ output_damage(struct kiwmi_output *output)
output->damaged = 2; 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);
}
}
}
}

71
kiwmi/desktop/popup.c Normal file
View file

@ -0,0 +1,71 @@
/* Copyright (c), Niclas Meyer <niclas@countingsort.com>
*
* 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 <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
#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;
}

View file

@ -11,6 +11,7 @@
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "desktop/output.h" #include "desktop/output.h"
#include "desktop/stratum.h"
#include "input/cursor.h" #include "input/cursor.h"
#include "input/seat.h" #include "input/seat.h"
#include "server.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->x = x;
view->y = y; 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; struct kiwmi_view_child *child;
wl_list_for_each (child, &view->children, link) { wl_list_for_each (child, &view->children, link) {
if (child->impl && child->impl->reconfigure) { 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 * struct wlr_surface *
view_surface_at( view_surface_at(
struct kiwmi_view *view, struct kiwmi_view *view,
@ -296,12 +314,26 @@ view_create(
wl_list_init(&view->children); wl_list_init(&view->children);
view->desktop_surface.type = KIWMI_DESKTOP_SURFACE_VIEW;
wl_signal_init(&view->events.unmap); wl_signal_init(&view->events.unmap);
wl_signal_init(&view->events.request_move); wl_signal_init(&view->events.request_move);
wl_signal_init(&view->events.request_resize); wl_signal_init(&view->events.request_resize);
wl_signal_init(&view->events.post_render); wl_signal_init(&view->events.post_render);
wl_signal_init(&view->events.pre_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; return view;
} }

View file

@ -11,6 +11,7 @@
#include <pixman.h> #include <pixman.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xdg_decoration_v1.h> #include <wlr/types/wlr_xdg_decoration_v1.h>
#include <wlr/types/wlr_xdg_shell.h> #include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/edges.h> #include <wlr/util/edges.h>
@ -18,6 +19,7 @@
#include "desktop/desktop.h" #include "desktop/desktop.h"
#include "desktop/output.h" #include "desktop/output.h"
#include "desktop/popup.h"
#include "desktop/view.h" #include "desktop/view.h"
#include "input/cursor.h" #include "input/cursor.h"
#include "input/input.h" #include "input/input.h"
@ -191,6 +193,14 @@ xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data))
if (view->mapped) { if (view->mapped) {
view->mapped = false; 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; struct kiwmi_output *output;
wl_list_for_each (output, &view->desktop->outputs, link) { wl_list_for_each (output, &view->desktop->outputs, link) {
output_damage(output); output_damage(output);
@ -224,6 +234,10 @@ static void
xdg_surface_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) 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_desktop *desktop = view->desktop;
struct kiwmi_server *server = wl_container_of(desktop, server, desktop); struct kiwmi_server *server = wl_container_of(desktop, server, desktop);
struct kiwmi_seat *seat = server->input.seat; 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) { if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
wlr_log(WLR_DEBUG, "New xdg_shell 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; return;
} }
@ -402,6 +425,9 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data)
view->xdg_surface = xdg_surface; view->xdg_surface = xdg_surface;
view->wlr_surface = xdg_surface->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; view->map.notify = xdg_surface_map_notify;
wl_signal_add(&xdg_surface->events.map, &view->map); 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); view_init_subsurfaces(NULL, view);
wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom);
wl_list_insert(&desktop->views, &view->link); wl_list_insert(&desktop->views, &view->link);
} }

View file

@ -83,6 +83,10 @@ seat_focus_view(struct kiwmi_seat *seat, struct kiwmi_view *view)
// move view to front // move view to front
wl_list_remove(&view->link); wl_list_remove(&view->link);
wl_list_insert(&desktop->views, &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); cursor_refresh_focus(seat->input->cursor, NULL, NULL, NULL);
seat->focused_view = view; seat->focused_view = view;

View file

@ -69,6 +69,11 @@ l_kiwmi_server_bg_color(lua_State *L)
server->desktop.bg_color[1] = color[1]; server->desktop.bg_color[1] = color[1];
server->desktop.bg_color[2] = color[2]; server->desktop.bg_color[2] = color[2];
// ignore alpha // 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; return 0;
} }

View file

@ -137,7 +137,7 @@ l_kiwmi_view_hide(lua_State *L)
struct kiwmi_view *view = obj->object; struct kiwmi_view *view = obj->object;
view->hidden = true; view_set_hidden(view, true);
return 0; return 0;
} }
@ -315,7 +315,7 @@ l_kiwmi_view_show(lua_State *L)
struct kiwmi_view *view = obj->object; struct kiwmi_view *view = obj->object;
view->hidden = false; view_set_hidden(view, false);
return 0; return 0;
} }

View file

@ -5,6 +5,7 @@ kiwmi_sources = files(
'desktop/desktop.c', 'desktop/desktop.c',
'desktop/layer_shell.c', 'desktop/layer_shell.c',
'desktop/output.c', 'desktop/output.c',
'desktop/popup.c',
'desktop/stratum.c', 'desktop/stratum.c',
'desktop/view.c', 'desktop/view.c',
'desktop/xdg_shell.c', 'desktop/xdg_shell.c',