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:
parent
8c191d2d41
commit
f144eb1438
16 changed files with 336 additions and 20 deletions
|
@ -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;
|
||||||
|
|
27
include/desktop/desktop_surface.h
Normal file
27
include/desktop/desktop_surface.h
Normal 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 */
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
20
include/desktop/popup.h
Normal 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 */
|
|
@ -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,
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
71
kiwmi/desktop/popup.c
Normal 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;
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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',
|
||||||
|
|
Loading…
Reference in a new issue