tiling: Allow orientation of active container to be swapped

This commit is contained in:
Victoria Brekenfeld 2022-03-29 14:41:09 +02:00
parent 2c311c67d1
commit b3ff2a7ca3
9 changed files with 105 additions and 18 deletions

View file

@ -27,6 +27,9 @@
(modifiers: [Logo], key: "Right"): Focus(Right), (modifiers: [Logo], key: "Right"): Focus(Right),
(modifiers: [Logo], key: "Up"): Focus(Up), (modifiers: [Logo], key: "Up"): Focus(Up),
(modifiers: [Logo], key: "Down"): Focus(Down), (modifiers: [Logo], key: "Down"): Focus(Down),
(modifiers: [Logo], key: "v"): Orientation(Vertical),
(modifiers: [Logo], key: "h"): Orientation(Horizontal),
(modifiers: [Ctrl], key: "Return"): Spawn("gnome-terminal"), (modifiers: [Ctrl], key: "Return"): Spawn("gnome-terminal"),
} },
workspace_mode: OutputBound,
) )

View file

@ -12,6 +12,7 @@ use xkbcommon::xkb;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Config { pub struct Config {
pub key_bindings: HashMap<KeyPattern, Action>, pub key_bindings: HashMap<KeyPattern, Action>,
pub workspace_mode: crate::shell::Mode,
} }
impl Config { impl Config {
@ -39,6 +40,7 @@ impl Config {
Config { Config {
key_bindings: HashMap::new(), key_bindings: HashMap::new(),
workspace_mode: crate::shell::Mode::global(),
} }
} }
} }
@ -180,6 +182,7 @@ pub enum Action {
Workspace(u8), Workspace(u8),
MoveToWorkspace(u8), MoveToWorkspace(u8),
Focus(FocusAction), Focus(FocusAction),
Orientation(crate::shell::layout::Orientation),
Spawn(String), Spawn(String),
} }

View file

