fix(desktop): use the window id for context menus

This commit is contained in:
Ashley Wulber 2025-07-25 14:11:39 -04:00 committed by Ashley Wulber
parent a6e369df0f
commit 6d9e6c1d20
3 changed files with 66 additions and 26 deletions

View file

@ -960,6 +960,7 @@ impl App {
location: Location,
activate: bool,
selection_paths: Option<Vec<PathBuf>>,
window_id: Option<window::Id>,
) -> (Entity, Task<Message>) {
#[cfg(feature = "gvfs")]
if let Location::Network(ref uri, ref name, Some(ref path)) = location {
@ -1001,6 +1002,7 @@ impl App {
location.clone(),
self.config.tab,
Some(&self.state.sort_names),
window_id,
);
tab.mode = match self.mode {
Mode::App => tab::Mode::App,
@ -1009,6 +1011,7 @@ impl App {
tab::Mode::Desktop
}
};
let entity = self
.tab_model
.insert()
@ -1038,7 +1041,8 @@ impl App {
activate: bool,
selection_paths: Option<Vec<PathBuf>>,
) -> Task<Message> {
self.open_tab_entity(location, activate, selection_paths).1
self.open_tab_entity(location, activate, selection_paths, None)
.1
}
// This wrapper ensures that local folders use trash and remote folders permanently delete with a dialog
@ -2424,7 +2428,7 @@ impl Application for App {
if tab.context_menu.is_some() {
return self.update(Message::TabMessage(
Some(entity),
tab::Message::ContextMenu(None),
tab::Message::ContextMenu(None, None),
));
}
@ -3705,7 +3709,7 @@ impl Application for App {
if tab.context_menu.is_some() {
tasks.push(self.update(Message::TabMessage(
Some(active),
tab::Message::ContextMenu(None),
tab::Message::ContextMenu(None, None),
)));
}
}
@ -3804,7 +3808,7 @@ impl Application for App {
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
//TODO: move to Task?
if let tab::Message::ContextMenu(_point_opt) = tab_message {
if let tab::Message::ContextMenu(_point_opt, _) = tab_message {
// Disable side context page
self.set_show_context(false);
}
@ -3852,7 +3856,7 @@ impl Application for App {
self.update_tab(entity, tab_path, selection_paths),
]));
}
tab::Command::ContextMenu(point_opt) => {
tab::Command::ContextMenu(point_opt, parent_id) => {
#[cfg(feature = "wayland")]
match point_opt {
Some(point) => {
@ -3887,9 +3891,10 @@ impl Application for App {
..Default::default()
};
SctkPopupSettings {
parent: app
.window_id_opt
.unwrap_or_else(|| WindowId::NONE),
parent: parent_id.unwrap_or(
app.window_id_opt
.unwrap_or_else(|| WindowId::NONE),
),
id: window_id,
positioner,
parent_size: None,
@ -4543,6 +4548,7 @@ impl Application for App {
Location::Desktop(crate::desktop_dir(), display, self.config.desktop),
false,
None,
Some(surface_id),
);
self.windows.insert(surface_id, WindowKind::Desktop(entity));
return Task::batch([

View file

@ -945,7 +945,7 @@ impl Application for App {
},
});
let mut tab = Tab::new(location, flags.config.dialog_tab(), None);
let mut tab = Tab::new(location, flags.config.dialog_tab(), None, None);
tab.mode = tab::Mode::Dialog(flags.kind.clone());
tab.sort_name = tab::HeadingOptions::Modified;
tab.sort_direction = false;
@ -1239,7 +1239,7 @@ impl Application for App {
}
if self.tab.context_menu.is_some() {
return self.update(Message::TabMessage(tab::Message::ContextMenu(None)));
return self.update(Message::TabMessage(tab::Message::ContextMenu(None, None)));
}
if self.tab.edit_location.is_some() {
@ -1605,7 +1605,7 @@ impl Application for App {
tab::Command::ChangeLocation(_tab_title, _tab_path, _selection_paths) => {
commands.push(Task::batch([self.update_watcher(), self.rescan_tab()]));
}
tab::Command::ContextMenu(point_opt) => {
tab::Command::ContextMenu(point_opt, parent_id) => {
#[cfg(feature = "wayland")]
match point_opt {
Some(point) => {
@ -1639,7 +1639,8 @@ impl Application for App {
..Default::default()
};
SctkPopupSettings {
parent: app.flags.window_id,
parent: parent_id
.unwrap_or(app.flags.window_id),
id: window_id,
positioner,
parent_size: None,

View file

@ -16,6 +16,7 @@ use cosmic::{
horizontal_rule, rule,
scrollable::{self, AbsoluteOffset, Viewport},
},
window,
Alignment,
Border,
Color,
@ -1508,7 +1509,7 @@ pub enum Command {
AddToSidebar(PathBuf),
AutoScroll(Option<f32>),
ChangeLocation(String, Location, Option<Vec<PathBuf>>),
ContextMenu(Option<Point>),
ContextMenu(Option<Point>, Option<window::Id>),
Delete(Vec<PathBuf>),
DropFiles(PathBuf, ClipboardPaste),
EmptyTrash,
@ -1536,7 +1537,7 @@ pub enum Message {
ClickRelease(Option<usize>),
Config(TabConfig),
ContextAction(Action),
ContextMenu(Option<Point>),
ContextMenu(Option<Point>, Option<window::Id>),
LocationContextMenuPoint(Option<Point>),
LocationContextMenuIndex(Option<usize>),
LocationMenuAction(LocationMenuAction),
@ -2411,6 +2412,7 @@ pub struct Tab {
date_time_formatter: DateTimeFormatter,
time_formatter: DateTimeFormatter,
watch_drag: bool,
window_id: Option<window::Id>,
}
async fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
@ -2478,6 +2480,7 @@ impl Tab {
location: Location,
config: TabConfig,
sorting_options: Option<&OrderMap<String, (HeadingOptions, bool)>>,
window_id: Option<window::Id>,
) -> Self {
let location_str = location.to_string();
let (sort_name, sort_direction) = sorting_options
@ -2523,6 +2526,7 @@ impl Tab {
date_time_formatter: date_time_formatter(config.military_time),
time_formatter: time_formatter(config.military_time),
watch_drag: true,
window_id,
}
}
@ -3087,7 +3091,7 @@ impl Tab {
commands.push(Command::Action(action));
}
Message::ContextMenu(point_opt) => {
Message::ContextMenu(point_opt, _) => {
self.edit_location = None;
if point_opt.is_none() || !mod_shift {
self.context_menu = point_opt;
@ -3926,12 +3930,13 @@ impl Tab {
// Update context menu popup
if self.context_menu != last_context_menu {
if last_context_menu.is_some() {
commands.push(Command::ContextMenu(None));
commands.push(Command::ContextMenu(None, self.window_id.clone()));
}
if let Some(point) = self.context_menu {
commands.push(Command::ContextMenu(Some(
point + self.offset_opt.unwrap_or_default(),
)));
commands.push(Command::ContextMenu(
Some(point + self.offset_opt.unwrap_or_default()),
self.window_id.clone(),
));
}
}
@ -5400,9 +5405,12 @@ impl Tab {
.on_scroll(|delta| respond_to_scroll_direction(delta, self.modifiers));
if self.context_menu.is_some() {
mouse_area = mouse_area.on_right_press(move |_point_opt| Message::ContextMenu(None));
mouse_area = mouse_area.on_right_press(move |_point_opt| {
Message::ContextMenu(None, self.window_id.clone())
});
} else {
mouse_area = mouse_area.on_right_press(Message::ContextMenu);
let window_id = self.window_id.clone();
mouse_area = mouse_area.on_right_press(move |p| Message::ContextMenu(p, window_id));
}
let mut popover = widget::popover(mouse_area);
@ -6063,7 +6071,12 @@ mod tests {
fn tab_history() -> io::Result<(TempDir, Tab, Vec<PathBuf>)> {
let fs = simple_fs(NUM_FILES, NUM_NESTED, NUM_DIRS, NUM_NESTED, NAME_LEN)?;
let path = fs.path();
let mut tab = Tab::new(Location::Path(path.into()), TabConfig::default(), None);
let mut tab = Tab::new(
Location::Path(path.into()),
TabConfig::default(),
None,
None,
);
// All directories (simple_fs only produces one nested layer)
let dirs: Vec<PathBuf> = filter_dirs(path)?
@ -6160,7 +6173,12 @@ mod tests {
.next()
.expect("temp directory should have at least one directory");
let mut tab = Tab::new(Location::Path(path.to_owned()), TabConfig::default(), None);
let mut tab = Tab::new(
Location::Path(path.to_owned()),
TabConfig::default(),
None,
None,
);
debug!(
"Emitting Message::Location(Location::Path(\"{}\"))",
next_dir.display()
@ -6292,7 +6310,12 @@ mod tests {
fn tab_empty_history_does_nothing_on_prev_next() -> io::Result<()> {
let fs = simple_fs(0, NUM_NESTED, NUM_DIRS, 0, NAME_LEN)?;
let path = fs.path();
let mut tab = Tab::new(Location::Path(path.into()), TabConfig::default(), None);
let mut tab = Tab::new(
Location::Path(path.into()),
TabConfig::default(),
None,
None,
);
// Tab's location shouldn't change if GoPrev or GoNext is triggered
debug!("Emitting Message::GoPrevious",);
@ -6314,7 +6337,12 @@ mod tests {
.next()
.expect("should be at least one directory");
let mut tab = Tab::new(Location::Path(next_dir.clone()), TabConfig::default(), None);
let mut tab = Tab::new(
Location::Path(next_dir.clone()),
TabConfig::default(),
None,
None,
);
// This will eventually yield false once root is hit
while next_dir.pop() {
debug!("Emitting Message::LocationUp",);
@ -6347,7 +6375,12 @@ mod tests {
}
debug!("Creating tab for directory of long file names");
Tab::new(Location::Path(path.into()), TabConfig::default(), None);
Tab::new(
Location::Path(path.into()),
TabConfig::default(),
None,
None,
);
Ok(())
}