Merge pull request #50 from tiosgz/wlr-scene

This commit is contained in:
Niclas 2022-07-30 20:49:54 +00:00 committed by GitHub
commit 17814972ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 707 additions and 1277 deletions

View file

@ -9,23 +9,32 @@
#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]; 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,45 @@
/* 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
struct wlr_surface;
struct kiwmi_desktop;
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;
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 */

View file

@ -14,12 +14,15 @@
#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; uint32_t layer; // enum zwlr_layer_shell_v1_layer
struct kiwmi_output *output; struct kiwmi_output *output;
@ -27,19 +30,10 @@ struct kiwmi_layer {
struct wl_listener commit; struct wl_listener commit;
struct wl_listener map; struct wl_listener map;
struct wl_listener unmap; struct wl_listener unmap;
struct wlr_box geom;
}; };
void arrange_layers(struct kiwmi_output *output); 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); void layer_shell_new_surface_notify(struct wl_listener *listener, void *data);
#endif /* KIWMI_DESKTOP_LAYER_SHELL_H */ #endif /* KIWMI_DESKTOP_LAYER_SHELL_H */

View file

@ -11,19 +11,22 @@
#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_box usable_area; struct wlr_scene_tree *strata[KIWMI_STRATA_COUNT];
int damaged; struct wlr_box usable_area;
struct { struct {
struct wl_signal destroy; struct wl_signal destroy;
@ -42,7 +45,6 @@ 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);
#endif /* KIWMI_DESKTOP_OUTPUT_H */ #endif /* KIWMI_DESKTOP_OUTPUT_H */

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 */

33
include/desktop/stratum.h Normal file
View file

@ -0,0 +1,33 @@
/* 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_STRATUM_H
#define KIWMI_DESKTOP_STRATUM_H
#include <stdint.h>
/**
* 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 */

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,
@ -28,7 +30,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 kiwmi_desktop_surface desktop_surface;
struct kiwmi_desktop *desktop; struct kiwmi_desktop *desktop;
@ -47,16 +49,10 @@ struct kiwmi_view {
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener commit; struct wl_listener commit;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener new_popup;
struct wl_listener new_subsurface;
struct wl_listener request_move; struct wl_listener request_move;
struct wl_listener request_resize; struct wl_listener request_resize;
int x;
int y;
bool mapped; bool mapped;
bool hidden;
struct { struct {
struct wl_signal unmap; struct wl_signal unmap;
@ -71,58 +67,12 @@ struct kiwmi_view {
struct kiwmi_view_impl { struct kiwmi_view_impl {
void (*close)(struct kiwmi_view *view); 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); pid_t (*get_pid)(struct kiwmi_view *view);
void (*set_activated)(struct kiwmi_view *view, bool activated); void (*set_activated)(struct kiwmi_view *view, bool activated);
void (*set_size)(struct kiwmi_view *view, uint32_t width, uint32_t height); void (*set_size)(struct kiwmi_view *view, uint32_t width, uint32_t height);
const char *( const char *(
*get_string_prop)(struct kiwmi_view *view, enum kiwmi_view_prop prop); *get_string_prop)(struct kiwmi_view *view, enum kiwmi_view_prop prop);
void (*set_tiled)(struct kiwmi_view *view, enum wlr_edges edges); 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 { struct kiwmi_request_resize_event {
@ -131,10 +81,6 @@ struct kiwmi_request_resize_event {
}; };
void view_close(struct kiwmi_view *view); 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); pid_t view_get_pid(struct kiwmi_view *view);
void view_get_size(struct kiwmi_view *view, uint32_t *width, uint32_t *height); void view_get_size(struct kiwmi_view *view, uint32_t *width, uint32_t *height);
const char *view_get_app_id(struct kiwmi_view *view); const char *view_get_app_id(struct kiwmi_view *view);
@ -143,21 +89,10 @@ 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);
struct wlr_surface *view_surface_at( void view_set_hidden(struct kiwmi_view *view, bool hidden);
struct kiwmi_view *view,
double sx,
double sy,
double *sub_x,
double *sub_y);
void view_focus(struct kiwmi_view *view); void view_focus(struct kiwmi_view *view);
struct kiwmi_view *view_at( struct kiwmi_view *view_at(struct kiwmi_desktop *desktop, double lx, double ly);
struct kiwmi_desktop *desktop,
double lx,
double ly,
struct wlr_surface **surface,
double *sx,
double *sy);
void view_move(struct kiwmi_view *view); void view_move(struct kiwmi_view *view);
void view_resize(struct kiwmi_view *view, uint32_t edges); void view_resize(struct kiwmi_view *view, uint32_t edges);
struct kiwmi_view *view_create( struct kiwmi_view *view_create(
@ -165,20 +100,4 @@ struct kiwmi_view *view_create(
enum kiwmi_view_type type, enum kiwmi_view_type type,
const struct kiwmi_view_impl *impl); 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 */ #endif /* KIWMI_DESKTOP_VIEW_H */

View file

@ -1,16 +0,0 @@
/* 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_LUAK_KIWMI_RENDERER_H
#define KIWMI_LUAK_KIWMI_RENDERER_H
#include <lua.h>
int luaK_kiwmi_renderer_new(lua_State *L);
int luaK_kiwmi_renderer_register(lua_State *L);
#endif /* KIWMI_LUAK_KIWMI_RENDERER_H */

View file

@ -17,16 +17,21 @@
#include <wlr/types/wlr_export_dmabuf_v1.h> #include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_presentation_time.h>
#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/desktop_surface.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"
#include "input/input.h" #include "input/input.h"
#include "input/seat.h"
#include "server.h" #include "server.h"
bool bool
@ -44,10 +49,28 @@ desktop_init(struct kiwmi_desktop *desktop)
wlr_xdg_output_manager_v1_create( wlr_xdg_output_manager_v1_create(
server->wl_display, desktop->output_layout); server->wl_display, desktop->output_layout);
desktop->bg_color[0] = 0.1f; desktop->scene = wlr_scene_create();
desktop->bg_color[1] = 0.1f; if (!desktop->scene) {
desktop->bg_color[2] = 0.1f; wlr_log(WLR_ERROR, "failed to create scene");
desktop->bg_color[3] = 1.0f; 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);
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 = 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;
@ -75,6 +98,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 +114,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 *
@ -100,19 +129,14 @@ desktop_active_output(struct kiwmi_server *server)
return output; return output;
} }
// 2. focused view center // 2. focused view
if (!wl_list_empty(&server->desktop.views)) { struct kiwmi_view *focused_view = server->input.seat->focused_view;
struct kiwmi_view *view; if (focused_view) {
wl_list_for_each (view, &server->desktop.views, link) { output = desktop_surface_get_output(&focused_view->desktop_surface);
break; // get first element of list
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 // 3. cursor

View file

@ -0,0 +1,87 @@
/* 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/desktop_surface.h"
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xdg_shell.h>
#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);
}

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,12 +26,17 @@ 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);
wl_list_remove(&layer->link); 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);
arrange_layers(layer->output); if (layer->output != NULL) {
wl_list_remove(&layer->link);
arrange_layers(layer->output);
}
free(layer); free(layer);
} }
@ -40,25 +47,21 @@ 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); arrange_layers(output);
} }
} }
@ -67,7 +70,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);
output_damage(layer->output); 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);
} }
static void static void
@ -75,7 +81,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);
output_damage(layer->output); 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);
} }
static void static void
@ -241,7 +251,14 @@ arrange_layer(
continue; continue;
} }
layer->geom = arranged_area; wlr_scene_node_set_position(
&layer->desktop_surface.tree->node,
arranged_area.x,
arranged_area.y);
wlr_scene_node_set_position(
&layer->desktop_surface.popups_tree->node,
arranged_area.x,
arranged_area.y);
apply_exclusive( apply_exclusive(
usable_area, usable_area,
@ -343,36 +360,18 @@ arrange_layers(struct kiwmi_output *output)
seat_focus_layer(seat, topmost); seat_focus_layer(seat, topmost);
} }
struct kiwmi_layer * static struct kiwmi_output *
layer_at( layer_desktop_surface_get_output(struct kiwmi_desktop_surface *desktop_surface)
struct wl_list *layers,
struct wlr_surface **surface,
double ox,
double oy,
double *sx,
double *sy)
{ {
struct kiwmi_layer *layer; struct kiwmi_layer *layer =
wl_list_for_each_reverse (layer, layers, link) { wl_container_of(desktop_surface, layer, desktop_surface);
double layer_sx = ox - layer->geom.x; return layer->output;
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 const struct kiwmi_desktop_surface_impl layer_desktop_surface_impl = {
.get_output = layer_desktop_surface_get_output,
};
void void
layer_shell_new_surface_notify(struct wl_listener *listener, void *data) layer_shell_new_surface_notify(struct wl_listener *listener, void *data)
{ {
@ -413,6 +412,9 @@ 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->desktop_surface.impl = &layer_desktop_surface_impl;
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);
@ -425,10 +427,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

@ -18,6 +18,7 @@
#include <wlr/types/wlr_matrix.h> #include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.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_surface.h> #include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
@ -30,216 +31,24 @@
#include "input/pointer.h" #include "input/pointer.h"
#include "server.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 static void
output_frame_notify(struct wl_listener *listener, void *data) output_frame_notify(struct wl_listener *listener, void *data)
{ {
struct kiwmi_output *output = wl_container_of(listener, output, frame); struct kiwmi_output *output = wl_container_of(listener, output, frame);
struct wlr_output *wlr_output = data; 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; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_output_send_frame_done(scene_output, &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);
} }
static void static void
@ -250,7 +59,6 @@ output_commit_notify(struct wl_listener *listener, void *data)
if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) { if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) {
arrange_layers(output); arrange_layers(output);
output_damage(output);
wl_signal_emit(&output->events.resize, output); wl_signal_emit(&output->events.resize, output);
} }
@ -261,13 +69,32 @@ output_destroy_notify(struct wl_listener *listener, void *UNUSED(data))
{ {
struct kiwmi_output *output = wl_container_of(listener, output, destroy); 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->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);
} }
wl_signal_emit(&output->events.destroy, output);
wl_list_remove(&output->link); wl_list_remove(&output->link);
wl_list_remove(&output->frame.link); wl_list_remove(&output->frame.link);
wl_list_remove(&output->commit.link); wl_list_remove(&output->commit.link);
@ -285,7 +112,6 @@ output_mode_notify(struct wl_listener *listener, void *UNUSED(data))
struct kiwmi_output *output = wl_container_of(listener, output, mode); struct kiwmi_output *output = wl_container_of(listener, output, mode);
arrange_layers(output); arrange_layers(output);
output_damage(output);
wl_signal_emit(&output->events.resize, output); wl_signal_emit(&output->events.resize, output);
} }
@ -316,8 +142,6 @@ output_create(struct wlr_output *wlr_output, struct kiwmi_desktop *desktop)
output->mode.notify = output_mode_notify; output->mode.notify = output_mode_notify;
wl_signal_add(&wlr_output->events.mode, &output->mode); wl_signal_add(&wlr_output->events.mode, &output->mode);
output_damage(output);
return output; return output;
} }
@ -369,20 +193,51 @@ 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);
} }
void void
output_damage(struct kiwmi_output *output) output_layout_change_notify(struct wl_listener *listener, void *UNUSED(data))
{ {
output->damaged = 2; 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);
}
}
}
} }

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

@ -0,0 +1,119 @@
/* 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_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
#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 *
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;
}
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,
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;
}
}
popup_unconstrain(popup, desktop_surface);
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;
}

33
kiwmi/desktop/stratum.c Normal file
View file

@ -0,0 +1,33 @@
/* 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 <stdint.h>
#include <wlr/util/log.h>
#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;
}
}

View file

@ -8,9 +8,11 @@
#include "desktop/view.h" #include "desktop/view.h"
#include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_scene.h>
#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"
@ -23,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 pid_t
view_get_pid(struct kiwmi_view *view) view_get_pid(struct kiwmi_view *view)
{ {
@ -84,42 +75,21 @@ view_set_size(struct kiwmi_view *view, uint32_t width, uint32_t height)
{ {
if (view->impl->set_size) { if (view->impl->set_size) {
view->impl->set_size(view, width, height); 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);
}
}
struct kiwmi_output *output;
wl_list_for_each (output, &view->desktop->outputs, link) {
output_damage(output);
}
} }
} }
void void
view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y) view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y)
{ {
view->x = x; wlr_scene_node_set_position(&view->desktop_surface.tree->node, x, y);
view->y = y; wlr_scene_node_set_position(&view->desktop_surface.popups_tree->node, x, y);
struct kiwmi_view_child *child; int lx, ly; // unused
wl_list_for_each (child, &view->children, link) { // If it is enabled (as well as all its parents)
if (child->impl && child->impl->reconfigure) { if (wlr_scene_node_coords(&view->desktop_surface.tree->node, &lx, &ly)) {
child->impl->reconfigure(child); 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);
struct kiwmi_output *output;
wl_list_for_each (output, &desktop->outputs, link) {
output_damage(output);
} }
} }
@ -131,69 +101,39 @@ view_set_tiled(struct kiwmi_view *view, enum wlr_edges edges)
} }
} }
struct wlr_surface * void
view_surface_at( view_set_hidden(struct kiwmi_view *view, bool hidden)
struct kiwmi_view *view,
double sx,
double sy,
double *sub_x,
double *sub_y)
{ {
if (view->impl->surface_at) { if (!view->mapped) {
return view->impl->surface_at(view, sx, sy, sub_x, sub_y); return;
} }
return NULL; wlr_scene_node_set_enabled(&view->desktop_surface.tree->node, !hidden);
} wlr_scene_node_set_enabled(
&view->desktop_surface.popups_tree->node, !hidden);
static bool struct kiwmi_server *server =
surface_at( wl_container_of(view->desktop, server, desktop);
struct kiwmi_view *view, struct kiwmi_seat *seat = server->input.seat;
struct wlr_surface **surface, if (seat->focused_view == view) {
double lx, seat->focused_view = NULL;
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 * struct kiwmi_view *
view_at( view_at(struct kiwmi_desktop *desktop, double lx, double ly)
struct kiwmi_desktop *desktop,
double lx,
double ly,
struct wlr_surface **surface,
double *sx,
double *sy)
{ {
struct kiwmi_view *view; struct kiwmi_desktop_surface *desktop_surface =
wl_list_for_each (view, &desktop->views, link) { desktop_surface_at(desktop, lx, ly);
if (view->hidden || !view->mapped) {
continue;
}
if (surface_at(view, surface, lx, ly, sx, sy)) { if (!desktop_surface
return view; || 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 static void
@ -220,17 +160,20 @@ view_begin_interactive(
cursor->cursor_mode = mode; cursor->cursor_mode = mode;
cursor->grabbed.view = view; 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) { if (mode == KIWMI_CURSOR_MOVE) {
cursor->grabbed.orig_x = cursor->cursor->x - view->x; cursor->grabbed.orig_x = cursor->cursor->x - view_lx;
cursor->grabbed.orig_y = cursor->cursor->y - view->y; cursor->grabbed.orig_y = cursor->cursor->y - view_ly;
} else { } else {
cursor->grabbed.orig_x = cursor->cursor->x; cursor->grabbed.orig_x = cursor->cursor->x;
cursor->grabbed.orig_y = cursor->cursor->y; cursor->grabbed.orig_y = cursor->cursor->y;
cursor->grabbed.resize_edges = edges; cursor->grabbed.resize_edges = edges;
} }
cursor->grabbed.orig_geom.x = view->x; cursor->grabbed.orig_geom.x = view_lx;
cursor->grabbed.orig_geom.y = view->y; cursor->grabbed.orig_geom.y = view_ly;
cursor->grabbed.orig_geom.width = width; cursor->grabbed.orig_geom.width = width;
cursor->grabbed.orig_geom.height = height; cursor->grabbed.orig_geom.height = height;
} }
@ -247,31 +190,37 @@ view_resize(struct kiwmi_view *view, uint32_t edges)
view_begin_interactive(view, KIWMI_CURSOR_RESIZE, edges); view_begin_interactive(view, KIWMI_CURSOR_RESIZE, edges);
} }
/** static struct kiwmi_output *
* Creates a kiwmi_view_child for each subsurface of either the 'child' or the view_desktop_surface_get_output(struct kiwmi_desktop_surface *desktop_surface)
* '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 = struct kiwmi_view *view =
child ? child->wlr_surface : view->wlr_surface; wl_container_of(desktop_surface, view, desktop_surface);
if (!surface) {
wlr_log(WLR_ERROR, "Attempting to init_subsurfaces without a surface"); int lx, ly;
return; 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;
} }
struct wlr_subsurface *subsurface; // Retry top-left corner
wl_list_for_each ( output = wlr_output_layout_output_at(view->desktop->output_layout, lx, ly);
subsurface, &surface->current.subsurfaces_below, current.link) { if (output) {
view_child_subsurface_create(child, view, subsurface); return (struct kiwmi_output *)output->data;
}
wl_list_for_each (
subsurface, &surface->current.subsurfaces_above, current.link) {
view_child_subsurface_create(child, view, subsurface);
} }
return NULL;
} }
static const struct kiwmi_desktop_surface_impl view_desktop_surface_impl = {
.get_output = view_desktop_surface_get_output,
};
struct kiwmi_view * struct kiwmi_view *
view_create( view_create(
struct kiwmi_desktop *desktop, struct kiwmi_desktop *desktop,
@ -288,13 +237,10 @@ view_create(
view->type = type; view->type = type;
view->impl = impl; view->impl = impl;
view->mapped = false; view->mapped = false;
view->hidden = true;
view->decoration = NULL; view->decoration = NULL;
view->x = 0; view->desktop_surface.type = KIWMI_DESKTOP_SURFACE_VIEW;
view->y = 0; view->desktop_surface.impl = &view_desktop_surface_impl;
wl_list_init(&view->children);
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);
@ -302,202 +248,17 @@ view_create(
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;
} }
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_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;
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(struct wl_listener *listener, void *UNUSED(data))
{
struct kiwmi_view_child *child = wl_container_of(listener, child, commit);
if (view_child_is_mapped(child)) {
view_child_damage(child);
}
}
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;
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;
}
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;
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);
child->extension_destroy.notify =
view_child_subsurface_extension_destroy_notify;
wl_signal_add(&subsurface->events.destroy, &child->extension_destroy);
return child;
}

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,168 +19,19 @@
#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"
#include "input/seat.h" #include "input/seat.h"
#include "server.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_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)
{
if (popup->type != KIWMI_VIEW_CHILD_XDG_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 = {
.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;
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);
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);
popup_unconstrain(child);
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 static void
xdg_surface_map_notify(struct wl_listener *listener, void *UNUSED(data)) xdg_surface_map_notify(struct wl_listener *listener, void *UNUSED(data))
{ {
struct kiwmi_view *view = wl_container_of(listener, view, map); struct kiwmi_view *view = wl_container_of(listener, view, map);
view->mapped = true; 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); wl_signal_emit(&view->desktop->events.view_map, view);
} }
@ -188,16 +40,25 @@ xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data))
{ {
struct kiwmi_view *view = wl_container_of(listener, view, unmap); struct kiwmi_view *view = wl_container_of(listener, view, unmap);
if (view->mapped) { view->mapped = false;
view->mapped = false;
struct kiwmi_output *output; int lx, ly; // unused
wl_list_for_each (output, &view->desktop->outputs, link) { if (wlr_scene_node_coords(&view->desktop_surface.tree->node, &lx, &ly)) {
output_damage(output); 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_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);
} }
wl_signal_emit(&view->events.unmap, view);
} }
static void static void
@ -205,52 +66,35 @@ xdg_surface_commit_notify(struct wl_listener *listener, void *UNUSED(data))
{ {
struct kiwmi_view *view = wl_container_of(listener, view, commit); struct kiwmi_view *view = wl_container_of(listener, view, commit);
struct kiwmi_desktop *desktop = view->desktop; struct wlr_box geom;
struct kiwmi_server *server = wl_container_of(desktop, server, desktop); wlr_xdg_surface_get_geometry(view->xdg_surface, &geom);
struct kiwmi_cursor *cursor = server->input.cursor;
cursor_refresh_focus(cursor, NULL, NULL, NULL);
if (pixman_region32_not_empty(&view->wlr_surface->buffer_damage)) { if (memcmp(&view->geom, &geom, sizeof(geom)) != 0) {
struct kiwmi_output *output; memcpy(&view->geom, &geom, sizeof(geom));
wl_list_for_each (output, &desktop->outputs, link) {
output_damage(output); 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);
} }
wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom);
} }
static void 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);
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) { wlr_scene_node_destroy(&view->desktop_surface.tree->node);
seat->focused_view = NULL; wlr_scene_node_destroy(&view->desktop_surface.popups_tree->node);
}
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) { if (view->decoration) {
view->decoration->view = NULL; view->decoration->view = NULL;
} }
wl_list_remove(&view->link); wl_list_remove(&view->link);
wl_list_remove(&view->children);
wl_list_remove(&view->map.link); wl_list_remove(&view->map.link);
wl_list_remove(&view->unmap.link); wl_list_remove(&view->unmap.link);
wl_list_remove(&view->commit.link); wl_list_remove(&view->commit.link);
wl_list_remove(&view->destroy.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_move.link);
wl_list_remove(&view->request_resize.link); wl_list_remove(&view->request_resize.link);
@ -293,15 +137,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 static pid_t
xdg_shell_view_get_pid(struct kiwmi_view *view) xdg_shell_view_get_pid(struct kiwmi_view *view)
{ {
@ -349,26 +184,13 @@ xdg_shell_view_set_tiled(struct kiwmi_view *view, enum wlr_edges edges)
wlr_xdg_toplevel_set_tiled(view->xdg_surface, 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 = { static const struct kiwmi_view_impl xdg_shell_view_impl = {
.close = xdg_shell_view_close, .close = xdg_shell_view_close,
.for_each_surface = xdg_shell_view_for_each_surface, .get_pid = xdg_shell_view_get_pid,
.get_pid = xdg_shell_view_get_pid, .get_string_prop = xdg_shell_view_get_string_prop,
.get_string_prop = xdg_shell_view_get_string_prop, .set_activated = xdg_shell_view_set_activated,
.set_activated = xdg_shell_view_set_activated, .set_size = xdg_shell_view_set_size,
.set_size = xdg_shell_view_set_size, .set_tiled = xdg_shell_view_set_tiled,
.set_tiled = xdg_shell_view_set_tiled,
.surface_at = xdg_shell_view_surface_at,
}; };
void void
@ -380,6 +202,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 +233,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);
@ -414,13 +248,6 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data)
view->destroy.notify = xdg_surface_destroy_notify; view->destroy.notify = xdg_surface_destroy_notify;
wl_signal_add(&xdg_surface->events.destroy, &view->destroy); 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; view->request_move.notify = xdg_toplevel_request_move_notify;
wl_signal_add( wl_signal_add(
&xdg_surface->toplevel->events.request_move, &view->request_move); &xdg_surface->toplevel->events.request_move, &view->request_move);
@ -429,7 +256,7 @@ xdg_shell_new_surface_notify(struct wl_listener *listener, void *data)
wl_signal_add( wl_signal_add(
&xdg_surface->toplevel->events.request_resize, &view->request_resize); &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); wl_list_insert(&desktop->views, &view->link);
} }

View file

@ -14,6 +14,7 @@
#include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_pointer.h> #include <wlr/types/wlr_pointer.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_seat.h> #include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
@ -284,72 +285,24 @@ cursor_refresh_focus(
struct kiwmi_desktop *desktop = &cursor->server->desktop; struct kiwmi_desktop *desktop = &cursor->server->desktop;
struct wlr_seat *seat = cursor->server->input.seat->seat; 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; struct wlr_surface *surface = NULL;
double sx; double sx;
double sy; double sy;
struct kiwmi_layer *layer = layer_at( struct wlr_scene_node *node_at = wlr_scene_node_at(
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &desktop->scene->node, cursor->cursor->x, cursor->cursor->y, &sx, &sy);
&surface,
ox,
oy,
&sx,
&sy);
struct kiwmi_view *view;
if (!layer) { if (node_at && node_at->type == WLR_SCENE_NODE_SURFACE) {
layer = layer_at( struct wlr_scene_surface *scene_surface =
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], wlr_scene_surface_from_node(node_at);
&surface, surface = scene_surface->surface;
ox,
oy,
&sx,
&sy);
}
if (!layer) { if (surface != seat->pointer_state.focused_surface) {
view = view_at( wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
desktop, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); }
} } else {
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) {
wlr_xcursor_manager_set_cursor_image( wlr_xcursor_manager_set_cursor_image(
cursor->xcursor_manager, "left_ptr", cursor->cursor); 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); wlr_seat_pointer_clear_focus(seat);
} }

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;
@ -112,14 +116,6 @@ request_set_cursor_notify(struct wl_listener *listener, void *data)
return; 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( wlr_cursor_set_surface(
cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y); cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y);
} }

View file

@ -73,17 +73,8 @@ l_kiwmi_cursor_view_at_pos(lua_State *L)
struct kiwmi_cursor *cursor = obj->object; struct kiwmi_cursor *cursor = obj->object;
struct kiwmi_server *server = cursor->server; struct kiwmi_server *server = cursor->server;
struct wlr_surface *surface; struct kiwmi_view *view =
double sx; view_at(&server->desktop, cursor->cursor->x, cursor->cursor->y);
double sy;
struct kiwmi_view *view = view_at(
&server->desktop,
cursor->cursor->x,
cursor->cursor->y,
&surface,
&sx,
&sy);
if (view) { if (view) {
lua_pushcfunction(L, luaK_kiwmi_view_new); lua_pushcfunction(L, luaK_kiwmi_view_new);

View file

@ -98,23 +98,6 @@ l_kiwmi_output_pos(lua_State *L)
return 2; 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 static int
l_kiwmi_output_size(lua_State *L) l_kiwmi_output_size(lua_State *L)
{ {
@ -168,7 +151,6 @@ static const luaL_Reg kiwmi_output_methods[] = {
{"name", l_kiwmi_output_name}, {"name", l_kiwmi_output_name},
{"on", luaK_callback_register_dispatch}, {"on", luaK_callback_register_dispatch},
{"pos", l_kiwmi_output_pos}, {"pos", l_kiwmi_output_pos},
{"redraw", l_kiwmi_output_redraw},
{"size", l_kiwmi_output_size}, {"size", l_kiwmi_output_size},
{"usable_area", l_kiwmi_output_usable_area}, {"usable_area", l_kiwmi_output_usable_area},
{NULL, NULL}, {NULL, NULL},

View file

@ -1,100 +0,0 @@
/* 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 "luak/kiwmi_renderer.h"
#include <stdlib.h>
#include <string.h>
#include <lauxlib.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_output.h>
#include <wlr/util/log.h>
#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;
}

View file

@ -65,10 +65,12 @@ l_kiwmi_server_bg_color(lua_State *L)
return luaL_argerror(L, 2, "not a valid color"); return luaL_argerror(L, 2, "not a valid color");
} }
server->desktop.bg_color[0] = color[0]; // Ignore alpha (color channels are already premultiplied)
server->desktop.bg_color[1] = color[1]; color[3] = 1.0f;
server->desktop.bg_color[2] = color[2];
// ignore alpha 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;
} }
@ -308,12 +310,7 @@ l_kiwmi_server_view_at(lua_State *L)
double lx = lua_tonumber(L, 2); double lx = lua_tonumber(L, 2);
double ly = lua_tonumber(L, 3); double ly = lua_tonumber(L, 3);
struct wlr_surface *surface; struct kiwmi_view *view = view_at(&server->desktop, lx, ly);
double sx;
double sy;
struct kiwmi_view *view =
view_at(&server->desktop, lx, ly, &surface, &sx, &sy);
if (view) { if (view) {
lua_pushcfunction(L, luaK_kiwmi_view_new); lua_pushcfunction(L, luaK_kiwmi_view_new);

View file

@ -15,13 +15,13 @@
#include <wlr/util/edges.h> #include <wlr/util/edges.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "desktop/desktop_surface.h"
#include "desktop/output.h" #include "desktop/output.h"
#include "desktop/view.h" #include "desktop/view.h"
#include "desktop/xdg_shell.h" #include "desktop/xdg_shell.h"
#include "input/seat.h" #include "input/seat.h"
#include "luak/kiwmi_lua_callback.h" #include "luak/kiwmi_lua_callback.h"
#include "luak/kiwmi_output.h" #include "luak/kiwmi_output.h"
#include "luak/kiwmi_renderer.h"
#include "luak/lua_compat.h" #include "luak/lua_compat.h"
#include "server.h" #include "server.h"
@ -121,7 +121,11 @@ l_kiwmi_view_hidden(lua_State *L)
struct kiwmi_view *view = obj->object; 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; return 1;
} }
@ -138,7 +142,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;
} }
@ -276,8 +280,11 @@ l_kiwmi_view_pos(lua_State *L)
struct kiwmi_view *view = obj->object; struct kiwmi_view *view = obj->object;
lua_pushinteger(L, view->x); int lx, ly;
lua_pushinteger(L, view->y); desktop_surface_get_pos(&view->desktop_surface, &lx, &ly);
lua_pushinteger(L, lx);
lua_pushinteger(L, ly);
return 2; return 2;
} }
@ -316,7 +323,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;
} }
@ -471,65 +478,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 static void
kiwmi_view_on_request_move_notify(struct wl_listener *listener, void *data) kiwmi_view_on_request_move_notify(struct wl_listener *listener, void *data)
{ {
@ -644,62 +592,16 @@ l_kiwmi_view_on_destroy(lua_State *L)
} }
static int 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 = // noop
*(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;
}
return 0; return 0;
} }
static int 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 = // noop
*(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;
}
return 0; return 0;
} }

View file

@ -18,7 +18,6 @@
#include "luak/kiwmi_keyboard.h" #include "luak/kiwmi_keyboard.h"
#include "luak/kiwmi_lua_callback.h" #include "luak/kiwmi_lua_callback.h"
#include "luak/kiwmi_output.h" #include "luak/kiwmi_output.h"
#include "luak/kiwmi_renderer.h"
#include "luak/kiwmi_server.h" #include "luak/kiwmi_server.h"
#include "luak/kiwmi_view.h" #include "luak/kiwmi_view.h"
@ -220,8 +219,6 @@ luaK_create(struct kiwmi_server *server)
error |= lua_pcall(L, 0, 0, 0); error |= lua_pcall(L, 0, 0, 0);
lua_pushcfunction(L, luaK_kiwmi_output_register); lua_pushcfunction(L, luaK_kiwmi_output_register);
error |= lua_pcall(L, 0, 0, 0); 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); lua_pushcfunction(L, luaK_kiwmi_server_register);
error |= lua_pcall(L, 0, 0, 0); error |= lua_pcall(L, 0, 0, 0);
lua_pushcfunction(L, luaK_kiwmi_view_register); lua_pushcfunction(L, luaK_kiwmi_view_register);

View file

@ -3,8 +3,11 @@ kiwmi_sources = files(
'server.c', 'server.c',
'color.c', 'color.c',
'desktop/desktop.c', 'desktop/desktop.c',
'desktop/desktop_surface.c',
'desktop/layer_shell.c', 'desktop/layer_shell.c',
'desktop/output.c', 'desktop/output.c',
'desktop/popup.c',
'desktop/stratum.c',
'desktop/view.c', 'desktop/view.c',
'desktop/xdg_shell.c', 'desktop/xdg_shell.c',
'input/cursor.c', 'input/cursor.c',
@ -17,7 +20,6 @@ kiwmi_sources = files(
'luak/kiwmi_keyboard.c', 'luak/kiwmi_keyboard.c',
'luak/kiwmi_lua_callback.c', 'luak/kiwmi_lua_callback.c',
'luak/kiwmi_output.c', 'luak/kiwmi_output.c',
'luak/kiwmi_renderer.c',
'luak/kiwmi_server.c', 'luak/kiwmi_server.c',
'luak/kiwmi_view.c', 'luak/kiwmi_view.c',
'luak/lua_compat.c', 'luak/lua_compat.c',

View file

@ -20,6 +20,7 @@
#include <wlr/types/wlr_gamma_control_v1.h> #include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_primary_selection_v1.h> #include <wlr/types/wlr_primary_selection_v1.h>
#include <wlr/types/wlr_screencopy_v1.h> #include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_viewporter.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "luak/luak.h" #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_data_control_manager_v1_create(server->wl_display);
wlr_gamma_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_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); server->socket = wl_display_add_socket_auto(server->wl_display);
if (!server->socket) { if (!server->socket) {

View file

@ -240,10 +240,6 @@ Used to register event listeners.
Get the position of the output. Get the position of the output.
Returns two parameters: `x` and `y`. 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() #### output:size()
Get the size of the output. 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. 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`. 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 ## kiwmi_view
Represents a view (a window in kiwmi terms). Represents a view (a window in kiwmi terms).
@ -373,17 +358,11 @@ Callback receives the view.
#### post_render #### post_render
The view finished being rendered. This is a no-op event. Temporarily preserved only to make config migration easier.
Callback receives a table with the `view`, the `renderer` and the `output`.
This event occurs once per output the view might be drawn on.
#### pre_render #### pre_render
The view is about to be rendered. This is a no-op event. Temporarily preserved only to make config migration easier.
Callback receives a table with the `view`, the `renderer` and the `output`.
This event occurs once per output the view might be drawn on.
#### request_move #### request_move