diff options
author | William McKinnon <[email protected]> | 2024-10-25 11:14:37 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2024-10-25 11:14:37 -0400 |
commit | d998099612f0397234910ce753859ee127ec5b45 (patch) | |
tree | e60d699901f14054ea44718b1be8fcaf7dc9f244 /tinywl | |
parent | be5a78ac298f3b23c9955022ad35a18180a5894a (diff) |
feat: add shadow_node (#66)
---------
Co-authored-by: Erik Reider <[email protected]>
Diffstat (limited to 'tinywl')
-rw-r--r-- | tinywl/tinywl.c | 56 |
1 files changed, 45 insertions, 11 deletions
diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index c7dfa3a..973780a 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -6,7 +6,6 @@ #include <stdio.h> #include <time.h> #include <scenefx/render/fx_renderer/fx_renderer.h> -#include <scenefx/types/fx/shadow_data.h> #include <scenefx/types/wlr_scene.h> #include <unistd.h> #include <wayland-server-core.h> @@ -85,9 +84,11 @@ struct tinywl_toplevel { struct wl_list link; struct tinywl_server *server; struct wlr_xdg_toplevel *xdg_toplevel; + struct wlr_scene_tree *xdg_scene_tree; struct wlr_scene_tree *scene_tree; struct wl_listener map; struct wl_listener unmap; + struct wl_listener commit; struct wl_listener destroy; struct wl_listener request_move; struct wl_listener request_resize; @@ -96,7 +97,7 @@ struct tinywl_toplevel { float opacity; int corner_radius; - struct shadow_data shadow_data; + struct wlr_scene_shadow *shadow; }; struct tinywl_keyboard { @@ -583,13 +584,10 @@ static void output_configure_scene(struct wlr_scene_node *node, if (toplevel && xdg_surface && xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { - // TODO: Be able to set whole decoration_data instead of calling - // each individually? wlr_scene_buffer_set_opacity(buffer, toplevel->opacity); if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { wlr_scene_buffer_set_corner_radius(buffer, toplevel->corner_radius); - wlr_scene_buffer_set_shadow_data(buffer, toplevel->shadow_data); } } } else if (node->type == WLR_SCENE_NODE_TREE) { @@ -707,15 +705,30 @@ static void xdg_toplevel_map(struct wl_listener *listener, void *data) { /* Called when the surface is mapped, or ready to display on-screen. */ struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, map); + wlr_scene_node_set_enabled(&toplevel->scene_tree->node, true); + wl_list_insert(&toplevel->server->toplevels, &toplevel->link); - focus_toplevel(toplevel, toplevel->xdg_toplevel->base->surface); + struct wlr_surface *surface = toplevel->xdg_toplevel->base->surface; + + int blur_sigma = toplevel->shadow->blur_sigma; + struct wlr_box geometry; + wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geometry); + wlr_scene_shadow_set_size(toplevel->shadow, + geometry.width + blur_sigma * 2, + geometry.height + blur_sigma * 2); + + wlr_scene_node_set_position(&toplevel->shadow->node, -blur_sigma, -blur_sigma); + + focus_toplevel(toplevel, surface); } static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { /* Called when the surface is unmapped, and should no longer be shown. */ struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, unmap); + wlr_scene_node_set_enabled(&toplevel->scene_tree->node, false); + /* Reset the cursor mode if the grabbed toplevel was unmapped. */ if (toplevel == toplevel->server->grabbed_toplevel) { reset_cursor_mode(toplevel->server); @@ -724,18 +737,33 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { wl_list_remove(&toplevel->link); } +static void xdg_toplevel_commit(struct wl_listener *listener, void *data) { + struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, commit); + + struct wlr_box geometry; + wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geometry); + wlr_scene_subsurface_tree_set_clip(&toplevel->xdg_scene_tree->node, &geometry); + + int blur_sigma = toplevel->shadow->blur_sigma; + wlr_scene_shadow_set_size(toplevel->shadow, + geometry.width + blur_sigma * 2, geometry.height + blur_sigma * 2); +} + static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) { /* Called when the xdg_toplevel is destroyed. */ struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, destroy); wl_list_remove(&toplevel->map.link); wl_list_remove(&toplevel->unmap.link); + wl_list_remove(&toplevel->commit.link); wl_list_remove(&toplevel->destroy.link); wl_list_remove(&toplevel->request_move.link); wl_list_remove(&toplevel->request_resize.link); wl_list_remove(&toplevel->request_maximize.link); wl_list_remove(&toplevel->request_fullscreen.link); + wlr_scene_node_destroy(&toplevel->scene_tree->node); + free(toplevel); } @@ -847,23 +875,29 @@ static void server_new_xdg_surface(struct wl_listener *listener, void *data) { struct tinywl_toplevel *toplevel = calloc(1, sizeof(*toplevel)); toplevel->server = server; toplevel->xdg_toplevel = xdg_surface->toplevel; - toplevel->scene_tree = wlr_scene_xdg_surface_create( - &toplevel->server->scene->tree, toplevel->xdg_toplevel->base); + toplevel->scene_tree = wlr_scene_tree_create(&toplevel->server->scene->tree); + toplevel->xdg_scene_tree = wlr_scene_xdg_surface_create( + toplevel->scene_tree, toplevel->xdg_toplevel->base); toplevel->scene_tree->node.data = toplevel; xdg_surface->data = toplevel->scene_tree; /* Set the scene_nodes decoration data */ toplevel->opacity = 1; toplevel->corner_radius = 20; - toplevel->shadow_data = shadow_data_get_default(); - toplevel->shadow_data.enabled = true; - toplevel->shadow_data.color = (struct wlr_render_color) {1.0f, 0.0f, 0.0f, 1.0f}; + + float blur_sigma = 20.0f; + toplevel->shadow = wlr_scene_shadow_create(toplevel->scene_tree, + 0, 0, toplevel->corner_radius, blur_sigma, (float[4]){ 1.0f, 0.f, 0.f, 1.0f }); + // Lower the shadow below the XDG scene tree + wlr_scene_node_lower_to_bottom(&toplevel->shadow->node); /* Listen to the various events it can emit */ toplevel->map.notify = xdg_toplevel_map; wl_signal_add(&xdg_surface->surface->events.map, &toplevel->map); toplevel->unmap.notify = xdg_toplevel_unmap; wl_signal_add(&xdg_surface->surface->events.unmap, &toplevel->unmap); + toplevel->commit.notify = xdg_toplevel_commit; + wl_signal_add(&xdg_surface->surface->events.commit, &toplevel->commit); toplevel->destroy.notify = xdg_toplevel_destroy; wl_signal_add(&xdg_surface->events.destroy, &toplevel->destroy); |