From cf328771c3bb199256ff3f3550c0e183dbef0a5e Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Thu, 26 Mar 2026 13:21:17 -0400 Subject: [PATCH 1/2] fix: handle slight delay in availability of clipboard data a better fix in the future would probably be an event indicating availability of the data. --- src/app.rs | 37 ++++++++++++++++++++++++++++++++++--- src/clipboard.rs | 9 ++------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/app.rs b/src/app.rs index 254827b..0561db4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -422,6 +422,7 @@ pub enum Message { CheckClipboardImage, CheckClipboardVideo, CheckClipboardText, + RetryCheckClipboard(ClipboardCache), ClipboardCached(ClipboardCache), PendingCancel(u64), PendingCancelAll, @@ -4036,9 +4037,12 @@ impl Application for App { // Check if clipboard has any paste-able content and cache it return clipboard::read_data::().map(|contents_opt| { match contents_opt { - Some(contents) if !contents.paths.is_empty() => cosmic::action::app( - Message::ClipboardCached(ClipboardCache::Files(contents)), + Some(contents) if contents.paths.is_empty() => cosmic::action::app( + Message::RetryCheckClipboard(ClipboardCache::Files(contents)), ), + Some(contents) => cosmic::action::app(Message::ClipboardCached( + ClipboardCache::Files(contents), + )), _ => cosmic::action::app(Message::CheckClipboardImage), } }); @@ -4071,6 +4075,28 @@ impl Application for App { })) }); } + Message::RetryCheckClipboard(cache) => { + let mut cmds = Vec::new(); + cmds.push(self.update(Message::ClipboardCached(cache))); + + cmds.push( + iced::Task::future(tokio::time::sleep(Duration::from_millis(300))) + .discard() + .chain( + clipboard::read_data::().map(|contents_opt| { + match contents_opt { + Some(contents) if !contents.paths.is_empty() => { + cosmic::action::app(Message::ClipboardCached( + ClipboardCache::Files(contents), + )) + } + _ => cosmic::action::app(Message::CheckClipboardImage), + } + }), + ), + ); + return Task::batch(cmds); + } Message::ClipboardCached(cache) => { self.clipboard_cache = cache; } @@ -4478,6 +4504,7 @@ impl Application for App { widget::Id::unique(), )), ); + commands.push(self.update(Message::CheckClipboard)); commands.push(self.update(Message::Surface( cosmic::surface::action::app_popup( move |app: &mut Self| -> SctkPopupSettings { @@ -5344,7 +5371,11 @@ impl Application for App { }; } // Check clipboard when window gains focus - return self.update(Message::CheckClipboard); + // HACK: Wait a moment for the data to be available. + return cosmic::task::future(async { + _ = tokio::time::sleep(Duration::from_millis(300)).await; + cosmic::action::app(Message::CheckClipboard) + }); } Message::Surface(action) => { return cosmic::task::message(cosmic::Action::Cosmic( diff --git a/src/clipboard.rs b/src/clipboard.rs index 6b0be96..5892071 100644 --- a/src/clipboard.rs +++ b/src/clipboard.rs @@ -133,9 +133,7 @@ impl TryFrom<(Vec, String)> for ClipboardPaste { "text/uri-list" => { let text = str::from_utf8(&data)?; let lines = text.lines(); - if text.is_empty() || lines.count() == 0 { - Err(format!("Empty file url"))?; - } + for line in text.lines() { let url = Url::parse(line)?; match url.to_file_path() { @@ -146,10 +144,7 @@ impl TryFrom<(Vec, String)> for ClipboardPaste { } "x-special/gnome-copied-files" => { let text = str::from_utf8(&data)?; - let lines = text.lines(); - if text.is_empty() || lines.count() == 0 { - Err(format!("Empty file url"))?; - } + for (i, line) in text.lines().enumerate() { if i == 0 { kind = match line { From 1c1f8fdf6e41361345156e1a6e2f03e8d5fb3902 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 27 Mar 2026 11:51:16 -0400 Subject: [PATCH 2/2] fix: retry reading clipboard if data is empty --- src/app.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/app.rs b/src/app.rs index 0561db4..19dc54d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3890,6 +3890,24 @@ impl Application for App { // Use cached clipboard data if available (needed for Wayland popups) match &self.clipboard_cache { ClipboardCache::Files(contents) => { + if contents.paths.is_empty() { + return iced::Task::future(tokio::time::sleep( + std::time::Duration::from_millis(300), + )) + .discard() + .chain( + clipboard::read_data::().map( + move |contents_opt| match contents_opt { + Some(contents) => cosmic::action::app( + Message::PasteContents(to.clone(), contents), + ), + None => { + cosmic::action::app(Message::PasteImage(to.clone())) + } + }, + ), + ); + } return self .update(Message::PasteContents(to.clone(), contents.clone())); }