Merge pull request #1389 from pop-os/subwindow-modifiers
Track and use modifiers per sub-window, fixes #1152
This commit is contained in:
commit
83bdc4d073
1 changed files with 88 additions and 65 deletions
153
src/app.rs
153
src/app.rs
|
|
@ -661,6 +661,20 @@ impl PartialEq for WatcherWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Window {
|
||||||
|
kind: WindowKind,
|
||||||
|
modifiers: Modifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
fn new(kind: WindowKind) -> Self {
|
||||||
|
Self {
|
||||||
|
kind,
|
||||||
|
modifiers: Modifiers::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The [`App`] stores application-specific state.
|
// The [`App`] stores application-specific state.
|
||||||
pub struct App {
|
pub struct App {
|
||||||
core: Core,
|
core: Core,
|
||||||
|
|
@ -709,7 +723,7 @@ pub struct App {
|
||||||
Debouncer<RecommendedWatcher, RecommendedCache>,
|
Debouncer<RecommendedWatcher, RecommendedCache>,
|
||||||
FxHashSet<PathBuf>,
|
FxHashSet<PathBuf>,
|
||||||
)>,
|
)>,
|
||||||
windows: FxHashMap<window::Id, WindowKind>,
|
windows: FxHashMap<window::Id, Window>,
|
||||||
nav_dnd_hover: Option<(Location, Instant)>,
|
nav_dnd_hover: Option<(Location, Instant)>,
|
||||||
tab_dnd_hover: Option<(Entity, Instant)>,
|
tab_dnd_hover: Option<(Entity, Instant)>,
|
||||||
nav_drag_id: DragId,
|
nav_drag_id: DragId,
|
||||||
|
|
@ -935,9 +949,9 @@ impl App {
|
||||||
dialog.set_accept_label(fl!("extract-here"));
|
dialog.set_accept_label(fl!("extract-here"));
|
||||||
self.windows.insert(
|
self.windows.insert(
|
||||||
dialog.window_id(),
|
dialog.window_id(),
|
||||||
WindowKind::FileDialog(Some(
|
Window::new(WindowKind::FileDialog(Some(
|
||||||
paths.iter().map(|x| x.as_ref().to_path_buf()).collect(),
|
paths.iter().map(|x| x.as_ref().to_path_buf()).collect(),
|
||||||
)),
|
))),
|
||||||
);
|
);
|
||||||
self.file_dialog_opt = Some(dialog);
|
self.file_dialog_opt = Some(dialog);
|
||||||
Task::batch([set_title_task, dialog_task])
|
Task::batch([set_title_task, dialog_task])
|
||||||
|
|
@ -1178,8 +1192,8 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_window(&mut self, id: &window::Id) {
|
fn remove_window(&mut self, id: &window::Id) {
|
||||||
if let Some(window_kind) = self.windows.remove(id) {
|
if let Some(window) = self.windows.remove(id) {
|
||||||
match window_kind {
|
match window.kind {
|
||||||
WindowKind::ContextMenu(entity, _) => {
|
WindowKind::ContextMenu(entity, _) => {
|
||||||
// Close context menu
|
// Close context menu
|
||||||
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
|
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
|
||||||
|
|
@ -2704,7 +2718,8 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (id, command) = window::open(settings);
|
let (id, command) = window::open(settings);
|
||||||
self.windows.insert(id, WindowKind::DesktopViewOptions);
|
self.windows
|
||||||
|
.insert(id, Window::new(WindowKind::DesktopViewOptions));
|
||||||
return command.map(|_id| cosmic::action::none());
|
return command.map(|_id| cosmic::action::none());
|
||||||
}
|
}
|
||||||
Message::DesktopDialogs(show) => {
|
Message::DesktopDialogs(show) => {
|
||||||
|
|
@ -2732,14 +2747,14 @@ impl Application for App {
|
||||||
|
|
||||||
let (id, command) = window::open(settings);
|
let (id, command) = window::open(settings);
|
||||||
self.windows
|
self.windows
|
||||||
.insert(id, WindowKind::Dialogs(widget::Id::unique()));
|
.insert(id, Window::new(WindowKind::Dialogs(widget::Id::unique())));
|
||||||
return command.map(|_id| cosmic::Action::None);
|
return command.map(|_id| cosmic::Action::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tasks = self
|
let tasks = self
|
||||||
.windows
|
.windows
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, kind)| matches!(*kind, WindowKind::Dialogs(_)))
|
.filter(|(_, window)| matches!(window.kind, WindowKind::Dialogs(_)))
|
||||||
.map(|(id, _)| window::close(*id));
|
.map(|(id, _)| window::close(*id));
|
||||||
return Task::batch(tasks);
|
return Task::batch(tasks);
|
||||||
}
|
}
|
||||||
|
|
@ -2929,9 +2944,10 @@ impl Application for App {
|
||||||
DialogResult::Open(selected_paths) => {
|
DialogResult::Open(selected_paths) => {
|
||||||
let mut archive_paths = None;
|
let mut archive_paths = None;
|
||||||
if let Some(file_dialog) = &self.file_dialog_opt {
|
if let Some(file_dialog) = &self.file_dialog_opt {
|
||||||
let window = self.windows.remove(&file_dialog.window_id());
|
if let Some(window) = self.windows.remove(&file_dialog.window_id()) {
|
||||||
if let Some(WindowKind::FileDialog(paths)) = window {
|
if let WindowKind::FileDialog(paths) = window.kind {
|
||||||
archive_paths = paths;
|
archive_paths = paths;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(archive_paths) = archive_paths {
|
if let Some(archive_paths) = archive_paths {
|
||||||
|
|
@ -3021,6 +3037,9 @@ impl Application for App {
|
||||||
if self.core.main_window_id() == Some(window_id) || in_surface_ids {
|
if self.core.main_window_id() == Some(window_id) || in_surface_ids {
|
||||||
self.modifiers = modifiers;
|
self.modifiers = modifiers;
|
||||||
}
|
}
|
||||||
|
if let Some(window) = self.windows.get_mut(&window_id) {
|
||||||
|
window.modifiers = modifiers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Message::MounterItems(mounter_key, mounter_items) => {
|
Message::MounterItems(mounter_key, mounter_items) => {
|
||||||
// Check for unmounted folders
|
// Check for unmounted folders
|
||||||
|
|
@ -3612,10 +3631,10 @@ impl Application for App {
|
||||||
let (id, command) = window::open(settings);
|
let (id, command) = window::open(settings);
|
||||||
self.windows.insert(
|
self.windows.insert(
|
||||||
id,
|
id,
|
||||||
WindowKind::Preview(
|
Window::new(WindowKind::Preview(
|
||||||
entity_opt,
|
entity_opt,
|
||||||
PreviewKind::Location(Location::Path(path)),
|
PreviewKind::Location(Location::Path(path)),
|
||||||
),
|
)),
|
||||||
);
|
);
|
||||||
commands.push(command.map(|_id| cosmic::action::none()));
|
commands.push(command.map(|_id| cosmic::action::none()));
|
||||||
}
|
}
|
||||||
|
|
@ -3912,7 +3931,10 @@ impl Application for App {
|
||||||
let window_id = WindowId::unique();
|
let window_id = WindowId::unique();
|
||||||
self.windows.insert(
|
self.windows.insert(
|
||||||
window_id,
|
window_id,
|
||||||
WindowKind::ContextMenu(entity, widget::Id::unique()),
|
Window::new(WindowKind::ContextMenu(
|
||||||
|
entity,
|
||||||
|
widget::Id::unique(),
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
commands.push(self.update(Message::Surface(
|
commands.push(self.update(Message::Surface(
|
||||||
cosmic::surface::action::app_popup(
|
cosmic::surface::action::app_popup(
|
||||||
|
|
@ -3952,8 +3974,8 @@ impl Application for App {
|
||||||
} else {
|
} else {
|
||||||
// Destroy previous popup
|
// Destroy previous popup
|
||||||
let mut window_ids = Vec::new();
|
let mut window_ids = Vec::new();
|
||||||
for (window_id, window_kind) in &self.windows {
|
for (window_id, window) in &self.windows {
|
||||||
if let WindowKind::ContextMenu(e, _) = window_kind {
|
if let WindowKind::ContextMenu(e, _) = &window.kind {
|
||||||
if *e == entity {
|
if *e == entity {
|
||||||
window_ids.push(*window_id);
|
window_ids.push(*window_id);
|
||||||
}
|
}
|
||||||
|
|
@ -4565,7 +4587,8 @@ impl Application for App {
|
||||||
widget::Id::unique(),
|
widget::Id::unique(),
|
||||||
Some(surface_id),
|
Some(surface_id),
|
||||||
);
|
);
|
||||||
self.windows.insert(surface_id, WindowKind::Desktop(entity));
|
self.windows
|
||||||
|
.insert(surface_id, Window::new(WindowKind::Desktop(entity)));
|
||||||
return Task::batch([
|
return Task::batch([
|
||||||
command,
|
command,
|
||||||
get_layer_surface(SctkLayerSurfaceSettings {
|
get_layer_surface(SctkLayerSurfaceSettings {
|
||||||
|
|
@ -4666,7 +4689,7 @@ impl Application for App {
|
||||||
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
|
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
|
||||||
Message::Focused(id) => {
|
Message::Focused(id) => {
|
||||||
if let Some(w) = self.windows.get(&id) {
|
if let Some(w) = self.windows.get(&id) {
|
||||||
match w {
|
match &w.kind {
|
||||||
WindowKind::Desktop(entity) => self.tab_model.activate(*entity),
|
WindowKind::Desktop(entity) => self.tab_model.activate(*entity),
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
@ -5696,66 +5719,66 @@ impl Application for App {
|
||||||
|
|
||||||
fn view_window(&self, id: WindowId) -> Element<'_, Self::Message> {
|
fn view_window(&self, id: WindowId) -> Element<'_, Self::Message> {
|
||||||
let content = match self.windows.get(&id) {
|
let content = match self.windows.get(&id) {
|
||||||
Some(WindowKind::ContextMenu(entity, id)) => {
|
Some(window) => match &window.kind {
|
||||||
match self.tab_model.data::<Tab>(*entity) {
|
WindowKind::ContextMenu(entity, id) => match self.tab_model.data::<Tab>(*entity) {
|
||||||
Some(tab) => {
|
Some(tab) => {
|
||||||
return widget::autosize::autosize(
|
return widget::autosize::autosize(
|
||||||
menu::context_menu(tab, &self.key_binds, &self.modifiers)
|
menu::context_menu(tab, &self.key_binds, &window.modifiers)
|
||||||
.map(|x| Message::TabMessage(Some(*entity), x)),
|
.map(|x| Message::TabMessage(Some(*entity), x)),
|
||||||
id.clone(),
|
id.clone(),
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
}
|
}
|
||||||
None => widget::text("Unknown tab ID").into(),
|
None => widget::text("Unknown tab ID").into(),
|
||||||
}
|
},
|
||||||
}
|
WindowKind::Desktop(entity) => {
|
||||||
Some(WindowKind::Desktop(entity)) => {
|
let mut tab_column = widget::column::with_capacity(3);
|
||||||
let mut tab_column = widget::column::with_capacity(3);
|
|
||||||
|
|
||||||
let tab_view = match self.tab_model.data::<Tab>(*entity) {
|
let tab_view = match self.tab_model.data::<Tab>(*entity) {
|
||||||
Some(tab) => tab
|
Some(tab) => tab
|
||||||
.view(&self.key_binds, &self.modifiers)
|
.view(&self.key_binds, &window.modifiers)
|
||||||
.map(move |message| Message::TabMessage(Some(*entity), message)),
|
.map(move |message| Message::TabMessage(Some(*entity), message)),
|
||||||
None => widget::vertical_space().into(),
|
None => widget::vertical_space().into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
tab_column = tab_column.push(tab_view);
|
tab_column = tab_column.push(tab_view);
|
||||||
|
|
||||||
// The toaster is added on top of an empty element to ensure that it does not override context menus
|
// The toaster is added on top of an empty element to ensure that it does not override context menus
|
||||||
tab_column =
|
tab_column =
|
||||||
tab_column.push(widget::toaster(&self.toasts, widget::horizontal_space()));
|
tab_column.push(widget::toaster(&self.toasts, widget::horizontal_space()));
|
||||||
return if let Some(margin) = self.margin.get(&id) {
|
return if let Some(margin) = self.margin.get(&id) {
|
||||||
if margin.0 >= 0. || margin.2 >= 0. {
|
if margin.0 >= 0. || margin.2 >= 0. {
|
||||||
tab_column = widget::column::with_children([
|
tab_column = widget::column::with_children([
|
||||||
vertical_space().height(margin.0).into(),
|
vertical_space().height(margin.0).into(),
|
||||||
tab_column.into(),
|
tab_column.into(),
|
||||||
vertical_space().height(margin.2).into(),
|
vertical_space().height(margin.2).into(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if margin.1 >= 0. || margin.3 >= 0. {
|
if margin.1 >= 0. || margin.3 >= 0. {
|
||||||
Element::from(widget::row::with_children([
|
Element::from(widget::row::with_children([
|
||||||
horizontal_space().width(margin.1).into(),
|
horizontal_space().width(margin.1).into(),
|
||||||
tab_column.into(),
|
tab_column.into(),
|
||||||
horizontal_space().width(margin.3).into(),
|
horizontal_space().width(margin.3).into(),
|
||||||
]))
|
]))
|
||||||
|
} else {
|
||||||
|
tab_column.into()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tab_column.into()
|
tab_column.into()
|
||||||
}
|
};
|
||||||
} else {
|
}
|
||||||
tab_column.into()
|
WindowKind::DesktopViewOptions => self.desktop_view_options(),
|
||||||
};
|
WindowKind::Dialogs(id) => match self.dialog() {
|
||||||
}
|
Some(element) => return widget::autosize::autosize(element, id.clone()).into(),
|
||||||
Some(WindowKind::DesktopViewOptions) => self.desktop_view_options(),
|
None => widget::horizontal_space().into(),
|
||||||
Some(WindowKind::Dialogs(id)) => match self.dialog() {
|
},
|
||||||
Some(element) => return widget::autosize::autosize(element, id.clone()).into(),
|
WindowKind::Preview(entity_opt, kind) => self
|
||||||
None => widget::horizontal_space().into(),
|
.preview(entity_opt, kind, false)
|
||||||
},
|
.map(|x| Message::TabMessage(*entity_opt, x)),
|
||||||
Some(WindowKind::Preview(entity_opt, kind)) => self
|
WindowKind::FileDialog(..) => match &self.file_dialog_opt {
|
||||||
.preview(entity_opt, kind, false)
|
Some(dialog) => return dialog.view(id),
|
||||||
.map(|x| Message::TabMessage(*entity_opt, x)),
|
None => widget::text("Unknown window ID").into(),
|
||||||
Some(WindowKind::FileDialog(..)) => match &self.file_dialog_opt {
|
},
|
||||||
Some(dialog) => return dialog.view(id),
|
|
||||||
None => widget::text("Unknown window ID").into(),
|
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
//TODO: distinct views per monitor in desktop mode
|
//TODO: distinct views per monitor in desktop mode
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue