git.lucas.co / cce-files
file manager
git clone https://git.lucas.co/cce-files.git

commitedb654e7ee45b968b5005bbbf8930fac147e7058
parent6ee3f6929b
authorLucas Galante <lsgalante12@gmail.com>
date2026-10-05 21:39
fix(osk): keep claiming an edited field on frames that replay the layout

The search and save-name boxes are painted only in rebuild_layout, and
display_list replays the cached frame otherwise, so a field claimed text
input on rebuild frames alone and the on-screen keyboard went away on the
next replayed frame. The rebuild now runs under
cce_ui::text_input::capture and its claim is made again every frame.
Repins cce-ui to 2e573c3 for capture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

 Cargo.lock  | 37 ++++++++++++++++++++++++++++++++++++-
 Cargo.toml  |  2 +-
 src/main.rs | 16 ++++++++++++++++
 3 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 90d609f..d644f81 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -489,7 +489,7 @@ dependencies = [
 [[package]]
 name = "cce-ui"
 version = "0.1.0"
-source = "git+https://github.com/lsgalante/cce-ui.git?rev=9afd4d8c634296572feaddc96ae7c7edd0582ce4#9afd4d8c634296572feaddc96ae7c7edd0582ce4"
+source = "git+https://github.com/lsgalante/cce-ui.git?rev=2e573c35b6826fff87ac216eba48b9cc3c5a3dac#2e573c35b6826fff87ac216eba48b9cc3c5a3dac"
 dependencies = [
  "ash",
  "bitflags 2.13.1",
@@ -497,12 +497,19 @@ dependencies = [
  "calloop",
  "calloop-wayland-source",
  "cosmic-text",
+ "cursor-icon",
+ "dispatch2",
  "glam",
  "gpu-allocator",
+ "js-sys",
  "kdl 4.7.1",
  "libc",
  "log",
  "naga",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
+ "objc2-quartz-core",
  "png 0.17.16",
  "raw-window-handle",
  "resvg",
@@ -510,10 +517,14 @@ dependencies = [
  "serde",
  "serde_json",
  "smithay-client-toolkit",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
  "wayland-backend",
  "wayland-client",
  "wayland-protocols 0.31.2",
  "wayland-scanner",
+ "web-sys",
+ "web-time",
  "xkeysym",
 ]
 
@@ -1745,7 +1756,9 @@ dependencies = [
  "bitflags 2.13.1",
  "block2",
  "objc2",
+ "objc2-core-foundation",
  "objc2-foundation",
+ "objc2-quartz-core",
 ]
 
 [[package]]
@@ -1776,6 +1789,18 @@ dependencies = [
  "objc2-core-foundation",
 ]
 
+[[package]]
+name = "objc2-quartz-core"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
+dependencies = [
+ "bitflags 2.13.1",
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-foundation",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.21.4"
@@ -3239,6 +3264,16 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "web-time"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "weezl"
 version = "0.1.12"
diff --git a/Cargo.toml b/Cargo.toml
index 966e37b..33cddbc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
 edition = "2024"
 
 [dependencies]
-cce-ui = { git = "https://github.com/lsgalante/cce-ui.git", rev = "9afd4d8c634296572feaddc96ae7c7edd0582ce4" }
+cce-ui = { git = "https://github.com/lsgalante/cce-ui.git", rev = "2e573c35b6826fff87ac216eba48b9cc3c5a3dac" }
 wayland-client = { version = "0.31", features = ["system"] }
 calloop = "0.13.0"
 chrono = "0.4.44"
diff --git a/src/main.rs b/src/main.rs
index bfe4c71..648880d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -469,6 +469,11 @@ struct FilesystemApp {
     texts: Vec<(String, f32, f32, f32, [f32; 4], Option<String>, Option<[f32; 4]>)>,
     font_system: FontSystem,
     needs_rebuild: bool,
+    /// What the last rebuild's widgets claimed for text input (an editing
+    /// TextBox, `cce_ui::text_input::capture`). Claimed again every frame:
+    /// a frame that only replays the cached layout paints no widget, and
+    /// would otherwise read as the field closing.
+    text_claim: Option<[f32; 4]>,
     width: u32,
     height: u32,
     scale_factor: f64,
@@ -619,7 +624,14 @@ impl FilesystemApp {
         self.needs_rebuild = true;
     }
 
+    /// Lay the window out and flatten it into the cached frame, keeping what
+    /// its widgets claimed for text input (`text_claim`).
     fn rebuild_layout(&mut self) {
+        let ((), claim) = cce_ui::text_input::capture(|| self.rebuild_layout_inner());
+        self.text_claim = claim;
+    }
+
+    fn rebuild_layout_inner(&mut self) {
 
         // Well focus → the emitters (each picks the tinted carve when set).
         self.browse.list.focused = self.focused_well == FocusedWell::Content;
@@ -1352,6 +1364,7 @@ impl Application for FilesystemApp {
             texts: Vec::new(),
             font_system: cce_ui::create_font_system(),
             needs_rebuild: true,
+            text_claim: None,
             width: initial_w,
             height: initial_h,
             scale_factor: 1.0,
@@ -1844,6 +1857,9 @@ impl Application for FilesystemApp {
         // with it: `paint_with_labels` carries the menu font's family, which
         // the hand-rolled `paint` + `text_labels()` loop here did not.
         cce_ui::widget::context_menu::paint_with_labels(&mut pc);
+        if let Some([x, y, w, h]) = self.text_claim {
+            cce_ui::text_input::claim(x, y, w, h);
+        }
         Some(pc.finish())
     }