]> git.mdlowis.com Git - proto/labwc.git/commitdiff
xdg: center small fullscreen views and add black background fill
authorJohn Lindgren <john@jlindgren.net>
Mon, 1 Dec 2025 20:13:07 +0000 (15:13 -0500)
committerHiroaki Yamamoto <hrak1529@gmail.com>
Tue, 2 Dec 2025 05:57:41 +0000 (14:57 +0900)
include/view.h
src/view.c
src/xdg.c

index d8c67e4284f32b60165701ca236c4f9b1a560295..2f8aac85f6a0c50e51a968c852108fd12af29426 100644 (file)
@@ -296,6 +296,9 @@ struct xdg_toplevel_view {
        struct view base;
        struct wlr_xdg_surface *xdg_surface;
 
+       /* Optional black background fill behind fullscreen view */
+       struct wlr_scene_rect *fullscreen_bg;
+
        /* Events unique to xdg-toplevel views */
        struct wl_listener set_app_id;
        struct wl_listener request_show_window_menu;
index cf0c521c1ceb4b311eb679483bf1db11594ebaf7..bd8f0a64d90983cf0a9d8765d6c5404841c9113a 100644 (file)
@@ -1699,6 +1699,12 @@ view_set_fullscreen(struct view *view, bool fullscreen)
                view_apply_special_geometry(view);
        }
        output_set_has_fullscreen_view(view->output, view->fullscreen);
+       /*
+        * Entering/leaving fullscreen might result in a different
+        * scene node ending up under the cursor even if view_moved()
+        * isn't called. Update cursor focus explicitly for that case.
+        */
+       cursor_update_focus(view->server);
 }
 
 static bool
index 5949638e6536c6314f62417005dd13f4026b3cde..b7bae3796da98bc1965ffcd8dc7b7c3e0f81850e 100644 (file)
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -10,6 +10,7 @@
 #include <wlr/types/wlr_xdg_toplevel_icon_v1.h>
 #include "buffer.h"
 #include "common/array.h"
+#include "common/box.h"
 #include "common/macros.h"
 #include "common/mem.h"
 #include "config/rcxml.h"
@@ -129,6 +130,58 @@ do_late_positioning(struct view *view)
        }
 }
 
+static void
+disable_fullscreen_bg(struct view *view)
+{
+       struct xdg_toplevel_view *xdg_view = xdg_toplevel_view_from_view(view);
+       if (xdg_view->fullscreen_bg) {
+               wlr_scene_node_set_enabled(&xdg_view->fullscreen_bg->node, false);
+       }
+}
+
+/*
+ * Centers any fullscreen view smaller than the full output size.
+ * This should be called immediately before view_moved().
+ */
+static void
+center_fullscreen_if_needed(struct view *view)
+{
+       if (!view->fullscreen || !output_is_usable(view->output)) {
+               disable_fullscreen_bg(view);
+               return;
+       }
+
+       struct wlr_box output_box = {0};
+       wlr_output_layout_get_box(view->server->output_layout,
+               view->output->wlr_output, &output_box);
+       box_center(view->current.width, view->current.height, &output_box,
+               &output_box, &view->current.x, &view->current.y);
+
+       /* Reset pending x/y to computed position also */
+       view->pending.x = view->current.x;
+       view->pending.y = view->current.y;
+
+       if (view->current.width >= output_box.width
+                       && view->current.width >= output_box.height) {
+               disable_fullscreen_bg(view);
+               return;
+       }
+
+       struct xdg_toplevel_view *xdg_view = xdg_toplevel_view_from_view(view);
+       if (!xdg_view->fullscreen_bg) {
+               const float black[4] = {0, 0, 0, 1};
+               xdg_view->fullscreen_bg =
+                       wlr_scene_rect_create(view->scene_tree, 0, 0, black);
+               wlr_scene_node_lower_to_bottom(&xdg_view->fullscreen_bg->node);
+       }
+
+       wlr_scene_node_set_position(&xdg_view->fullscreen_bg->node,
+               output_box.x - view->current.x, output_box.y - view->current.y);
+       wlr_scene_rect_set_size(xdg_view->fullscreen_bg,
+               output_box.width, output_box.height);
+       wlr_scene_node_set_enabled(&xdg_view->fullscreen_bg->node, true);
+}
+
 /* TODO: reorder so this forward declaration isn't needed */
 static void set_pending_configure_serial(struct view *view, uint32_t serial);
 
@@ -238,6 +291,7 @@ handle_commit(struct wl_listener *listener, void *data)
 
        if (update_required) {
                view_impl_apply_geometry(view, size.width, size.height);
+               center_fullscreen_if_needed(view);
                view_moved(view);
 
                /*
@@ -336,9 +390,11 @@ handle_configure_timeout(void *data)
                }
                view->current.x = view->pending.x;
                view->current.y = view->pending.y;
-               view_moved(view);
        }
 
+       center_fullscreen_if_needed(view);
+       view_moved(view);
+
        /* Re-sync pending view with current state */
        snap_constraints_update(view);
        view->pending = view->current;
@@ -546,6 +602,12 @@ xdg_toplevel_view_configure(struct view *view, struct wlr_box geo)
        } else if (view->pending_configure_serial == 0) {
                view->current.x = geo.x;
                view->current.y = geo.y;
+               /*
+                * It's a bit difficult to think of a corner case where
+                * center_fullscreen_if_needed() would actually be needed
+                * here, but including it anyway for completeness.
+                */
+               center_fullscreen_if_needed(view);
                view_moved(view);
        }
 }
@@ -664,6 +726,10 @@ xdg_toplevel_view_set_fullscreen(struct view *view, bool fullscreen)
        if (serial > 0) {
                set_pending_configure_serial(view, serial);
        }
+       /* Disable background fill immediately on leaving fullscreen */
+       if (!fullscreen) {
+               disable_fullscreen_bg(view);
+       }
 }
 
 static void
@@ -786,6 +852,9 @@ handle_map(struct wl_listener *listener, void *data)
                        set_initial_position(view);
                }
 
+               /* Disable background fill at map (paranoid?) */
+               disable_fullscreen_bg(view);
+
                /*
                 * Set initial "current" position directly before
                 * calling view_moved() to reduce flicker