tiling: Allow orientation of active container to be swapped
This commit is contained in:
parent
2c311c67d1
commit
b3ff2a7ca3
9 changed files with 105 additions and 18 deletions
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue