fix(desktop): use the window id for context menus
This commit is contained in:
parent
a6e369df0f
commit
6d9e6c1d20
3 changed files with 66 additions and 26 deletions
22
src/app.rs
22
src/app.rs
|
|
@ -960,6 +960,7 @@ impl App {
|
||||||
location: Location,
|
location: Location,
|
||||||
activate: bool,
|
activate: bool,
|
||||||
selection_paths: Option<Vec<PathBuf>>,
|
selection_paths: Option<Vec<PathBuf>>,
|
||||||
|
window_id: Option<window::Id>,
|
||||||
) -> (Entity, Task<Message>) {
|
) -> (Entity, Task<Message>) {
|
||||||
#[cfg(feature = "gvfs")]
|
#[cfg(feature = "gvfs")]
|
||||||
if let Location::Network(ref uri, ref name, Some(ref path)) = location {
|
if let Location::Network(ref uri, ref name, Some(ref path)) = location {
|
||||||
|
|
@ -1001,6 +1002,7 @@ impl App {
|
||||||
location.clone(),
|
location.clone(),
|
||||||
self.config.tab,
|
self.config.tab,
|
||||||
Some(&self.state.sort_names),
|
Some(&self.state.sort_names),
|
||||||
|
window_id,
|
||||||
);
|
);
|
||||||
tab.mode = match self.mode {
|
tab.mode = match self.mode {
|
||||||
Mode::App => tab::Mode::App,
|
Mode::App => tab::Mode::App,
|
||||||
|
|
@ -1009,6 +1011,7 @@ impl App {
|
||||||
tab::Mode::Desktop
|
tab::Mode::Desktop
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let entity = self
|
let entity = self
|
||||||
.tab_model
|
.tab_model
|
||||||
.insert()
|
.insert()
|
||||||
|
|
@ -1038,7 +1041,8 @@ impl App {
|
||||||
activate: bool,
|
activate: bool,
|
||||||
selection_paths: Option<Vec<PathBuf>>,
|
selection_paths: Option<Vec<PathBuf>>,
|
||||||
) -> Task<Message> {
|
) -> 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
|
// 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() {
|
if tab.context_menu.is_some() {
|
||||||
return self.update(Message::TabMessage(
|
return self.update(Message::TabMessage(
|
||||||
Some(entity),
|
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() {
|
if tab.context_menu.is_some() {
|
||||||
tasks.push(self.update(Message::TabMessage(
|
tasks.push(self.update(Message::TabMessage(
|
||||||
Some(active),
|
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());
|
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||||
|
|
||||||
//TODO: move to Task?
|
//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
|
// Disable side context page
|
||||||
self.set_show_context(false);
|
self.set_show_context(false);
|
||||||
}
|
}
|
||||||
|
|
@ -3852,7 +3856,7 @@ impl Application for App {
|
||||||
self.update_tab(entity, tab_path, selection_paths),
|
self.update_tab(entity, tab_path, selection_paths),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
tab::Command::ContextMenu(point_opt) => {
|
tab::Command::ContextMenu(point_opt, parent_id) => {
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
match point_opt {
|
match point_opt {
|
||||||
Some(point) => {
|
Some(point) => {
|
||||||
|
|
@ -3887,9 +3891,10 @@ impl Application for App {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
SctkPopupSettings {
|
SctkPopupSettings {
|
||||||
parent: app
|
parent: parent_id.unwrap_or(
|
||||||
.window_id_opt
|
app.window_id_opt
|
||||||
.unwrap_or_else(|| WindowId::NONE),
|
.unwrap_or_else(|| WindowId::NONE),
|
||||||
|
),
|
||||||
id: window_id,
|
id: window_id,
|
||||||
positioner,
|
positioner,
|
||||||
parent_size: None,
|
parent_size: None,
|
||||||
|
|
@ -4543,6 +4548,7 @@ impl Application for App {
|
||||||
Location::Desktop(crate::desktop_dir(), display, self.config.desktop),
|
Location::Desktop(crate::desktop_dir(), display, self.config.desktop),
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
|
Some(surface_id),
|
||||||
);
|
);
|
||||||
self.windows.insert(surface_id, WindowKind::Desktop(entity));
|
self.windows.insert(surface_id, WindowKind::Desktop(entity));
|
||||||
return Task::batch([
|
return Task::batch([
|
||||||
|
|
|
||||||
|
|
@ -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.mode = tab::Mode::Dialog(flags.kind.clone());
|
||||||
tab.sort_name = tab::HeadingOptions::Modified;
|
tab.sort_name = tab::HeadingOptions::Modified;
|
||||||
tab.sort_direction = false;
|
tab.sort_direction = false;
|
||||||
|
|
@ -1239,7 +1239,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tab.context_menu.is_some() {
|
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() {
|
if self.tab.edit_location.is_some() {
|
||||||
|
|
@ -1605,7 +1605,7 @@ impl Application for App {
|
||||||
tab::Command::ChangeLocation(_tab_title, _tab_path, _selection_paths) => {
|
tab::Command::ChangeLocation(_tab_title, _tab_path, _selection_paths) => {
|
||||||
commands.push(Task::batch([self.update_watcher(), self.rescan_tab()]));
|
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")]
|
#[cfg(feature = "wayland")]
|
||||||
match point_opt {
|
match point_opt {
|
||||||
Some(point) => {
|
Some(point) => {
|
||||||
|
|
@ -1639,7 +1639,8 @@ impl Application for App {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
SctkPopupSettings {
|
SctkPopupSettings {
|
||||||
parent: app.flags.window_id,
|
parent: parent_id
|
||||||
|
.unwrap_or(app.flags.window_id),
|
||||||
id: window_id,
|
id: window_id,
|
||||||
positioner,
|
positioner,
|
||||||
parent_size: None,
|
parent_size: None,
|
||||||
|
|
|
||||||
61
src/tab.rs
61
src/tab.rs
|
|
@ -16,6 +16,7 @@ use cosmic::{
|
||||||
horizontal_rule, rule,
|
horizontal_rule, rule,
|
||||||
scrollable::{self, AbsoluteOffset, Viewport},
|
scrollable::{self, AbsoluteOffset, Viewport},
|
||||||
},
|
},
|
||||||
|
window,
|
||||||
Alignment,
|
Alignment,
|
||||||
Border,
|
Border,
|
||||||
Color,
|
Color,
|
||||||
|
|
@ -1508,7 +1509,7 @@ pub enum Command {
|
||||||
AddToSidebar(PathBuf),
|
AddToSidebar(PathBuf),
|
||||||
AutoScroll(Option<f32>),
|
AutoScroll(Option<f32>),
|
||||||
ChangeLocation(String, Location, Option<Vec<PathBuf>>),
|
ChangeLocation(String, Location, Option<Vec<PathBuf>>),
|
||||||
ContextMenu(Option<Point>),
|
ContextMenu(Option<Point>, Option<window::Id>),
|
||||||
Delete(Vec<PathBuf>),
|
Delete(Vec<PathBuf>),
|
||||||
DropFiles(PathBuf, ClipboardPaste),
|
DropFiles(PathBuf, ClipboardPaste),
|
||||||
EmptyTrash,
|
EmptyTrash,
|
||||||
|
|
@ -1536,7 +1537,7 @@ pub enum Message {
|
||||||
ClickRelease(Option<usize>),
|
ClickRelease(Option<usize>),
|
||||||
Config(TabConfig),
|
Config(TabConfig),
|
||||||
ContextAction(Action),
|
ContextAction(Action),
|
||||||
ContextMenu(Option<Point>),
|
ContextMenu(Option<Point>, Option<window::Id>),
|
||||||
LocationContextMenuPoint(Option<Point>),
|
LocationContextMenuPoint(Option<Point>),
|
||||||
LocationContextMenuIndex(Option<usize>),
|
LocationContextMenuIndex(Option<usize>),
|
||||||
LocationMenuAction(LocationMenuAction),
|
LocationMenuAction(LocationMenuAction),
|
||||||
|
|
@ -2411,6 +2412,7 @@ pub struct Tab {
|
||||||
date_time_formatter: DateTimeFormatter,
|
date_time_formatter: DateTimeFormatter,
|
||||||
time_formatter: DateTimeFormatter,
|
time_formatter: DateTimeFormatter,
|
||||||
watch_drag: bool,
|
watch_drag: bool,
|
||||||
|
window_id: Option<window::Id>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
async fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
||||||
|
|
@ -2478,6 +2480,7 @@ impl Tab {
|
||||||
location: Location,
|
location: Location,
|
||||||
config: TabConfig,
|
config: TabConfig,
|
||||||
sorting_options: Option<&OrderMap<String, (HeadingOptions, bool)>>,
|
sorting_options: Option<&OrderMap<String, (HeadingOptions, bool)>>,
|
||||||
|
window_id: Option<window::Id>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let location_str = location.to_string();
|
let location_str = location.to_string();
|
||||||
let (sort_name, sort_direction) = sorting_options
|
let (sort_name, sort_direction) = sorting_options
|
||||||
|
|
@ -2523,6 +2526,7 @@ impl Tab {
|
||||||
date_time_formatter: date_time_formatter(config.military_time),
|
date_time_formatter: date_time_formatter(config.military_time),
|
||||||
time_formatter: time_formatter(config.military_time),
|
time_formatter: time_formatter(config.military_time),
|
||||||
watch_drag: true,
|
watch_drag: true,
|
||||||
|
window_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3087,7 +3091,7 @@ impl Tab {
|
||||||
|
|
||||||
commands.push(Command::Action(action));
|
commands.push(Command::Action(action));
|
||||||
}
|
}
|
||||||
Message::ContextMenu(point_opt) => {
|
Message::ContextMenu(point_opt, _) => {
|
||||||
self.edit_location = None;
|
self.edit_location = None;
|
||||||
if point_opt.is_none() || !mod_shift {
|
if point_opt.is_none() || !mod_shift {
|
||||||
self.context_menu = point_opt;
|
self.context_menu = point_opt;
|
||||||
|
|
@ -3926,12 +3930,13 @@ impl Tab {
|
||||||
// Update context menu popup
|
// Update context menu popup
|
||||||
if self.context_menu != last_context_menu {
|
if self.context_menu != last_context_menu {
|
||||||
if last_context_menu.is_some() {
|
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 {
|
if let Some(point) = self.context_menu {
|
||||||
commands.push(Command::ContextMenu(Some(
|
commands.push(Command::ContextMenu(
|
||||||
point + self.offset_opt.unwrap_or_default(),
|
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));
|
.on_scroll(|delta| respond_to_scroll_direction(delta, self.modifiers));
|
||||||
|
|
||||||
if self.context_menu.is_some() {
|
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 {
|
} 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);
|
let mut popover = widget::popover(mouse_area);
|
||||||
|
|
@ -6063,7 +6071,12 @@ mod tests {
|
||||||
fn tab_history() -> io::Result<(TempDir, Tab, Vec<PathBuf>)> {
|
fn tab_history() -> io::Result<(TempDir, Tab, Vec<PathBuf>)> {
|
||||||
let fs = simple_fs(NUM_FILES, NUM_NESTED, NUM_DIRS, NUM_NESTED, NAME_LEN)?;
|
let fs = simple_fs(NUM_FILES, NUM_NESTED, NUM_DIRS, NUM_NESTED, NAME_LEN)?;
|
||||||
let path = fs.path();
|
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)
|
// All directories (simple_fs only produces one nested layer)
|
||||||
let dirs: Vec<PathBuf> = filter_dirs(path)?
|
let dirs: Vec<PathBuf> = filter_dirs(path)?
|
||||||
|
|
@ -6160,7 +6173,12 @@ mod tests {
|
||||||
.next()
|
.next()
|
||||||
.expect("temp directory should have at least one directory");
|
.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!(
|
debug!(
|
||||||
"Emitting Message::Location(Location::Path(\"{}\"))",
|
"Emitting Message::Location(Location::Path(\"{}\"))",
|
||||||
next_dir.display()
|
next_dir.display()
|
||||||
|
|
@ -6292,7 +6310,12 @@ mod tests {
|
||||||
fn tab_empty_history_does_nothing_on_prev_next() -> io::Result<()> {
|
fn tab_empty_history_does_nothing_on_prev_next() -> io::Result<()> {
|
||||||
let fs = simple_fs(0, NUM_NESTED, NUM_DIRS, 0, NAME_LEN)?;
|
let fs = simple_fs(0, NUM_NESTED, NUM_DIRS, 0, NAME_LEN)?;
|
||||||
let path = fs.path();
|
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
|
// Tab's location shouldn't change if GoPrev or GoNext is triggered
|
||||||
debug!("Emitting Message::GoPrevious",);
|
debug!("Emitting Message::GoPrevious",);
|
||||||
|
|
@ -6314,7 +6337,12 @@ mod tests {
|
||||||
.next()
|
.next()
|
||||||
.expect("should be at least one directory");
|
.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
|
// This will eventually yield false once root is hit
|
||||||
while next_dir.pop() {
|
while next_dir.pop() {
|
||||||
debug!("Emitting Message::LocationUp",);
|
debug!("Emitting Message::LocationUp",);
|
||||||
|
|
@ -6347,7 +6375,12 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Creating tab for directory of long file names");
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue