mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-11-14 21:04:04 +01:00
feat(wm): lock
Containers can be locked since the model came in, and a locked container keeps its index while others are inserted, removed or swapped around it; nothing could lock one. `komorebic toggle-lock` locks the focused container, or unlocks it, and the `LockMonitorWorkspaceContainer` and `UnlockMonitorWorkspaceContainer` messages lock and unlock a container by the index of its monitor, its workspace and itself, for a program such as a status bar. The vm-commands sweep locks and unlocks a container.
This commit is contained in:
1 parent
062fe57fac
commit
3cc5dceb7d
11 files changed
+325
-6
No files matched your search
@@ -140,8 +140,8 @@ another layout, `layout-ratios` and `scrolling-layout-columns` tune it,
|
||||
`toggle-tiling` stops it moving windows and starts it again,
|
||||
`preselect-direction` reserves a tile for the next window, `resize-edge` and
|
||||
`resize-axis` move the edges of the focused tile, `promote` brings the
|
||||
focused window to the largest tile, and `toggle-float` takes it out of the
|
||||
layout. The scrolling layout
|
||||
focused window to the largest tile, `toggle-float` takes it out of the
|
||||
layout, and `toggle-lock` keeps its container at its place. The scrolling layout
|
||||
is a strip of columns that runs past the edges of the monitor and scrolls to
|
||||
the window that has the focus.
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
```text
|
||||
Toggle a lock for the focused container, ensuring it will not be displaced by any new windows
|
||||
|
||||
Usage: toggle-lock
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
```
|
||||
@@ -302,6 +302,11 @@ any other, so its events find it, and [`Workspace::update`] leaves it where it i
|
||||
floated window goes is [`WindowManagementBehaviour::toggle_float_placement`]: by default it
|
||||
stays where it is.
|
||||
|
||||
`ToggleLock` locks the focused container, or unlocks it ([`WindowManager::toggle_lock`]), and
|
||||
`LockMonitorWorkspaceContainer` and `UnlockMonitorWorkspaceContainer` do the same for a
|
||||
container given by its indices. A lock changes nothing until containers are inserted, removed or
|
||||
swapped around it, which the workspace does through `LockableSequence`.
|
||||
|
||||
`ResizeWindowEdge` and `ResizeWindowAxis` resize the focused container
|
||||
([`WindowManager::resize_window`]). A resize is an adjustment of the container's tile, kept in
|
||||
[`Workspace::resize_dimensions`], one per container, which the layout applies when it calculates
|
||||
@@ -370,7 +375,7 @@ module's unit.
|
||||
- [`window_manager`](../../komorebi/src/window_manager.rs): the [`WindowManager`] and the
|
||||
operations on it (tile the workspace in front, tile every monitor, take a minimized
|
||||
window out, move the focus, move the focused container, change the layout, resize or
|
||||
promote the focused container, float a window).
|
||||
promote the focused container, float a window, lock a container).
|
||||
- [`desktop`](../../komorebi/src/desktop.rs): loads the monitors and the open windows from
|
||||
the backend.
|
||||
- [`window_manager_event`](../../komorebi/src/window_manager_event.rs) and
|
||||
@@ -434,7 +439,7 @@ the fake. The window manager is its only caller, through [`backend`]. The contra
|
||||
| The window manager asks for a backend that was never installed | runtime error: [`backend`] panics, naming [`set_backend`] and [`with_backend`] | `# Panics` on [`backend`] | none |
|
||||
| A test's backend does not outlive the test | framework path: [`with_backend`] restores the previous one on drop | `with_backend_puts_the_previous_backend_back_when_the_closure_panics` | none |
|
||||
| A command about a missing window is an error, not a panic | test | `a_command_about_a_window_nobody_opened_is_an_error` and `a_command_about_a_closed_window_is_an_error` against the fake, `a_command_about_a_window_the_table_does_not_know_is_an_error_and_sends_nothing` against the KWin backend | none |
|
||||
| A locked container keeps its index | framework path: a [`Workspace`] inserts, removes and swaps its containers through `LockableSequence` | `test_locked_containers_with_new_window` and `test_locked_containers_remove_window` | `containers_mut()` is the `VecDeque` itself |
|
||||
| A locked container keeps its index | framework path: a [`Workspace`] inserts, removes and swaps its containers through `LockableSequence` | `test_locked_containers_with_new_window`, `test_locked_containers_remove_window`, `a_window_that_opens_does_not_push_a_locked_container_from_its_index` | `containers_mut()` is the `VecDeque` itself |
|
||||
| A window komorebi does not manage is never moved | framework path: `handle_event` asks [`Window::should_manage`] before it acts on any event but a destroy | `dialogs_and_other_non_normal_windows_are_left_alone` | none |
|
||||
| A destroyed window leaves whichever workspace has it | framework path: the destroy is looked up in the index of managed windows, which is rebuilt at startup and before and after every event | `a_window_that_was_open_before_komorebi_started_is_removed_when_it_closes` | none |
|
||||
| The daemon does not start without KWin, unless it is told to run against the fake | startup check: [`connect`] fails, and the daemon exits with the error, code 1 | `without_a_session_bus_komorebi_exits_with_an_error_naming_it` | `--fake-backend` |
|
||||
@@ -572,7 +577,8 @@ A window is shown, and ends up on a tile:
|
||||
[`komorebi/tests/scrolling.rs`](../../komorebi/tests/scrolling.rs), the layout options and the
|
||||
scrolling layout; [`komorebi/tests/resize.rs`](../../komorebi/tests/resize.rs), resizing;
|
||||
[`komorebi/tests/promote.rs`](../../komorebi/tests/promote.rs), promoting;
|
||||
[`komorebi/tests/float.rs`](../../komorebi/tests/float.rs), floating.
|
||||
[`komorebi/tests/float.rs`](../../komorebi/tests/float.rs), floating;
|
||||
[`komorebi/tests/lock.rs`](../../komorebi/tests/lock.rs), locking.
|
||||
- [`nix/tests/vm/suites/scrolling`](../../nix/tests/vm/suites/scrolling/test.py): the scrolling
|
||||
strip in a real KWin, with its columns out of view off the screen.
|
||||
- [`nix/tests/vm/suites/commands`](../../nix/tests/vm/suites/commands/test.py): every layout,
|
||||
@@ -613,6 +619,7 @@ A window is shown, and ends up on a tile:
|
||||
[`Workspace::resize_dimensions`]: ../../komorebi/src/workspace.rs
|
||||
[`WindowManager::resize_window`]: ../../komorebi/src/window_manager.rs
|
||||
[`WindowManager::toggle_float`]: ../../komorebi/src/window_manager.rs
|
||||
[`WindowManager::toggle_lock`]: ../../komorebi/src/window_manager.rs
|
||||
[`WindowManagementBehaviour::toggle_float_placement`]: ../../komorebi/src/core/mod.rs
|
||||
[`WindowManager::promote_container_to_front`]: ../../komorebi/src/window_manager.rs
|
||||
[`WindowManager::promote_container_swap`]: ../../komorebi/src/window_manager.rs
|
||||
|
||||
@@ -55,6 +55,22 @@ komorebic promote-window left
|
||||
[`komorebic promote-focus`](../cli/promote-focus.md) gives the focus to the window on the first
|
||||
tile and moves nothing.
|
||||
|
||||
## Locking a window in its place
|
||||
|
||||
[`komorebic toggle-lock`](../cli/toggle-lock.md) locks the focused window's container at its
|
||||
place in the order of the workspace, and unlocks it again. Windows that open, close or move
|
||||
around a locked container leave it where it is: a new window that would go in its place goes
|
||||
after it. A window moved onto the place of a locked one with `move`, `cycle-move` or
|
||||
`promote-swap` is locked there instead, since the lock belongs to the place.
|
||||
|
||||
```sh
|
||||
komorebic toggle-lock
|
||||
```
|
||||
|
||||
The `LockMonitorWorkspaceContainer` and `UnlockMonitorWorkspaceContainer` messages lock and
|
||||
unlock a container by the index of its monitor, its workspace and itself, for a program such as
|
||||
a status bar. They have no subcommand.
|
||||
|
||||
## The pointer
|
||||
|
||||
The pointer follows the window that moved, unless
|
||||
|
||||
@@ -352,6 +352,9 @@ pub enum SocketMessage {
|
||||
PromoteSwap,
|
||||
PromoteFocus,
|
||||
PromoteWindow(OperationDirection),
|
||||
LockMonitorWorkspaceContainer(usize, usize, usize),
|
||||
UnlockMonitorWorkspaceContainer(usize, usize, usize),
|
||||
ToggleLock,
|
||||
ToggleFloat,
|
||||
// Current Workspace Commands
|
||||
ChangeLayout(DefaultLayout),
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
//! already, and **CancelPreselect** gives the reserved place up.
|
||||
//! - **MouseFollowsFocus** and **ToggleMouseFollowsFocus** set whether the pointer is moved to
|
||||
//! the window that is given the focus.
|
||||
//! - **ToggleLock** locks the focused container at its index, or unlocks it
|
||||
//! ([`WindowManager::toggle_lock`]), and **LockMonitorWorkspaceContainer** and
|
||||
//! **UnlockMonitorWorkspaceContainer** do the same for a container given by the index of its
|
||||
//! monitor, its workspace and itself.
|
||||
//! - **ToggleFloat** takes the focused window out of the layout into the floating windows of the
|
||||
//! workspace, which komorebi does not move, or puts a floating window back
|
||||
//! ([`WindowManager::toggle_float`]).
|
||||
@@ -147,6 +151,8 @@ impl WindowManager {
|
||||
/// [`WindowManager::move_container_in_cycle_direction`] give.
|
||||
/// - There is no focused workspace to change the layout or the tiling of, to preselect a
|
||||
/// place in, or to resize or promote a container of, or it cannot be tiled again.
|
||||
/// - The monitor or the workspace of `LockMonitorWorkspaceContainer` or
|
||||
/// `UnlockMonitorWorkspaceContainer` is not there (a container that is not there is ignored).
|
||||
/// - The focused window cannot be floated or put back, for one of the reasons
|
||||
/// [`WindowManager::toggle_float`] gives.
|
||||
/// - The file of `QuickSave` or `Save` cannot be written, or the file of `QuickLoad` or
|
||||
@@ -274,11 +280,50 @@ impl WindowManager {
|
||||
|
||||
self.update_focused_workspace(false, false)?;
|
||||
}
|
||||
SocketMessage::LockMonitorWorkspaceContainer(
|
||||
monitor_idx,
|
||||
workspace_idx,
|
||||
container_idx,
|
||||
) => {
|
||||
let monitor = self
|
||||
.monitors_mut()
|
||||
.get_mut(monitor_idx)
|
||||
.ok_or_eyre("no monitor at the given index")?;
|
||||
|
||||
let workspace = monitor
|
||||
.workspaces_mut()
|
||||
.get_mut(workspace_idx)
|
||||
.ok_or_eyre("no workspace at the given index")?;
|
||||
|
||||
if let Some(container) = workspace.containers_mut().get_mut(container_idx) {
|
||||
container.locked = true;
|
||||
}
|
||||
}
|
||||
SocketMessage::UnlockMonitorWorkspaceContainer(
|
||||
monitor_idx,
|
||||
workspace_idx,
|
||||
container_idx,
|
||||
) => {
|
||||
let monitor = self
|
||||
.monitors_mut()
|
||||
.get_mut(monitor_idx)
|
||||
.ok_or_eyre("no monitor at the given index")?;
|
||||
|
||||
let workspace = monitor
|
||||
.workspaces_mut()
|
||||
.get_mut(workspace_idx)
|
||||
.ok_or_eyre("no workspace at the given index")?;
|
||||
|
||||
if let Some(container) = workspace.containers_mut().get_mut(container_idx) {
|
||||
container.locked = false;
|
||||
}
|
||||
}
|
||||
SocketMessage::FlipLayout(layout_flip) => self.flip_layout(layout_flip)?,
|
||||
SocketMessage::ChangeLayout(layout) => self.change_workspace_layout_default(layout)?,
|
||||
SocketMessage::CycleLayout(direction) => self.cycle_layout(direction)?,
|
||||
SocketMessage::Retile => self.retile_all(false)?,
|
||||
SocketMessage::RetileWithResizeDimensions => self.retile_all(true)?,
|
||||
SocketMessage::ToggleLock => self.toggle_lock()?,
|
||||
SocketMessage::ToggleTiling => {
|
||||
self.toggle_tiling()?;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ use crate::core::Rect;
|
||||
use crate::core::Sizing;
|
||||
use crate::core::WindowManagementBehaviour;
|
||||
use crate::desktop;
|
||||
use crate::lockable_sequence::Lockable;
|
||||
use crate::monitor::Monitor;
|
||||
use crate::ring::Ring;
|
||||
use crate::window::Window;
|
||||
@@ -857,6 +858,24 @@ impl WindowManager {
|
||||
self.update_focused_workspace(self.mouse_follows_focus, false)
|
||||
}
|
||||
|
||||
/// Locks the focused container of the focused workspace at its index, or unlocks it
|
||||
///
|
||||
/// A locked container stays at its index while containers are inserted, removed and swapped
|
||||
/// around it. Nothing is retiled.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// There is no focused workspace.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn toggle_lock(&mut self) -> eyre::Result<()> {
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
if let Some(container) = workspace.focused_container_mut() {
|
||||
// Toggle the locked flag
|
||||
container.set_locked(!container.locked());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Turns the tiling of the focused workspace off, or back on and tiles it again
|
||||
///
|
||||
/// While its tiling is off, the workspace keeps its containers and moves no window.
|
||||
@@ -1211,6 +1230,57 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_toggle_lock() {
|
||||
let (mut wm, _context) = setup_window_manager();
|
||||
|
||||
{
|
||||
// Add monitor with default workspace to
|
||||
let mut m = monitor::new(
|
||||
0,
|
||||
Rect::default(),
|
||||
Rect::default(),
|
||||
"TestMonitor".to_string(),
|
||||
"TestDeviceID".to_string(),
|
||||
);
|
||||
|
||||
let workspace = m.focused_workspace_mut().unwrap();
|
||||
|
||||
// Create containers to add to the workspace
|
||||
for _ in 0..3 {
|
||||
let container = Container::default();
|
||||
workspace.add_container_to_back(container);
|
||||
}
|
||||
|
||||
wm.monitors_mut().push_back(m);
|
||||
}
|
||||
|
||||
{
|
||||
// Ensure container 2 is not locked
|
||||
let workspace = wm.focused_workspace_mut().unwrap();
|
||||
assert_eq!(workspace.focused_container_idx(), 2);
|
||||
assert!(!workspace.focused_container().unwrap().locked);
|
||||
}
|
||||
|
||||
// Toggle lock on focused container
|
||||
wm.toggle_lock().unwrap();
|
||||
|
||||
{
|
||||
// Ensure container 2 is locked
|
||||
let workspace = wm.focused_workspace_mut().unwrap();
|
||||
assert!(workspace.focused_container().unwrap().locked);
|
||||
}
|
||||
|
||||
// Toggle lock on focused container
|
||||
wm.toggle_lock().unwrap();
|
||||
|
||||
{
|
||||
// Ensure container 2 is not locked
|
||||
let workspace = wm.focused_workspace_mut().unwrap();
|
||||
assert!(!workspace.focused_container().unwrap().locked);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_window() {
|
||||
let (mut wm, _context) = setup_window_manager();
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
//! Locking containers with `toggle-lock` and the messages that lock and unlock a container by its
|
||||
//! indices, against an in-memory desktop: the messages go in through
|
||||
//! [`WindowManager::process_command`], and what comes out is the order of the containers.
|
||||
//!
|
||||
//! Window ids are in the 26_000s.
|
||||
|
||||
use komorebi::backend::fake::FakeBackend;
|
||||
use komorebi::backend::with_backend;
|
||||
use komorebi::core::SocketMessage;
|
||||
use komorebi::window::Window;
|
||||
use komorebi::window_manager::WindowManager;
|
||||
use komorebi::window_manager_event::KWinNotification;
|
||||
use komorebi::window_manager_event::SystemNotification;
|
||||
use komorebi::window_manager_event::WindowManagerEvent;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn added(id: u32) -> WindowManagerEvent {
|
||||
WindowManagerEvent::Show(
|
||||
SystemNotification::KWin(KWinNotification::WindowAdded),
|
||||
Window::from(id),
|
||||
)
|
||||
}
|
||||
|
||||
fn activated(id: u32) -> WindowManagerEvent {
|
||||
WindowManagerEvent::FocusChange(
|
||||
SystemNotification::KWin(KWinNotification::WindowActivated),
|
||||
Window::from(id),
|
||||
)
|
||||
}
|
||||
|
||||
/// A window manager over a fake desktop with one 1920x1080 monitor, and a window for each of
|
||||
/// `ids`, opened in that order. The last one has the focus.
|
||||
fn desktop_with(ids: &[u32]) -> (Arc<FakeBackend>, WindowManager) {
|
||||
let fake = Arc::new(FakeBackend::with_one_monitor());
|
||||
let (_sender, receiver) = crossbeam_channel::bounded(1);
|
||||
// unix socket paths are limited to ~104 bytes on macOS, which the temp dir alone can exceed
|
||||
static NEXT: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0);
|
||||
let socket = std::path::PathBuf::from(format!(
|
||||
"/tmp/kmk-{}-{}.sock",
|
||||
std::process::id(),
|
||||
NEXT.fetch_add(1, std::sync::atomic::Ordering::SeqCst)
|
||||
));
|
||||
|
||||
let mut wm = with_backend(fake.clone(), || {
|
||||
let mut wm = WindowManager::new(receiver, Some(socket)).unwrap();
|
||||
wm.init().unwrap();
|
||||
wm
|
||||
});
|
||||
for &id in ids {
|
||||
open(&fake, &mut wm, id);
|
||||
}
|
||||
|
||||
(fake, wm)
|
||||
}
|
||||
|
||||
fn open(fake: &Arc<FakeBackend>, wm: &mut WindowManager, id: u32) {
|
||||
fake.open_window(id, "foot", "foot", &format!("terminal {id}"));
|
||||
with_backend(fake.clone(), || wm.process_event(added(id))).unwrap();
|
||||
}
|
||||
|
||||
fn send(
|
||||
fake: &Arc<FakeBackend>,
|
||||
wm: &mut WindowManager,
|
||||
message: SocketMessage,
|
||||
) -> color_eyre::Result<()> {
|
||||
with_backend(fake.clone(), || wm.process_command(message, Vec::new()))
|
||||
}
|
||||
|
||||
/// The window of each container of the focused workspace, in order
|
||||
fn order(wm: &WindowManager) -> Vec<u32> {
|
||||
wm.focused_workspace()
|
||||
.unwrap()
|
||||
.containers()
|
||||
.iter()
|
||||
.map(|container| container.focused_window().unwrap().id)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn locked(wm: &WindowManager) -> Vec<bool> {
|
||||
wm.focused_workspace()
|
||||
.unwrap()
|
||||
.containers()
|
||||
.iter()
|
||||
.map(|container| container.locked)
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn toggle_lock_locks_the_focused_container_and_unlocks_it() {
|
||||
let (fake, mut wm) = desktop_with(&[26_001, 26_002]);
|
||||
|
||||
send(&fake, &mut wm, SocketMessage::ToggleLock).unwrap();
|
||||
assert_eq!(locked(&wm), [false, true]);
|
||||
|
||||
send(&fake, &mut wm, SocketMessage::ToggleLock).unwrap();
|
||||
assert_eq!(locked(&wm), [false, false]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_window_that_opens_does_not_push_a_locked_container_from_its_index() {
|
||||
let (fake, mut wm) = desktop_with(&[26_011, 26_012]);
|
||||
// the first window gets the focus, and its container is locked: a new window goes after it,
|
||||
// where the second one is
|
||||
with_backend(fake.clone(), || wm.process_event(activated(26_011))).unwrap();
|
||||
send(
|
||||
&fake,
|
||||
&mut wm,
|
||||
SocketMessage::LockMonitorWorkspaceContainer(0, 0, 1),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
open(&fake, &mut wm, 26_013);
|
||||
|
||||
assert_eq!(
|
||||
order(&wm),
|
||||
[26_011, 26_012, 26_013],
|
||||
"the second stays second"
|
||||
);
|
||||
assert_eq!(locked(&wm), [false, true, false]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_container_is_locked_and_unlocked_by_its_indices() {
|
||||
let (fake, mut wm) = desktop_with(&[26_021, 26_022]);
|
||||
|
||||
send(
|
||||
&fake,
|
||||
&mut wm,
|
||||
SocketMessage::LockMonitorWorkspaceContainer(0, 0, 0),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(locked(&wm), [true, false]);
|
||||
|
||||
send(
|
||||
&fake,
|
||||
&mut wm,
|
||||
SocketMessage::UnlockMonitorWorkspaceContainer(0, 0, 0),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(locked(&wm), [false, false]);
|
||||
|
||||
// a container that is not there is ignored, a monitor that is not there is an error
|
||||
send(
|
||||
&fake,
|
||||
&mut wm,
|
||||
SocketMessage::LockMonitorWorkspaceContainer(0, 0, 9),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
send(
|
||||
&fake,
|
||||
&mut wm,
|
||||
SocketMessage::LockMonitorWorkspaceContainer(3, 0, 0),
|
||||
)
|
||||
.map_err(|error| error.to_string()),
|
||||
Err(String::from("no monitor at the given index"))
|
||||
);
|
||||
}
|
||||
@@ -16,7 +16,8 @@
|
||||
//! next window and give it up.
|
||||
//! - `promote`, `promote-swap`, `promote-focus` and `promote-window` bring a window to the largest
|
||||
//! tile, or the focus to it.
|
||||
//! - `toggle-float` takes the focused window out of the layout, or puts it back.
|
||||
//! - `toggle-float` takes the focused window out of the layout, or puts it back, and
|
||||
//! `toggle-lock` locks the focused container at its index, or unlocks it.
|
||||
//! - `resize-edge` and `resize-axis` resize the focused window by the `resize-delta`, and
|
||||
//! `quick-save-resize`, `quick-load-resize`, `save-resize` and `load-resize` save the sizes of
|
||||
//! the tiles of the focused workspace and load them back.
|
||||
@@ -307,6 +308,8 @@ enum SubCommand {
|
||||
ToggleTiling,
|
||||
/// Toggle floating mode for the focused window
|
||||
ToggleFloat,
|
||||
/// Toggle a lock for the focused container, ensuring it will not be displaced by any new windows
|
||||
ToggleLock,
|
||||
/// Enable or disable mouse follows focus on all workspaces
|
||||
#[clap(arg_required_else_help = true)]
|
||||
MouseFollowsFocus(MouseFollowsFocus),
|
||||
@@ -483,6 +486,9 @@ fn main() -> eyre::Result<()> {
|
||||
SubCommand::ToggleTiling => {
|
||||
send_message(&SocketMessage::ToggleTiling)?;
|
||||
}
|
||||
SubCommand::ToggleLock => {
|
||||
send_message(&SocketMessage::ToggleLock)?;
|
||||
}
|
||||
SubCommand::State => {
|
||||
print_query(&SocketMessage::State);
|
||||
}
|
||||
|
||||
@@ -210,6 +210,7 @@ fn the_layout_subcommands_send_the_layout_axis_or_direction_they_are_given() {
|
||||
);
|
||||
sends(&["toggle-tiling"], r#"{"type":"ToggleTiling"}"#);
|
||||
sends(&["toggle-float"], r#"{"type":"ToggleFloat"}"#);
|
||||
sends(&["toggle-lock"], r#"{"type":"ToggleLock"}"#);
|
||||
sends(
|
||||
&["preselect-direction", "up"],
|
||||
r#"{"type":"PreselectDirection","content":"Up"}"#,
|
||||
@@ -385,6 +386,7 @@ fn docgen_writes_the_help_of_every_subcommand_in_a_text_fence() {
|
||||
"stop.md",
|
||||
"subscribe-socket.md",
|
||||
"toggle-float.md",
|
||||
"toggle-lock.md",
|
||||
"toggle-mouse-follows-focus.md",
|
||||
"toggle-tiling.md",
|
||||
"unsubscribe-socket.md",
|
||||
|
||||
@@ -184,6 +184,8 @@ preselect-direction left
|
||||
cancel-preselect
|
||||
toggle-float
|
||||
toggle-float
|
||||
toggle-lock
|
||||
toggle-lock
|
||||
toggle-tiling
|
||||
toggle-tiling
|
||||
mouse-follows-focus enable
|
||||
|
||||
Reference in new issue
Block a user