git.lucas.co / cce-cloud
cloud storage client
git clone https://git.lucas.co/cce-cloud.git

commit96a0050bc947278c5cb232a06c5d5b04cd64f757
parent75c2d46d45
authorLucas Galante <[email protected]>
date2026-07-14 10:25
fix: ingest initial dmenu items in daemon mode

In daemon mode the per-connection reader thread only signals the event
loop for lines that arrive after the popup is set up; the items packed
into the request's initial_stdin sat in StdinState with new_data=true
but nothing ever fired the channel, so --dmenu popups (e.g. the status
bar's window picker) rendered "No matches found" while --json popups
(fed synchronously via json_layout_config) worked. Fire one signal once
the state is installed so the existing handler ingests them.

Also drop the st.stdin_state swap that ran before app.state was
replaced — it only ever mutated the previous popup's dead state.

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

 src/main.rs | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 5da504e..2f43fd1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2913,9 +2913,6 @@ fn run_daemon(socket_path: &str) {
             parent_app_id,
         ));
 
-        if let Some(ref mut st) = app.state {
-            st.stdin_state = stdin_state.clone();
-        }
         app.window = state.window.clone();
         app.surface = Some(state.wl_surface.clone());
         app.cce_toplevel = cce_toplevel;
@@ -2926,6 +2923,11 @@ fn run_daemon(socket_path: &str) {
         app.fade_start = None;
         app.fade_factor = 1.0;
 
+        // The reader thread only signals for lines that arrive after this
+        // point; the initial_stdin items are already sitting in stdin_state,
+        // so fire one signal to make the channel handler ingest them.
+        let _ = stdin_sender.send(());
+
         let mut last_tick = std::time::Instant::now();
         while !app.exit {
             if app.fade_out {