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,
|
io::Write,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Mutex,
|
sync::Mutex,
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "subscription")]
|
#[cfg(feature = "subscription")]
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ use iced::Application as IcedApplication;
|
||||||
use iced::event::wayland;
|
use iced::event::wayland;
|
||||||
use iced::{Task, window};
|
use iced::{Task, window};
|
||||||
use iced_futures::event::listen_with;
|
use iced_futures::event::listen_with;
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
|
use iced_winit::SurfaceIdWrapper;
|
||||||
use palette::color_difference::EuclideanDistance;
|
use palette::color_difference::EuclideanDistance;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
|
@ -84,7 +86,11 @@ pub struct Cosmic<App: Application> {
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub surface_views: HashMap<
|
pub surface_views: HashMap<
|
||||||
window::Id,
|
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")]
|
#[cfg(feature = "multi-window")]
|
||||||
pub fn view(&self, id: window::Id) -> Element<crate::Action<T::Message>> {
|
pub fn view(&self, id: window::Id) -> Element<crate::Action<T::Message>> {
|
||||||
#[cfg(feature = "wayland")]
|
#[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);
|
return v(&self.app);
|
||||||
}
|
}
|
||||||
if self
|
if self
|
||||||
|
|
@ -841,13 +847,45 @@ impl<T: Application> Cosmic<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::Focus(f) => {
|
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) => {
|
Action::Unfocus(id) => {
|
||||||
let core = self.app.core_mut();
|
let core = self.app.core_mut();
|
||||||
if core.focused_window.as_ref().is_some_and(|cur| *cur == id) {
|
if core.focused_window().as_ref().is_some_and(|cur| *cur == id) {
|
||||||
core.focused_window = None;
|
core.focused_window.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "applet")]
|
#[cfg(feature = "applet")]
|
||||||
|
|
@ -886,7 +924,14 @@ impl<App: Application> Cosmic<App> {
|
||||||
) -> Task<crate::Action<App::Message>> {
|
) -> Task<crate::Action<App::Message>> {
|
||||||
use iced_winit::commands::subsurface::get_subsurface;
|
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)
|
get_subsurface(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -901,7 +946,14 @@ impl<App: Application> Cosmic<App> {
|
||||||
) -> Task<crate::Action<App::Message>> {
|
) -> Task<crate::Action<App::Message>> {
|
||||||
use iced_winit::commands::popup::get_popup;
|
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)
|
get_popup(settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -548,8 +548,9 @@ impl<App: Application> ApplicationExt for App {
|
||||||
let show_context = core.window.show_context;
|
let show_context = core.window.show_context;
|
||||||
let nav_bar_active = core.nav_bar_active();
|
let nav_bar_active = core.nav_bar_active();
|
||||||
let focused = core
|
let focused = core
|
||||||
.focused_window()
|
.focus_chain()
|
||||||
.is_some_and(|i| Some(i) == self.core().main_window_id());
|
.iter()
|
||||||
|
.any(|i| Some(*i) == self.core().main_window_id());
|
||||||
|
|
||||||
let border_padding = if sharp_corners { 8 } else { 7 };
|
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,
|
scale_factor: f32,
|
||||||
|
|
||||||
/// Window focus state
|
/// Window focus state
|
||||||
pub(super) focused_window: Option<window::Id>,
|
pub(super) focused_window: Vec<window::Id>,
|
||||||
|
|
||||||
pub(super) theme_sub_counter: u64,
|
pub(super) theme_sub_counter: u64,
|
||||||
/// Last known system theme
|
/// Last known system theme
|
||||||
|
|
@ -141,7 +141,7 @@ impl Default for Core {
|
||||||
height: 0.,
|
height: 0.,
|
||||||
width: 0.,
|
width: 0.,
|
||||||
},
|
},
|
||||||
focused_window: None,
|
focused_window: Vec::new(),
|
||||||
#[cfg(feature = "applet")]
|
#[cfg(feature = "applet")]
|
||||||
applet: crate::applet::Context::default(),
|
applet: crate::applet::Context::default(),
|
||||||
#[cfg(feature = "single-instance")]
|
#[cfg(feature = "single-instance")]
|
||||||
|
|
@ -384,8 +384,15 @@ impl Core {
|
||||||
/// Get the current focused window if it exists
|
/// Get the current focused window if it exists
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn focused_window(&self) -> Option<window::Id> {
|
pub fn focused_window(&self) -> Option<window::Id> {
|
||||||
self.focused_window
|
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
|
/// Whether the application should use a dark theme, according to the system
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue