shell: Handle focus shortcuts for floating layer
This commit is contained in:
parent
63c073e3e5
commit
3d10ca6105
4 changed files with 122 additions and 20 deletions
|
|
@ -6,8 +6,8 @@ use crate::{
|
||||||
shell::{
|
shell::{
|
||||||
focus::{target::PointerFocusTarget, FocusDirection},
|
focus::{target::PointerFocusTarget, FocusDirection},
|
||||||
grabs::{ResizeEdge, SeatMoveGrabState},
|
grabs::{ResizeEdge, SeatMoveGrabState},
|
||||||
layout::tiling::{Direction, FocusResult, MoveResult, SwapWindowGrab, TilingLayout},
|
layout::tiling::{Direction, MoveResult, SwapWindowGrab, TilingLayout},
|
||||||
OverviewMode, ResizeDirection, ResizeMode, Trigger, Workspace,
|
FocusResult, OverviewMode, ResizeDirection, ResizeMode, Trigger, Workspace,
|
||||||
},
|
},
|
||||||
state::Common,
|
state::Common,
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
|
|
@ -1305,19 +1305,14 @@ impl State {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let overview = self.common.shell.overview_mode().0;
|
let overview = self.common.shell.overview_mode().0;
|
||||||
let workspace = self.common.shell.active_space_mut(¤t_output);
|
let workspace = self.common.shell.active_space_mut(¤t_output);
|
||||||
let focus_stack = workspace.focus_stack.get(seat);
|
let result = workspace.next_focus(
|
||||||
let mut result = workspace.tiling_layer.next_focus(
|
|
||||||
focus,
|
focus,
|
||||||
seat,
|
seat,
|
||||||
focus_stack.iter(),
|
|
||||||
match overview {
|
match overview {
|
||||||
OverviewMode::Started(Trigger::KeyboardSwap(_, desc), _) => Some(desc),
|
OverviewMode::Started(Trigger::KeyboardSwap(_, desc), _) => Some(desc),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if workspace.get_fullscreen(¤t_output).is_some() {
|
|
||||||
result = FocusResult::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
FocusResult::None => {
|
FocusResult::None => {
|
||||||
|
|
@ -1367,7 +1362,6 @@ impl State {
|
||||||
}
|
}
|
||||||
FocusResult::Handled => {}
|
FocusResult::Handled => {}
|
||||||
FocusResult::Some(target) => {
|
FocusResult::Some(target) => {
|
||||||
std::mem::drop(focus_stack);
|
|
||||||
Common::set_focus(self, Some(&target), seat, None);
|
Common::set_focus(self, Some(&target), seat, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,16 @@ use smithay::{
|
||||||
element::{AsRenderElements, RenderElement},
|
element::{AsRenderElements, RenderElement},
|
||||||
ImportAll, ImportMem, Renderer,
|
ImportAll, ImportMem, Renderer,
|
||||||
},
|
},
|
||||||
desktop::{layer_map_for_output, space::SpaceElement, Space, WindowSurfaceType},
|
desktop::{layer_map_for_output, space::SpaceElement, PopupKind, Space, WindowSurfaceType},
|
||||||
input::{pointer::GrabStartData as PointerGrabStartData, Seat},
|
input::{pointer::GrabStartData as PointerGrabStartData, Seat},
|
||||||
output::Output,
|
output::Output,
|
||||||
utils::{Logical, Point, Rectangle, Size},
|
utils::{Logical, Point, Rectangle, Size},
|
||||||
|
wayland::seat::WaylandFocus,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::shell::focus::FocusDirection;
|
||||||
|
use crate::shell::FocusResult;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::{element::AsGlowRenderer, IndicatorShader, Key, Usage},
|
backend::render::{element::AsGlowRenderer, IndicatorShader, Key, Usage},
|
||||||
shell::{
|
shell::{
|
||||||
|
|
@ -25,7 +28,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
state::State,
|
state::State,
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::protocols::toplevel_info::ToplevelInfoState,
|
wayland::{
|
||||||
|
handlers::xdg_shell::popup::get_popup_toplevel, protocols::toplevel_info::ToplevelInfoState,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod grabs;
|
mod grabs;
|
||||||
|
|
@ -347,6 +352,77 @@ impl FloatingLayout {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_focus<'a>(
|
||||||
|
&mut self,
|
||||||
|
direction: FocusDirection,
|
||||||
|
seat: &Seat<State>,
|
||||||
|
_focus_stack: impl Iterator<Item = &'a CosmicMapped> + 'a,
|
||||||
|
) -> FocusResult {
|
||||||
|
let Some(target) = seat.get_keyboard().unwrap().current_focus() else {
|
||||||
|
return FocusResult::None
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(focused) = (match target {
|
||||||
|
KeyboardFocusTarget::Popup(popup) => {
|
||||||
|
let Some(toplevel_surface) = (match popup {
|
||||||
|
PopupKind::Xdg(xdg) => get_popup_toplevel(&xdg),
|
||||||
|
}) else {
|
||||||
|
return FocusResult::None
|
||||||
|
};
|
||||||
|
self.space.elements().find(|elem| elem.wl_surface().as_ref() == Some(&toplevel_surface))
|
||||||
|
},
|
||||||
|
KeyboardFocusTarget::Element(elem) => self.space.elements().find(|e| *e == &elem),
|
||||||
|
_ => None,
|
||||||
|
}) else {
|
||||||
|
return FocusResult::None
|
||||||
|
};
|
||||||
|
|
||||||
|
if focused.handle_focus(direction, None) {
|
||||||
|
return FocusResult::Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
let geometry = self.space.element_geometry(focused).unwrap();
|
||||||
|
|
||||||
|
let next = match direction {
|
||||||
|
FocusDirection::Up => self.space.elements().min_by_key(|other| {
|
||||||
|
let res = geometry.loc.y - self.space.element_geometry(other).unwrap().loc.y;
|
||||||
|
if res.is_positive() {
|
||||||
|
res
|
||||||
|
} else {
|
||||||
|
i32::MAX
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
FocusDirection::Down => self.space.elements().max_by_key(|other| {
|
||||||
|
let res = geometry.loc.y - self.space.element_geometry(other).unwrap().loc.y;
|
||||||
|
if res.is_negative() {
|
||||||
|
res
|
||||||
|
} else {
|
||||||
|
i32::MIN
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
FocusDirection::Left => self.space.elements().min_by_key(|other| {
|
||||||
|
let res = geometry.loc.x - self.space.element_geometry(other).unwrap().loc.x;
|
||||||
|
if res.is_positive() {
|
||||||
|
res
|
||||||
|
} else {
|
||||||
|
i32::MAX
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
FocusDirection::Right => self.space.elements().max_by_key(|other| {
|
||||||
|
let res = geometry.loc.x - self.space.element_geometry(other).unwrap().loc.x;
|
||||||
|
if res.is_negative() {
|
||||||
|
res
|
||||||
|
} else {
|
||||||
|
i32::MIN
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
_ => return FocusResult::None,
|
||||||
|
};
|
||||||
|
|
||||||
|
next.map(|elem| FocusResult::Some(KeyboardFocusTarget::Element(elem.clone())))
|
||||||
|
.unwrap_or(FocusResult::None)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mapped(&self) -> impl Iterator<Item = &CosmicMapped> {
|
pub fn mapped(&self) -> impl Iterator<Item = &CosmicMapped> {
|
||||||
self.space.elements().rev()
|
self.space.elements().rev()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
grabs::ResizeEdge,
|
grabs::ResizeEdge,
|
||||||
layout::Orientation,
|
layout::Orientation,
|
||||||
CosmicSurface, OutputNotMapped, OverviewMode, ResizeDirection, ResizeMode, Trigger,
|
CosmicSurface, FocusResult, OutputNotMapped, OverviewMode, ResizeDirection, ResizeMode,
|
||||||
|
Trigger,
|
||||||
},
|
},
|
||||||
utils::{prelude::*, tween::EaseRectangle},
|
utils::{prelude::*, tween::EaseRectangle},
|
||||||
wayland::{
|
wayland::{
|
||||||
|
|
@ -131,13 +132,6 @@ impl std::ops::Not for Direction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum FocusResult {
|
|
||||||
None,
|
|
||||||
Handled,
|
|
||||||
Some(KeyboardFocusTarget),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum MoveResult {
|
pub enum MoveResult {
|
||||||
Done,
|
Done,
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ use super::{
|
||||||
},
|
},
|
||||||
focus::{
|
focus::{
|
||||||
target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup},
|
target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup},
|
||||||
FocusStack, FocusStackMut,
|
FocusDirection, FocusStack, FocusStackMut,
|
||||||
},
|
},
|
||||||
grabs::{ResizeEdge, ResizeGrab},
|
grabs::{ResizeEdge, ResizeGrab},
|
||||||
layout::tiling::{Data, NodeDesc},
|
layout::tiling::{Data, NodeDesc},
|
||||||
|
|
@ -133,6 +133,25 @@ pub enum ManagedState {
|
||||||
Floating,
|
Floating,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum FocusResult {
|
||||||
|
None,
|
||||||
|
Handled,
|
||||||
|
Some(KeyboardFocusTarget),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FocusResult {
|
||||||
|
pub fn or_else<F>(self, f: F) -> FocusResult
|
||||||
|
where
|
||||||
|
F: FnOnce() -> FocusResult,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
FocusResult::None => f(),
|
||||||
|
x => x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Workspace {
|
impl Workspace {
|
||||||
pub fn new(handle: WorkspaceHandle, tiling_enabled: bool, gaps: (u8, u8)) -> Workspace {
|
pub fn new(handle: WorkspaceHandle, tiling_enabled: bool, gaps: (u8, u8)) -> Workspace {
|
||||||
Workspace {
|
Workspace {
|
||||||
|
|
@ -795,6 +814,25 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_focus<'a>(
|
||||||
|
&mut self,
|
||||||
|
direction: FocusDirection,
|
||||||
|
seat: &Seat<State>,
|
||||||
|
swap_desc: Option<NodeDesc>,
|
||||||
|
) -> FocusResult {
|
||||||
|
if self.fullscreen.contains_key(&seat.active_output()) {
|
||||||
|
return FocusResult::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let focus_stack = self.focus_stack.get(seat);
|
||||||
|
self.floating_layer
|
||||||
|
.next_focus(direction, seat, focus_stack.iter())
|
||||||
|
.or_else(|| {
|
||||||
|
self.tiling_layer
|
||||||
|
.next_focus(direction, seat, focus_stack.iter(), swap_desc)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render_output<'a, R>(
|
pub fn render_output<'a, R>(
|
||||||
&self,
|
&self,
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue