refactor: track focus chain
This commit is contained in:
parent
50367b96e3
commit
0943f131c2
4 changed files with 73 additions and 14 deletions
|
|
@ -10,7 +10,6 @@ use std::{
|
|||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
sync::Mutex,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
#[cfg(feature = "subscription")]
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ use iced::Application as IcedApplication;
|
|||
use iced::event::wayland;
|
||||
use iced::{Task, window};
|
||||
use iced_futures::event::listen_with;
|
||||
#[cfg(feature = "wayland")]
|
||||
use iced_winit::SurfaceIdWrapper;
|
||||
use palette::color_difference::EuclideanDistance;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
|
|
@ -84,7 +86,11 @@ pub struct Cosmic<App: Application> {
|
|||
#[cfg(feature = "wayland")]
|
||||
pub surface_views: HashMap<
|
||||
window::Id,
|
||||
Box<dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>>>,
|
||||
(
|
||||
Option<window::Id>,
|
||||
SurfaceIdWrapper,
|
||||
Box<dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>>>,
|
||||
),
|
||||
>,
|
||||
}
|
||||
|
||||
|
|
@ -449,7 +455,7 @@ where
|
|||
#[cfg(feature = "multi-window")]
|
||||
pub fn view(&self, id: window::Id) -> Element<crate::Action<T::Message>> {
|
||||
#[cfg(feature = "wayland")]
|
||||
if let Some(v) = self.surface_views.get(&id) {
|
||||
if let Some((_, _, v)) = self.surface_views.get(&id) {
|
||||
return v(&self.app);
|
||||
}
|
||||
if self
|
||||
|
|
@ -841,13 +847,45 @@ impl<T: Application> Cosmic<T> {
|
|||
}
|
||||
|
||||
Action::Focus(f) => {
|
||||
self.app.core_mut().focused_window = Some(f);
|
||||
#[cfg(all(
|
||||
feature = "wayland",
|
||||
feature = "multi-window",
|
||||
feature = "surface-message"
|
||||
))]
|
||||
if let Some((
|
||||
parent,
|
||||
SurfaceIdWrapper::Subsurface(_) | SurfaceIdWrapper::Popup(_),
|
||||
_,
|
||||
)) = self.surface_views.get(&f)
|
||||
{
|
||||
// If the parent is already focused, push the new focus
|
||||
// to the end of the focus chain.
|
||||
if parent.is_some_and(|p| self.app.core().focused_window.last() == Some(&p)) {
|
||||
self.app.core_mut().focused_window.push(f);
|
||||
return iced::Task::none();
|
||||
} else {
|
||||
// set the whole parent chain to the focus chain
|
||||
let mut parent_chain = vec![f];
|
||||
let mut cur = *parent;
|
||||
while let Some(p) = cur {
|
||||
parent_chain.push(p);
|
||||
cur = self
|
||||
.surface_views
|
||||
.get(&p)
|
||||
.and_then(|(parent, _, _)| *parent);
|
||||
}
|
||||
parent_chain.reverse();
|
||||
self.app.core_mut().focused_window = parent_chain;
|
||||
return iced::Task::none();
|
||||
}
|
||||
}
|
||||
self.app.core_mut().focused_window = vec![f];
|
||||
}
|
||||
|
||||
Action::Unfocus(id) => {
|
||||
let core = self.app.core_mut();
|
||||
if core.focused_window.as_ref().is_some_and(|cur| *cur == id) {
|
||||
core.focused_window = None;
|
||||
if core.focused_window().as_ref().is_some_and(|cur| *cur == id) {
|
||||
core.focused_window.pop();
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "applet")]
|
||||
|
|
@ -886,7 +924,14 @@ impl<App: Application> Cosmic<App> {
|
|||
) -> Task<crate::Action<App::Message>> {
|
||||
use iced_winit::commands::subsurface::get_subsurface;
|
||||
|
||||
self.surface_views.insert(settings.id, view);
|
||||
self.surface_views.insert(
|
||||
settings.id,
|
||||
(
|
||||
Some(settings.parent),
|
||||
SurfaceIdWrapper::Subsurface(settings.id),
|
||||
view,
|
||||
),
|
||||
);
|
||||
get_subsurface(settings)
|
||||
}
|
||||
|
||||
|
|
@ -901,7 +946,14 @@ impl<App: Application> Cosmic<App> {
|
|||
) -> Task<crate::Action<App::Message>> {
|
||||
use iced_winit::commands::popup::get_popup;
|
||||
|
||||
self.surface_views.insert(settings.id, view);
|
||||
self.surface_views.insert(
|
||||
settings.id,
|
||||
(
|
||||
Some(settings.parent),
|
||||
SurfaceIdWrapper::Popup(settings.id),
|
||||
view,
|
||||
),
|
||||
);
|
||||
get_popup(settings)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -548,8 +548,9 @@ impl<App: Application> ApplicationExt for App {
|
|||
let show_context = core.window.show_context;
|
||||
let nav_bar_active = core.nav_bar_active();
|
||||
let focused = core
|
||||
.focused_window()
|
||||
.is_some_and(|i| Some(i) == self.core().main_window_id());
|
||||
.focus_chain()
|
||||
.iter()
|
||||
.any(|i| Some(*i) == self.core().main_window_id());
|
||||
|
||||
let border_padding = if sharp_corners { 8 } else { 7 };
|
||||
|
||||
|
|
|
|||
15
src/core.rs
15
src/core.rs
|
|
@ -64,7 +64,7 @@ pub struct Core {
|
|||
scale_factor: f32,
|
||||
|
||||
/// Window focus state
|
||||
pub(super) focused_window: Option<window::Id>,
|
||||
pub(super) focused_window: Vec<window::Id>,
|
||||
|
||||
pub(super) theme_sub_counter: u64,
|
||||
/// Last known system theme
|
||||
|
|
@ -141,7 +141,7 @@ impl Default for Core {
|
|||
height: 0.,
|
||||
width: 0.,
|
||||
},
|
||||
focused_window: None,
|
||||
focused_window: Vec::new(),
|
||||
#[cfg(feature = "applet")]
|
||||
applet: crate::applet::Context::default(),
|
||||
#[cfg(feature = "single-instance")]
|
||||
|
|
@ -384,8 +384,15 @@ impl Core {
|
|||
/// Get the current focused window if it exists
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn focused_window(&self) -> Option<window::Id> {
|
||||
self.focused_window
|
||||
pub fn focused_window(&self) -> Option<window::Id> {
|
||||
self.focused_window.last().copied()
|
||||
}
|
||||
|
||||
/// Get the current focus chain of windows
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn focus_chain(&self) -> &[window::Id] {
|
||||
&self.focused_window
|
||||
}
|
||||
|
||||
/// Whether the application should use a dark theme, according to the system
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue