shell: Handle focus shortcuts for floating layer

This commit is contained in:
Victoria Brekenfeld 2023-09-20 16:30:37 +02:00
parent 63c073e3e5
commit 3d10ca6105
4 changed files with 122 additions and 20 deletions

View file

@ -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(&current_output); let workspace = self.common.shell.active_space_mut(&current_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(&current_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);
} }
} }

View file

@ -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()
} }

View file

@ -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,

View file

@ -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,