git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commit55dbd7c2c310a4f8cf48978224be50d4149241b8
parent3c7731b342
authorLucas Galante <[email protected]>
date2026-07-16 20:14
feat: split the implicit CSD title-bar move into an opt-out hook

The standard CSD reserved a title-bar strip (y in [8,32)) as a
drag-to-move handle unconditionally whenever standard_csd was on. Gate it
behind a new Application::csd_titlebar_move() (default true, so existing
apps are unchanged). A window with no title bar can return false and then
be moved only via explicitly-declared is_movable_backplate_at regions —
nothing is implicitly draggable.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/backend/window_runner.rs | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/backend/window_runner.rs b/src/backend/window_runner.rs
index 07d36ed..9865c8e 100644
--- a/src/backend/window_runner.rs
+++ b/src/backend/window_runner.rs
@@ -1657,6 +1657,16 @@ pub trait Application: Sized + 'static {
         true
     }
 
+    /// Whether the standard CSD reserves an implicit title-bar strip (`y` in `[8, 32)`) as a
+    /// drag-to-move handle. Separate from [`standard_csd`](Application::standard_csd), which
+    /// also gates the resize borders. Return `false` for a window that has no title bar and
+    /// should only be moved via explicitly-declared handles
+    /// ([`is_movable_backplate_at`](Application::is_movable_backplate_at)) — nothing is then
+    /// implicitly draggable. Only consulted when `standard_csd()` is on.
+    fn csd_titlebar_move(&self) -> bool {
+        true
+    }
+
     /// Override the pointer cursor at (x, y). `None` falls back to the
     /// runner's standard CSD edge cursors (or `Default` when
     /// [`standard_csd`](Application::standard_csd) is off).
@@ -2391,7 +2401,10 @@ impl<A: Application> PointerHandler for EngineState<A> {
                                 is_widget = true;
                             }
                         }
-                        if !is_widget && ly >= border && ly < 32.0 && lx < self.logical_width - 70.0 {
+                        if !is_widget
+                            && self.inner.as_ref().unwrap().csd_titlebar_move()
+                            && ly >= border && ly < 32.0 && lx < self.logical_width - 70.0
+                        {
                             should_move = true;
                         } else if self.inner.as_ref().unwrap().is_movable_backplate_at(lx, ly) {
                             should_move = true;