@ -283,6 +283,15 @@ impl Common {
Action::Focus(focus) => match focus { Action::Focus(focus) => match focus {
_ => { /* TODO */ } _ => { /* TODO */ }
}, },
Action::Orientation(orientation) => {
let output = active_output(seat, &self);
self.shell.set_orientation(
&seat,
&output,
*orientation,
);
return FilterResult::Intercept(());
}
Action::Spawn(command) => { Action::Spawn(command) => {
if let Err(err) = if let Err(err) =
std::process::Command::new("/bin/sh") std::process::Command::new("/bin/sh")

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{input::active_output, state::State, utils::SurfaceDropNotifier}; use crate::{config::Config, input::active_output, state::State, utils::SurfaceDropNotifier};
use smithay::{ use smithay::{
backend::renderer::utils::on_commit_buffer_handler, backend::renderer::utils::on_commit_buffer_handler,
desktop::{ desktop::{
@ -27,7 +27,7 @@ use smithay::{
}; };
use std::{cell::Cell, rc::Rc, sync::Mutex}; use std::{cell::Cell, rc::Rc, sync::Mutex};
pub fn init_shell(display: &mut Display) -> super::Shell { pub fn init_shell(config: &Config, display: &mut Display) -> super::Shell {
compositor_init( compositor_init(
display, display,
move |surface, mut ddata| { move |surface, mut ddata| {
@ -234,7 +234,7 @@ pub fn init_shell(display: &mut Display) -> super::Shell {
None, None,
); );
super::Shell::new(popup_grab) super::Shell::new(config, popup_grab)
} }
fn check_grab_preconditions( fn check_grab_preconditions(

View file

@ -14,6 +14,12 @@ pub mod combined;
pub mod floating; pub mod floating;
pub mod tiling; pub mod tiling;
#[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Orientation {
Horizontal,
Vertical,
}
pub trait Layout { pub trait Layout {
fn map_window<'a>( fn map_window<'a>(
&mut self, &mut self,
@ -25,6 +31,15 @@ pub trait Layout {
fn refresh(&mut self, space: &mut Space); fn refresh(&mut self, space: &mut Space);
//fn unmap_window(&mut self, space: &mut Space, window: &Window); //fn unmap_window(&mut self, space: &mut Space, window: &Window);
fn update_orientation<'a>(
&mut self,
orientation: Orientation,
seat: &Seat,
space: &mut Space,
focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
) {
let _ = (orientation, seat, space, focus_stack);
}
fn maximize_request(&mut self, space: &mut Space, window: &Window, output: &Output) { fn maximize_request(&mut self, space: &mut Space, window: &Window, output: &Output) {
let _ = (space, window, output); let _ = (space, window, output);
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::shell::layout::Layout; use crate::shell::layout::{Layout, Orientation};
use id_tree::{InsertBehavior, MoveBehavior, Node, NodeId, NodeIdError, RemoveBehavior, Tree}; use id_tree::{InsertBehavior, MoveBehavior, Node, NodeId, NodeIdError, RemoveBehavior, Tree};
use smithay::{ use smithay::{
desktop::{layer_map_for_output, Kind, Space, Window}, desktop::{layer_map_for_output, Kind, Space, Window},
@ -16,12 +16,6 @@ pub struct TilingLayout {
gaps: (i32, i32), gaps: (i32, i32),
} }
#[derive(Debug)]
pub enum Orientation {
Horizontal,
Vertical,
}
#[derive(Debug)] #[derive(Debug)]
pub enum Data { pub enum Data {
Fork { Fork {
@ -143,6 +137,50 @@ impl Layout for TilingLayout {
self.refresh(space); self.refresh(space);
} }
fn update_orientation<'a>(
&mut self,
new_orientation: Orientation,
seat: &Seat,
space: &mut Space,
mut focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
) {
{
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 = &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 &mut Data::Fork {
ref mut orientation,
..
} = tree.get_mut(&parent_id).unwrap().data_mut()
{
*orientation = new_orientation;
break;
}
node_id = parent_id;
}
}
}
self.refresh(space);
}
fn refresh(&mut self, space: &mut Space) { fn refresh(&mut self, space: &mut Space) {
while let Some(dead_windows) = while let Some(dead_windows) =
Some(update_space_positions(self.idx, space, self.gaps)).filter(|v| !v.is_empty()) Some(update_space_positions(self.idx, space, self.gaps)).filter(|v| !v.is_empty())

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::config::Config;
pub use smithay::{ pub use smithay::{
desktop::{PopupGrab, PopupManager, PopupUngrabStrategy, Space, Window}, desktop::{PopupGrab, PopupManager, PopupUngrabStrategy, Space, Window},
reexports::wayland_server::protocol::wl_surface::WlSurface, reexports::wayland_server::protocol::wl_surface::WlSurface,
@ -33,10 +34,13 @@ impl ActiveWorkspace {
} }
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, serde::Deserialize, PartialEq, Eq, Clone, Copy)]
pub enum Mode { pub enum Mode {
OutputBound, OutputBound,
Global { active: usize }, Global {
#[serde(default)]
active: usize,
},
} }
impl Mode { impl Mode {
@ -60,11 +64,11 @@ pub struct Shell {
const UNINIT_SPACE: MaybeUninit<Workspace> = MaybeUninit::uninit(); const UNINIT_SPACE: MaybeUninit<Workspace> = MaybeUninit::uninit();
impl Shell { impl Shell {
fn new(popup_grab: Rc<Cell<Option<PopupGrab>>>) -> Self { fn new(config: &Config, popup_grab: Rc<Cell<Option<PopupGrab>>>) -> Self {
Shell { Shell {
popups: PopupManager::new(None), popups: PopupManager::new(None),
popup_grab, popup_grab,
mode: Mode::global(), mode: config.workspace_mode,
outputs: Vec::new(), outputs: Vec::new(),
spaces: unsafe { spaces: unsafe {
let mut spaces = [UNINIT_SPACE; MAX_WORKSPACES]; let mut spaces = [UNINIT_SPACE; MAX_WORKSPACES];
@ -392,4 +396,14 @@ impl Shell {
} }
} }
} }
pub fn set_orientation(
&mut self,
seat: &Seat,
output: &Output,
orientation: layout::Orientation,
) {
self.active_space_mut(output)
.update_orientation(seat, orientation)
}
} }

View file

@ -63,6 +63,11 @@ impl Workspace {
self.space.refresh(); self.space.refresh();
} }
pub fn update_orientation(&mut self, seat: &Seat, orientation: layout::Orientation) {
self.layout
.update_orientation(orientation, seat, &mut self.space, self.focus_stack.iter())
}
pub fn maximize_request(&mut self, window: &Window, output: &Output) { pub fn maximize_request(&mut self, window: &Window, output: &Output) {
self.layout self.layout
.maximize_request(&mut self.space, window, output) .maximize_request(&mut self.space, window, output)

View file

@ -135,9 +135,10 @@ impl State {
handle: LoopHandle<'static, State>, handle: LoopHandle<'static, State>,
log: LogState, log: LogState,
) -> State { ) -> State {
let config = Config::load();
init_shm_global(&mut display, vec![], None); init_shm_global(&mut display, vec![], None);
init_xdg_output_manager(&mut display, None); init_xdg_output_manager(&mut display, None);
let shell = init_shell(&mut display); let shell = init_shell(&config, &mut display);
let initial_seat = crate::input::add_seat(&mut display, "seat-0".into()); let initial_seat = crate::input::add_seat(&mut display, "seat-0".into());
init_data_device( init_data_device(
&mut display, &mut display,
@ -170,8 +171,7 @@ impl State {
State { State {
common: Common { common: Common {
config: Config::load(), config,
display: Rc::new(RefCell::new(display)), display: Rc::new(RefCell::new(display)),
socket, socket,
event_loop_handle: handle, event_loop_handle: handle,