input: Implement focus switched on tiling layout
This commit is contained in:
parent
f7ac9654d1
commit
69c71179d4
7 changed files with 336 additions and 166 deletions
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::shell::layout::FocusDirection;
|
||||
use serde::Deserialize;
|
||||
use smithay::wayland::seat::Keysym;
|
||||
pub use smithay::{
|
||||
|
|
@ -181,15 +182,7 @@ pub enum Action {
|
|||
Close,
|
||||
Workspace(u8),
|
||||
MoveToWorkspace(u8),
|
||||
Focus(FocusAction),
|
||||
Focus(FocusDirection),
|
||||
Orientation(crate::shell::layout::Orientation),
|
||||
Spawn(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum FocusAction {
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -302,9 +302,15 @@ impl Common {
|
|||
*num,
|
||||
);
|
||||
}
|
||||
Action::Focus(focus) => match focus {
|
||||
_ => { /* TODO */ }
|
||||
},
|
||||
Action::Focus(focus) => {
|
||||
let current_output = active_output(seat, &self);
|
||||
self.shell.move_focus(
|
||||
seat,
|
||||
¤t_output,
|
||||
*focus,
|
||||
self.seats.iter(),
|
||||
);
|
||||
}
|
||||
Action::Orientation(orientation) => {
|
||||
let output = active_output(seat, &self);
|
||||
self.shell.set_orientation(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use super::Layout;
|
||||
use super::{FocusDirection, Layout, Orientation};
|
||||
use smithay::{
|
||||
desktop::{Space, Window},
|
||||
reexports::wayland_protocols::xdg_shell::server::xdg_toplevel::ResizeEdge,
|
||||
|
|
@ -108,4 +108,44 @@ impl<A: Layout, B: Layout> Layout for Combined<A, B> {
|
|||
.resize_request(space, window, seat, serial, start_data, edges)
|
||||
}
|
||||
}
|
||||
|
||||
fn move_focus<'a>(
|
||||
&mut self,
|
||||
direction: FocusDirection,
|
||||
seat: &Seat,
|
||||
space: &mut Space,
|
||||
focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
|
||||
) -> Option<Window> {
|
||||
let focus_stack = focus_stack.collect::<Vec<_>>();
|
||||
match self.first.move_focus(
|
||||
direction,
|
||||
seat,
|
||||
space,
|
||||
Box::new(focus_stack.clone().into_iter()),
|
||||
) {
|
||||
Some(window) => Some(window),
|
||||
None => {
|
||||
self.second
|
||||
.move_focus(direction, seat, space, Box::new(focus_stack.into_iter()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_orientation<'a>(
|
||||
&mut self,
|
||||
orientation: Orientation,
|
||||
seat: &Seat,
|
||||
space: &mut Space,
|
||||
focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
|
||||
) {
|
||||
let focus_stack = focus_stack.collect::<Vec<_>>();
|
||||
self.first.update_orientation(
|
||||
orientation,
|
||||
seat,
|
||||
space,
|
||||
Box::new(focus_stack.clone().into_iter()),
|
||||
);
|
||||
self.second
|
||||
.update_orientation(orientation, seat, space, Box::new(focus_stack.into_iter()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,14 @@ pub enum Orientation {
|
|||
Vertical,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum FocusDirection {
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
pub trait Layout {
|
||||
fn map_window<'a>(
|
||||
&mut self,
|
||||
|
|
@ -34,6 +42,16 @@ pub trait Layout {
|
|||
fn refresh(&mut self, space: &mut Space);
|
||||
fn unmap_window(&mut self, space: &mut Space, window: &Window);
|
||||
|
||||
fn move_focus<'a>(
|
||||
&mut self,
|
||||
direction: FocusDirection,
|
||||
seat: &Seat,
|
||||
space: &mut Space,
|
||||
focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
|
||||
) -> Option<Window> {
|
||||
let _ = (direction, seat, space, focus_stack);
|
||||
None
|
||||
}
|
||||
fn update_orientation<'a>(
|
||||
&mut self,
|
||||
orientation: Orientation,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::shell::layout::{Layout, Orientation};
|
||||
use crate::shell::layout::{FocusDirection, Layout, Orientation};
|
||||
use id_tree::{InsertBehavior, MoveBehavior, Node, NodeId, NodeIdError, RemoveBehavior, Tree};
|
||||
use smithay::{
|
||||
desktop::{layer_map_for_output, Kind, Space, Window},
|
||||
|
|
@ -119,12 +119,12 @@ impl Layout for TilingLayout {
|
|||
Ok(window_id)
|
||||
} else {
|
||||
// we create a new fork
|
||||
new_fork(tree, node_id, new_window)
|
||||
TilingLayout::new_fork(tree, node_id, new_window)
|
||||
}
|
||||
} else {
|
||||
// nothing? then we add to the root
|
||||
if let Some(root_id) = tree.root_node_id().cloned() {
|
||||
new_fork(tree, &root_id, new_window)
|
||||
TilingLayout::new_fork(tree, &root_id, new_window)
|
||||
} else {
|
||||
tree.insert(new_window, InsertBehavior::AsRoot)
|
||||
}
|
||||
|
|
@ -146,12 +146,76 @@ impl Layout for TilingLayout {
|
|||
self.refresh(space);
|
||||
}
|
||||
|
||||
fn move_focus<'a>(
|
||||
&mut self,
|
||||
direction: FocusDirection,
|
||||
seat: &Seat,
|
||||
space: &mut Space,
|
||||
focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
|
||||
) -> Option<Window> {
|
||||
let output = super::output_from_seat(seat, space);
|
||||
output
|
||||
.user_data()
|
||||
.insert_if_missing(|| RefCell::new(OutputInfo::default()));
|
||||
let mut output_info = output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputInfo>>()
|
||||
.unwrap()
|
||||
.borrow_mut();
|
||||
let tree = output_info.trees.entry(self.idx).or_insert_with(Tree::new);
|
||||
|
||||
if let Some(last_active) = TilingLayout::last_active(tree, focus_stack) {
|
||||
let mut node_id = last_active;
|
||||
while let Some((fork, child)) = TilingLayout::find_fork(tree, node_id) {
|
||||
if let &Data::Fork {
|
||||
ref orientation, ..
|
||||
} = tree.get(&fork).unwrap().data()
|
||||
{
|
||||
// found a fork
|
||||
// which child are we?
|
||||
let first = tree.children_ids(&fork).unwrap().next() == Some(&child);
|
||||
let focus_subtree = match (first, orientation, direction) {
|
||||
(true, Orientation::Horizontal, FocusDirection::Down)
|
||||
| (true, Orientation::Vertical, FocusDirection::Right) => {
|
||||
tree.children_ids(&fork).unwrap().skip(1).next()
|
||||
}
|
||||
(false, Orientation::Horizontal, FocusDirection::Up)
|
||||
| (false, Orientation::Vertical, FocusDirection::Left) => {
|
||||
tree.children_ids(&fork).unwrap().next()
|
||||
}
|
||||
_ => None, // continue iterating
|
||||
};
|
||||
|
||||
if focus_subtree.is_some() {
|
||||
let mut node_id = focus_subtree;
|
||||
while node_id.is_some()
|
||||
&& !matches!(
|
||||
tree.get(node_id.as_ref().unwrap()).unwrap().data(),
|
||||
Data::Window(_)
|
||||
)
|
||||
{
|
||||
// TODO, if ndoe_id is a stack, we want to assign the active node instead of the first
|
||||
node_id = tree.children_ids(node_id.as_ref().unwrap()).unwrap().next();
|
||||
}
|
||||
if let Some(Data::Window(window)) =
|
||||
node_id.and_then(|i| tree.get(&i).ok()).map(|n| n.data())
|
||||
{
|
||||
return Some(window.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
node_id = fork;
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
fn update_orientation<'a>(
|
||||
&mut self,
|
||||
new_orientation: Orientation,
|
||||
seat: &Seat,
|
||||
space: &mut Space,
|
||||
mut focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
|
||||
focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
|
||||
) {
|
||||
{
|
||||
let output = super::output_from_seat(seat, space);
|
||||
|
|
@ -165,25 +229,15 @@ impl Layout for TilingLayout {
|
|||
.borrow_mut();
|
||||
let tree = &mut output_info.trees.entry(self.idx).or_insert_with(Tree::new);
|
||||
|
||||
let last_active = focus_stack
|
||||
.find_map(|window| tree.root_node_id()
|
||||
.and_then(|root| tree.traverse_pre_order_ids(root).unwrap()
|
||||
.find(|id| matches!(tree.get(id).map(|n| n.data()), Ok(Data::Window(w)) if w == window))
|
||||
)
|
||||
);
|
||||
|
||||
if let Some(ref node_id) = last_active {
|
||||
let mut node_id = node_id.clone();
|
||||
while let Some(parent_id) = tree.get(&node_id).unwrap().parent().cloned() {
|
||||
if let Some(last_active) = TilingLayout::last_active(tree, focus_stack) {
|
||||
if let Some((fork, _child)) = TilingLayout::find_fork(tree, last_active) {
|
||||
if let &mut Data::Fork {
|
||||
ref mut orientation,
|
||||
..
|
||||
} = tree.get_mut(&parent_id).unwrap().data_mut()
|
||||
} = tree.get_mut(&fork).unwrap().data_mut()
|
||||
{
|
||||
*orientation = new_orientation;
|
||||
break;
|
||||
}
|
||||
node_id = parent_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -191,8 +245,10 @@ impl Layout for TilingLayout {
|
|||
}
|
||||
|
||||
fn refresh(&mut self, space: &mut Space) {
|
||||
while let Some(dead_windows) =
|
||||
Some(update_space_positions(self.idx, space, self.gaps)).filter(|v| !v.is_empty())
|
||||
while let Some(dead_windows) = Some(TilingLayout::update_space_positions(
|
||||
self.idx, space, self.gaps,
|
||||
))
|
||||
.filter(|v| !v.is_empty())
|
||||
{
|
||||
for window in dead_windows {
|
||||
self.unmap_window(&window);
|
||||
|
|
@ -226,15 +282,16 @@ impl Layout for TilingLayout {
|
|||
let tree = &mut output_info.trees.entry(self.idx).or_insert_with(Tree::new);
|
||||
|
||||
let mut node_id = info.borrow().node.clone();
|
||||
while let Some(parent_id) = tree.get(&node_id).unwrap().parent().cloned() {
|
||||
|
||||
while let Some((fork, child)) = TilingLayout::find_fork(tree, node_id) {
|
||||
if let &Data::Fork {
|
||||
ref orientation,
|
||||
ref ratio,
|
||||
} = tree.get(&parent_id).unwrap().data()
|
||||
} = tree.get(&fork).unwrap().data()
|
||||
{
|
||||
// found a fork
|
||||
// which child are we?
|
||||
let first = tree.children_ids(&parent_id).unwrap().next() == Some(&node_id);
|
||||
let first = tree.children_ids(&fork).unwrap().next() == Some(&child);
|
||||
match (first, orientation, edges) {
|
||||
(true, Orientation::Horizontal, ResizeEdge::Bottom)
|
||||
| (false, Orientation::Horizontal, ResizeEdge::Top)
|
||||
|
|
@ -242,22 +299,19 @@ impl Layout for TilingLayout {
|
|||
| (false, Orientation::Vertical, ResizeEdge::Left) => {
|
||||
let grab = ResizeForkGrab {
|
||||
start_data,
|
||||
node_id: parent_id,
|
||||
node_id: fork,
|
||||
initial_ratio: *ratio,
|
||||
idx: self.idx,
|
||||
output: output.clone(),
|
||||
};
|
||||
|
||||
slog_scope::debug!("Tiling resize grabs");
|
||||
pointer.set_grab(grab, serial, 0);
|
||||
return;
|
||||
}
|
||||
(x, y, z) => {
|
||||
slog_scope::debug!("Nope: {:?}, {:?}, {:?}", x, y, z);
|
||||
}
|
||||
_ => {} // continue iterating
|
||||
}
|
||||
}
|
||||
node_id = parent_id;
|
||||
node_id = fork;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -265,15 +319,42 @@ impl Layout for TilingLayout {
|
|||
}
|
||||
|
||||
impl TilingLayout {
|
||||
fn last_active<'a>(
|
||||
tree: &mut Tree<Data>,
|
||||
mut focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
|
||||
) -> Option<NodeId> {
|
||||
let last_active = focus_stack
|
||||
.find_map(|window| tree.root_node_id()
|
||||
.and_then(|root| tree.traverse_pre_order_ids(root).unwrap()
|
||||
.find(|id| matches!(tree.get(id).map(|n| n.data()), Ok(Data::Window(w)) if w == window))
|
||||
)
|
||||
);
|
||||
|
||||
last_active
|
||||
}
|
||||
|
||||
fn find_fork(tree: &mut Tree<Data>, mut node_id: NodeId) -> Option<(NodeId, NodeId)> {
|
||||
while let Some(parent_id) = tree.get(&node_id).unwrap().parent().cloned() {
|
||||
if let &Data::Fork { .. } = tree.get(&parent_id).unwrap().data() {
|
||||
return Some((parent_id, node_id));
|
||||
}
|
||||
node_id = parent_id;
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn unmap_window(&mut self, window: &Window) {
|
||||
if let Some(info) = window.user_data().get::<RefCell<WindowInfo>>() {
|
||||
let output = &info.borrow().output;
|
||||
output
|
||||
.user_data()
|
||||
.insert_if_missing(|| RefCell::new(OutputInfo::default()));
|
||||
let mut output_info = output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputInfo>>()
|
||||
.unwrap()
|
||||
.borrow_mut();
|
||||
let tree = &mut output_info.trees.entry(self.idx).or_insert_with(Tree::new);
|
||||
let tree = output_info.trees.entry(self.idx).or_insert_with(Tree::new);
|
||||
|
||||
let node_id = info.borrow().node.clone();
|
||||
let parent_id = tree
|
||||
|
|
@ -335,151 +416,153 @@ impl TilingLayout {
|
|||
None => {} // root
|
||||
_ => unreachable!(),
|
||||
}
|
||||
// update_space_positions(space, self.gaps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_fork(
|
||||
tree: &mut Tree<Data>,
|
||||
old_id: &NodeId,
|
||||
new: Node<Data>,
|
||||
) -> Result<NodeId, NodeIdError> {
|
||||
let new_fork = Node::new(Data::fork());
|
||||
let old = tree.get(old_id)?;
|
||||
let parent_id = old.parent().cloned();
|
||||
let pos = parent_id.as_ref().and_then(|parent_id| {
|
||||
tree.children_ids(parent_id)
|
||||
.unwrap()
|
||||
.position(|id| id == old_id)
|
||||
});
|
||||
fn new_fork(
|
||||
tree: &mut Tree<Data>,
|
||||
old_id: &NodeId,
|
||||
new: Node<Data>,
|
||||
) -> Result<NodeId, NodeIdError> {
|
||||
let new_fork = Node::new(Data::fork());
|
||||
let old = tree.get(old_id)?;
|
||||
let parent_id = old.parent().cloned();
|
||||
let pos = parent_id.as_ref().and_then(|parent_id| {
|
||||
tree.children_ids(parent_id)
|
||||
.unwrap()
|
||||
.position(|id| id == old_id)
|
||||
});
|
||||
|
||||
let fork_id = tree
|
||||
.insert(
|
||||
new_fork,
|
||||
if let Some(parent) = parent_id.as_ref() {
|
||||
InsertBehavior::UnderNode(parent)
|
||||
} else {
|
||||
InsertBehavior::AsRoot
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let fork_id = tree
|
||||
.insert(
|
||||
new_fork,
|
||||
if let Some(parent) = parent_id.as_ref() {
|
||||
InsertBehavior::UnderNode(parent)
|
||||
} else {
|
||||
InsertBehavior::AsRoot
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
tree.move_node(old_id, MoveBehavior::ToParent(&fork_id))
|
||||
.unwrap();
|
||||
// keep position
|
||||
if let Some(old_pos) = pos {
|
||||
tree.make_nth_sibling(&fork_id, old_pos).unwrap();
|
||||
tree.move_node(old_id, MoveBehavior::ToParent(&fork_id))
|
||||
.unwrap();
|
||||
// keep position
|
||||
if let Some(old_pos) = pos {
|
||||
tree.make_nth_sibling(&fork_id, old_pos).unwrap();
|
||||
}
|
||||
tree.insert(new, InsertBehavior::UnderNode(&fork_id))
|
||||
}
|
||||
tree.insert(new, InsertBehavior::UnderNode(&fork_id))
|
||||
}
|
||||
|
||||
fn update_space_positions(idx: u8, space: &mut Space, gaps: (i32, i32)) -> Vec<Window> {
|
||||
let mut dead_windows = Vec::new();
|
||||
let (outer, inner) = gaps;
|
||||
for output in space.outputs().cloned().collect::<Vec<_>>().into_iter() {
|
||||
if let Some(mut info) = output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputInfo>>()
|
||||
.map(|x| x.borrow_mut())
|
||||
{
|
||||
let tree = &mut info.trees.entry(idx).or_insert_with(Tree::new);
|
||||
if let Some(root) = tree.root_node_id() {
|
||||
let mut stack = Vec::new();
|
||||
fn update_space_positions(idx: u8, space: &mut Space, gaps: (i32, i32)) -> Vec<Window> {
|
||||
let mut dead_windows = Vec::new();
|
||||
let (outer, inner) = gaps;
|
||||
for output in space.outputs().cloned().collect::<Vec<_>>().into_iter() {
|
||||
if let Some(mut info) = output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputInfo>>()
|
||||
.map(|x| x.borrow_mut())
|
||||
{
|
||||
let tree = &mut info.trees.entry(idx).or_insert_with(Tree::new);
|
||||
if let Some(root) = tree.root_node_id() {
|
||||
let mut stack = Vec::new();
|
||||
|
||||
let mut geo = Some(layer_map_for_output(&output).non_exclusive_zone());
|
||||
// TODO saturate? minimum?
|
||||
if let Some(mut geo) = geo.as_mut() {
|
||||
geo.loc.x += outer;
|
||||
geo.loc.y += outer;
|
||||
geo.size.w -= outer * 2;
|
||||
geo.size.h -= outer * 2;
|
||||
}
|
||||
let mut geo = Some(layer_map_for_output(&output).non_exclusive_zone());
|
||||
// TODO saturate? minimum?
|
||||
if let Some(mut geo) = geo.as_mut() {
|
||||
geo.loc.x += outer;
|
||||
geo.loc.y += outer;
|
||||
geo.size.w -= outer * 2;
|
||||
geo.size.h -= outer * 2;
|
||||
}
|
||||
|
||||
for node in tree.traverse_pre_order(root).unwrap() {
|
||||
let geo = stack.pop().unwrap_or(geo);
|
||||
match node.data() {
|
||||
Data::Fork { orientation, ratio } => {
|
||||
if let Some(geo) = geo {
|
||||
match orientation {
|
||||
Orientation::Horizontal => {
|
||||
let top_size = (
|
||||
geo.size.w,
|
||||
((geo.size.h as f64) * ratio).ceil() as i32,
|
||||
);
|
||||
stack.push(Some(Rectangle::from_loc_and_size(
|
||||
(geo.loc.x, geo.loc.y + top_size.1),
|
||||
(geo.size.w, geo.size.h - top_size.1),
|
||||
)));
|
||||
stack.push(Some(Rectangle::from_loc_and_size(
|
||||
geo.loc, top_size,
|
||||
)));
|
||||
for node in tree.traverse_pre_order(root).unwrap() {
|
||||
let geo = stack.pop().unwrap_or(geo);
|
||||
match node.data() {
|
||||
Data::Fork { orientation, ratio } => {
|
||||
if let Some(geo) = geo {
|
||||
match orientation {
|
||||
Orientation::Horizontal => {
|
||||
let top_size = (
|
||||
geo.size.w,
|
||||
((geo.size.h as f64) * ratio).ceil() as i32,
|
||||
);
|
||||
stack.push(Some(Rectangle::from_loc_and_size(
|
||||
(geo.loc.x, geo.loc.y + top_size.1),
|
||||
(geo.size.w, geo.size.h - top_size.1),
|
||||
)));
|
||||
stack.push(Some(Rectangle::from_loc_and_size(
|
||||
geo.loc, top_size,
|
||||
)));
|
||||
}
|
||||
Orientation::Vertical => {
|
||||
let left_size = (
|
||||
((geo.size.w as f64) * ratio).ceil() as i32,
|
||||
geo.size.h,
|
||||
);
|
||||
stack.push(Some(Rectangle::from_loc_and_size(
|
||||
(geo.loc.x + left_size.0, geo.loc.y),
|
||||
(geo.size.w - left_size.0, geo.size.h),
|
||||
)));
|
||||
stack.push(Some(Rectangle::from_loc_and_size(
|
||||
geo.loc, left_size,
|
||||
)));
|
||||
}
|
||||
}
|
||||
Orientation::Vertical => {
|
||||
let left_size = (
|
||||
((geo.size.w as f64) * ratio).ceil() as i32,
|
||||
geo.size.h,
|
||||
);
|
||||
stack.push(Some(Rectangle::from_loc_and_size(
|
||||
(geo.loc.x + left_size.0, geo.loc.y),
|
||||
(geo.size.w - left_size.0, geo.size.h),
|
||||
)));
|
||||
stack.push(Some(Rectangle::from_loc_and_size(
|
||||
geo.loc, left_size,
|
||||
)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stack.push(None);
|
||||
stack.push(None);
|
||||
}
|
||||
}
|
||||
Data::Stack { active, len } => {
|
||||
for i in 0..*len {
|
||||
if i == *active {
|
||||
stack.push(geo);
|
||||
} else {
|
||||
stack.push(None);
|
||||
stack.push(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
Data::Window(window) => {
|
||||
if window.toplevel().alive() {
|
||||
if let Some(geo) = geo {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Kind::Xdg(xdg) = &window.toplevel() {
|
||||
let ret = xdg.with_pending_state(|state| {
|
||||
state.size = Some(
|
||||
(geo.size.w - inner * 2, geo.size.h - inner * 2)
|
||||
.into(),
|
||||
);
|
||||
state.states.set(XdgState::TiledLeft);
|
||||
state.states.set(XdgState::TiledRight);
|
||||
state.states.set(XdgState::TiledTop);
|
||||
state.states.set(XdgState::TiledBottom);
|
||||
});
|
||||
if ret.is_ok() {
|
||||
xdg.send_configure();
|
||||
}
|
||||
Data::Stack { active, len } => {
|
||||
for i in 0..*len {
|
||||
if i == *active {
|
||||
stack.push(geo);
|
||||
} else {
|
||||
stack.push(None);
|
||||
}
|
||||
let window_geo = window.geometry();
|
||||
space.map_window(
|
||||
&window,
|
||||
(
|
||||
geo.loc.x + inner - window_geo.loc.x,
|
||||
geo.loc.y + inner - window_geo.loc.y,
|
||||
),
|
||||
false,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
dead_windows.push(window.clone());
|
||||
}
|
||||
Data::Window(window) => {
|
||||
if window.toplevel().alive() {
|
||||
if let Some(geo) = geo {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Kind::Xdg(xdg) = &window.toplevel() {
|
||||
let ret = xdg.with_pending_state(|state| {
|
||||
state.size = Some(
|
||||
(
|
||||
geo.size.w - inner * 2,
|
||||
geo.size.h - inner * 2,
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
state.states.set(XdgState::TiledLeft);
|
||||
state.states.set(XdgState::TiledRight);
|
||||
state.states.set(XdgState::TiledTop);
|
||||
state.states.set(XdgState::TiledBottom);
|
||||
});
|
||||
if ret.is_ok() {
|
||||
xdg.send_configure();
|
||||
}
|
||||
}
|
||||
let window_geo = window.geometry();
|
||||
space.map_window(
|
||||
&window,
|
||||
(
|
||||
geo.loc.x + inner - window_geo.loc.x,
|
||||
geo.loc.y + inner - window_geo.loc.y,
|
||||
),
|
||||
false,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
dead_windows.push(window.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dead_windows
|
||||
}
|
||||
dead_windows
|
||||
}
|
||||
|
|
|
|||
|
|
@ -409,6 +409,22 @@ impl Shell {
|
|||
.update_orientation(seat, orientation)
|
||||
}
|
||||
|
||||
pub fn move_focus<'a>(
|
||||
&mut self,
|
||||
seat: &Seat,
|
||||
output: &Output,
|
||||
focus: layout::FocusDirection,
|
||||
seats: impl Iterator<Item = &'a Seat>,
|
||||
) {
|
||||
if let Some(surface) = self
|
||||
.active_space_mut(output)
|
||||
.move_focus(seat, focus)
|
||||
.and_then(|window| window.toplevel().get_surface().cloned())
|
||||
{
|
||||
self.set_focus(Some(&surface), seat, seats, None)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_focus<'a>(
|
||||
&mut self,
|
||||
surface: Option<&WlSurface>,
|
||||
|
|
|
|||
|
|
@ -126,6 +126,20 @@ impl Workspace {
|
|||
.update_orientation(orientation, seat, &mut self.space, focus_stack.iter())
|
||||
}
|
||||
|
||||
pub fn move_focus(&mut self, seat: &Seat, focus: layout::FocusDirection) -> Option<Window> {
|
||||
seat.user_data()
|
||||
.insert_if_missing(|| FocusStackData::new((HashMap::new(), IndexSet::new())));
|
||||
let focus_stack = FocusStackMut(RefMut::map(
|
||||
seat.user_data()
|
||||
.get::<FocusStackData>()
|
||||
.unwrap()
|
||||
.borrow_mut(),
|
||||
|map| map.0.entry(self.idx).or_insert_with(|| IndexSet::new()),
|
||||
));
|
||||
self.layout
|
||||
.move_focus(focus, seat, &mut self.space, focus_stack.iter())
|
||||
}
|
||||
|
||||
pub fn maximize_request(&mut self, window: &Window, output: &Output) {
|
||||
self.layout
|
||||
.maximize_request(&mut self.space, window, output)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue