Filter window events by window id, fixes #1118

This commit is contained in:
Jeremy Soller 2025-08-15 09:23:29 -06:00
parent 30a0836018
commit 5e0645d1c2
No known key found for this signature in database
GPG key ID: 670FDFB5428E05CA

View file

@ -325,10 +325,10 @@ pub enum Message {
ExtractToResult(DialogResult),
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
Focused(window::Id),
Key(Modifiers, Key, Option<SmolStr>),
Key(window::Id, Modifiers, Key, Option<SmolStr>),
LaunchUrl(String),
MaybeExit,
ModifiersChanged(Modifiers),
ModifiersChanged(window::Id, Modifiers),
MounterItems(MounterKey, MounterItems),
MountResult(MounterKey, MounterItem, Result<bool, String>),
NavBarClose(Entity),
@ -357,7 +357,7 @@ pub enum Message {
OpenWithDialog(Option<Entity>),
OpenWithSelection(usize),
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
Overlap(OverlapNotifyEvent, window::Id),
Overlap(window::Id, OverlapNotifyEvent),
Paste(Option<Entity>),
PasteContents(PathBuf, ClipboardPaste),
PendingCancel(u64),
@ -383,7 +383,7 @@ pub enum Message {
SetShowDetails(bool),
SetTypeToSearch(TypeToSearch),
SystemThemeModeChange,
Size(Size),
Size(window::Id, Size),
TabActivate(Entity),
TabNext,
TabPrev,
@ -410,7 +410,6 @@ pub enum Message {
WindowCloseRequested(window::Id),
WindowMaximize(window::Id, bool),
WindowNew,
WindowUnfocus,
ZoomDefault(Option<Entity>),
ZoomIn(Option<Entity>),
ZoomOut(Option<Entity>),
@ -673,7 +672,6 @@ pub struct App {
surface_names: HashMap<WindowId, String>,
toasts: widget::toaster::Toasts<Message>,
watcher_opt: Option<(Debouncer<RecommendedWatcher, FileIdMap>, HashSet<PathBuf>)>,
pub(crate) window_id_opt: Option<window::Id>,
windows: HashMap<window::Id, WindowKind>,
nav_dnd_hover: Option<(Location, Instant)>,
tab_dnd_hover: Option<(Entity, Instant)>,
@ -1553,8 +1551,8 @@ impl App {
Some(tab_title) => format!("{tab_title}{}", fl!("cosmic-files")),
None => fl!("cosmic-files"),
};
if let Some(window_id) = &self.window_id_opt {
self.set_window_title(window_title, *window_id)
if let Some(window_id) = self.core.main_window_id() {
self.set_window_title(window_title, window_id)
} else {
Task::none()
}
@ -2099,8 +2097,6 @@ impl Application for App {
Mode::Desktop => tab::Mode::Desktop,
});
let window_id_opt = core.main_window_id();
// Create a dedicated thread for the compio runtime to handle operations on.
// Supports io_uring on Linux, IOPC on Windows, and polling everywhere else.
let (compio_tx, mut compio_rx) = mpsc::channel(1);
@ -2156,7 +2152,6 @@ impl Application for App {
surface_names: HashMap::new(),
toasts: widget::toaster::Toasts::new(Message::CloseToast),
watcher_opt: None,
window_id_opt,
windows: HashMap::new(),
nav_dnd_hover: None,
tab_dnd_hover: None,
@ -2207,7 +2202,7 @@ impl Application for App {
}
fn nav_bar(&self) -> Option<Element<cosmic::Action<Self::Message>>> {
if !self.core().nav_bar_active() {
if !self.core.nav_bar_active() {
return None;
}
@ -2235,7 +2230,7 @@ impl Application for App {
)
.into_container();
if !self.core().is_condensed() {
if !self.core.is_condensed() {
nav = nav.max_width(280);
}
@ -2942,40 +2937,46 @@ impl Application for App {
return dialog.update(dialog_message);
}
}
Message::Key(modifiers, key, text) => {
let entity = self.tab_model.active();
for (key_bind, action) in self.key_binds.iter() {
if key_bind.matches(modifiers, &key) {
return self.update(action.message(Some(entity)));
Message::Key(window_id, modifiers, key, text) => {
if self.core.main_window_id() == Some(window_id) {
let entity = self.tab_model.active();
for (key_bind, action) in self.key_binds.iter() {
if key_bind.matches(modifiers, &key) {
return self.update(action.message(Some(entity)));
}
}
}
// Uncaptured keys with only shift modifiers go to the search or location box
if !modifiers.logo()
&& !modifiers.control()
&& !modifiers.alt()
&& matches!(key, Key::Character(_))
{
if let Some(text) = text {
match self.config.type_to_search {
TypeToSearch::Recursive => {
let mut term = self.search_get().unwrap_or_default().to_string();
term.push_str(&text);
return self.search_set_active(Some(term));
}
TypeToSearch::EnterPath => {
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
let location = tab.edit_location.as_ref().map_or_else(
|| tab.location.clone(),
|x| x.location.clone(),
);
// Try to add text to end of location
if let Some(path) = location.path_opt() {
let mut path_string = path.to_string_lossy().to_string();
path_string.push_str(&text);
tab.edit_location = Some(
location.with_path(PathBuf::from(path_string)).into(),
// Uncaptured keys with only shift modifiers go to the search or location box
if !modifiers.logo()
&& !modifiers.control()
&& !modifiers.alt()
&& matches!(key, Key::Character(_))
{
if let Some(text) = text {
match self.config.type_to_search {
TypeToSearch::Recursive => {
let mut term =
self.search_get().unwrap_or_default().to_string();
term.push_str(&text);
return self.search_set_active(Some(term));
}
TypeToSearch::EnterPath => {
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
let location = tab.edit_location.as_ref().map_or_else(
|| tab.location.clone(),
|x| x.location.clone(),
);
// Try to add text to end of location
if let Some(path) = location.path_opt() {
let mut path_string =
path.to_string_lossy().to_string();
path_string.push_str(&text);
tab.edit_location = Some(
location
.with_path(PathBuf::from(path_string))
.into(),
);
}
}
}
}
@ -2984,7 +2985,7 @@ impl Application for App {
}
}
Message::MaybeExit => {
if self.window_id_opt.is_none() && self.pending_operations.is_empty() {
if self.core.main_window_id().is_none() && self.pending_operations.is_empty() {
// Exit if window is closed and there are no pending operations
process::exit(0);
}
@ -2995,13 +2996,15 @@ impl Application for App {
log::warn!("failed to open {:?}: {}", url, err);
}
},
Message::ModifiersChanged(modifiers) => {
self.modifiers = modifiers;
let entity = self.tab_model.active();
return self.update(Message::TabMessage(
Some(entity),
tab::Message::ModifiersChanged(modifiers),
));
Message::ModifiersChanged(window_id, modifiers) => {
if self.core.main_window_id() == Some(window_id) {
self.modifiers = modifiers;
let entity = self.tab_model.active();
return self.update(Message::TabMessage(
Some(entity),
tab::Message::ModifiersChanged(modifiers),
));
}
}
Message::MounterItems(mounter_key, mounter_items) => {
// Check for unmounted folders
@ -3802,8 +3805,8 @@ impl Application for App {
// If that was the last tab, close window
if self.tab_model.iter().next().is_none() {
if let Some(window_id) = &self.window_id_opt {
return window::close(*window_id);
if let Some(window_id) = self.core.main_window_id() {
return window::close(window_id);
}
}
@ -3914,7 +3917,8 @@ impl Application for App {
};
SctkPopupSettings {
parent: parent_id.unwrap_or(
app.window_id_opt
app.core
.main_window_id()
.unwrap_or_else(|| WindowId::NONE),
),
id: window_id,
@ -4002,13 +4006,13 @@ impl Application for App {
commands.push(self.operation(Operation::SetPermissions { path, mode }));
}
tab::Command::WindowDrag => {
if let Some(window_id) = &self.window_id_opt {
commands.push(window::drag(*window_id));
if let Some(window_id) = self.core.main_window_id() {
commands.push(window::drag(window_id));
}
}
tab::Command::WindowToggleMaximize => {
if let Some(window_id) = &self.window_id_opt {
commands.push(window::toggle_maximize(*window_id));
if let Some(window_id) = self.core.main_window_id() {
commands.push(window::toggle_maximize(window_id));
}
}
tab::Command::SetSort(location, heading_options, direction) => {
@ -4168,7 +4172,8 @@ impl Application for App {
return self.operation(Operation::Restore { items });
}
Message::WindowClose => {
if let Some(window_id) = self.window_id_opt.take() {
if let Some(window_id) = self.core.main_window_id() {
self.core.set_main_window_id(None);
return Task::batch([
window::close(window_id),
Task::perform(
@ -4178,14 +4183,6 @@ impl Application for App {
]);
}
}
Message::WindowUnfocus => {
/*TODO
let tab_entity = self.tab_model.active();
if let Some(tab) = self.tab_model.data_mut::<Tab>(tab_entity) {
tab.context_menu = None;
}
*/
}
Message::WindowCloseRequested(id) => {
self.remove_window(&id);
}
@ -4621,7 +4618,7 @@ impl Application for App {
}
Message::None => {}
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
Message::Overlap(overlap_notify_event, w_id) => match overlap_notify_event {
Message::Overlap(w_id, overlap_notify_event) => match overlap_notify_event {
OverlapNotifyEvent::OverlapLayerAdd {
identifier,
namespace,
@ -4640,9 +4637,11 @@ impl Application for App {
}
_ => {}
},
Message::Size(size) => {
self.size = Some(size);
self.handle_overlap();
Message::Size(window_id, size) => {
if self.core.main_window_id() == Some(window_id) {
self.size = Some(size);
self.handle_overlap();
}
}
Message::Eject => {
#[cfg(feature = "gvfs")]
@ -5818,6 +5817,7 @@ impl Application for App {
struct RecentsWatcherSubscription;
let mut subscriptions = vec![
//TODO: filter more events by window id
event::listen_with(|event, status, window_id| match event {
Event::Keyboard(KeyEvent::KeyPressed {
key,
@ -5825,20 +5825,19 @@ impl Application for App {
text,
..
}) => match status {
event::Status::Ignored => Some(Message::Key(modifiers, key, text)),
event::Status::Ignored => Some(Message::Key(window_id, modifiers, key, text)),
event::Status::Captured => None,
},
Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => {
Some(Message::ModifiersChanged(modifiers))
Some(Message::ModifiersChanged(window_id, modifiers))
}
Event::Window(WindowEvent::Unfocused) => Some(Message::WindowUnfocus),
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
Event::Window(WindowEvent::Focused) => Some(Message::Focused(window_id)),
Event::Window(WindowEvent::CloseRequested) => Some(Message::WindowClose),
Event::Window(WindowEvent::Opened { position: _, size }) => {
Some(Message::Size(size))
Some(Message::Size(window_id, size))
}
Event::Window(WindowEvent::Resized(s)) => Some(Message::Size(s)),
Event::Window(WindowEvent::Resized(s)) => Some(Message::Size(window_id, s)),
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
Event::PlatformSpecific(event::PlatformSpecific::Wayland(wayland_event)) => {
match wayland_event {
@ -5847,7 +5846,7 @@ impl Application for App {
}
#[cfg(feature = "desktop")]
WaylandEvent::OverlapNotify(event) => {
Some(Message::Overlap(event, window_id))
Some(Message::Overlap(window_id, event))
}
_ => None,
}
@ -6125,7 +6124,7 @@ impl Application for App {
if !self.pending_operations.is_empty() {
//TODO: inhibit suspend/shutdown?
if self.window_id_opt.is_some() {
if self.core.main_window_id().is_some() {
// Force refresh the UI every 100ms while an operation is active.
if self
.pending_operations