Compare commits

...

4 Commits

Author SHA1 Message Date
Oli Strik
1c1783b996
Merge 0704e1e330 into a283c34dbb 2024-07-09 22:44:52 -07:00
Ivan Molodetskikh
0704e1e330
Merge branch 'main' into add-schemars-jsonschema-to-ipc-types 2024-07-10 08:44:49 +03:00
Winter
a283c34dbb
Add move-column-{left/right}-or-to-monitor-{left/right} (#528)
* feature added, move-column-left-or-monitor-left and move-column-right-or-monitor-right

* fixed stupid mistake

* yalter's fixes

* fixed names

* fixed a stupid mistake

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2024-07-10 04:52:48 +00:00
olistrik
496525cf8c feat: add schemars JsonSchema trait to ipc types 2024-07-09 09:26:05 +02:00
6 changed files with 159 additions and 19 deletions

42
Cargo.lock generated
View File

@ -985,6 +985,12 @@ dependencies = [
"linux-raw-sys 0.6.4", "linux-raw-sys 0.6.4",
] ]
[[package]]
name = "dyn-clone"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
[[package]] [[package]]
name = "edid-rs" name = "edid-rs"
version = "0.1.0" version = "0.1.0"
@ -2294,6 +2300,7 @@ name = "niri-ipc"
version = "0.1.7" version = "0.1.7"
dependencies = [ dependencies = [
"clap", "clap",
"schemars",
"serde", "serde",
"serde_json", "serde_json",
] ]
@ -3307,6 +3314,30 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248" checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248"
[[package]]
name = "schemars"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92"
dependencies = [
"dyn-clone",
"schemars_derive",
"serde",
"serde_json",
]
[[package]]
name = "schemars_derive"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e"
dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.67",
]
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
version = "1.0.1" version = "1.0.1"
@ -3345,6 +3376,17 @@ dependencies = [
"syn 2.0.69", "syn 2.0.69",
] ]
[[package]]
name = "serde_derive_internals"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.67",
]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.120" version = "1.0.120"

View File

@ -995,6 +995,8 @@ pub enum Action {
MoveColumnRight, MoveColumnRight,
MoveColumnToFirst, MoveColumnToFirst,
MoveColumnToLast, MoveColumnToLast,
MoveColumnLeftOrToMonitorLeft,
MoveColumnRightOrToMonitorRight,
MoveWindowDown, MoveWindowDown,
MoveWindowUp, MoveWindowUp,
MoveWindowDownOrToWorkspaceDown, MoveWindowDownOrToWorkspaceDown,
@ -1075,6 +1077,10 @@ impl From<niri_ipc::Action> for Action {
niri_ipc::Action::MoveColumnRight => Self::MoveColumnRight, niri_ipc::Action::MoveColumnRight => Self::MoveColumnRight,
niri_ipc::Action::MoveColumnToFirst => Self::MoveColumnToFirst, niri_ipc::Action::MoveColumnToFirst => Self::MoveColumnToFirst,
niri_ipc::Action::MoveColumnToLast => Self::MoveColumnToLast, niri_ipc::Action::MoveColumnToLast => Self::MoveColumnToLast,
niri_ipc::Action::MoveColumnLeftOrToMonitorLeft => Self::MoveColumnLeftOrToMonitorLeft,
niri_ipc::Action::MoveColumnRightOrToMonitorRight => {
Self::MoveColumnRightOrToMonitorRight
}
niri_ipc::Action::MoveWindowDown => Self::MoveWindowDown, niri_ipc::Action::MoveWindowDown => Self::MoveWindowDown,
niri_ipc::Action::MoveWindowUp => Self::MoveWindowUp, niri_ipc::Action::MoveWindowUp => Self::MoveWindowUp,
niri_ipc::Action::MoveWindowDownOrToWorkspaceDown => { niri_ipc::Action::MoveWindowDownOrToWorkspaceDown => {

View File

@ -9,6 +9,7 @@ repository.workspace = true
[dependencies] [dependencies]
clap = { workspace = true, optional = true } clap = { workspace = true, optional = true }
schemars = "0.8.21"
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true

View File

@ -4,13 +4,14 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::str::FromStr; use std::str::FromStr;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
mod socket; mod socket;
pub use socket::{Socket, SOCKET_PATH_ENV}; pub use socket::{Socket, SOCKET_PATH_ENV};
/// Request from client to niri. /// Request from client to niri.
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub enum Request { pub enum Request {
/// Request the version string for the running niri instance. /// Request the version string for the running niri instance.
Version, Version,
@ -50,7 +51,7 @@ pub enum Request {
pub type Reply = Result<Response, String>; pub type Reply = Result<Response, String>;
/// Successful response from niri to client. /// Successful response from niri to client.
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub enum Response { pub enum Response {
/// A request that does not need a response was handled successfully. /// A request that does not need a response was handled successfully.
Handled, Handled,
@ -73,7 +74,7 @@ pub enum Response {
/// Actions that niri can perform. /// Actions that niri can perform.
// Variants in this enum should match the spelling of the ones in niri-config. Most, but not all, // Variants in this enum should match the spelling of the ones in niri-config. Most, but not all,
// variants from niri-config should be present here. // variants from niri-config should be present here.
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
#[cfg_attr(feature = "clap", derive(clap::Parser))] #[cfg_attr(feature = "clap", derive(clap::Parser))]
#[cfg_attr(feature = "clap", command(subcommand_value_name = "ACTION"))] #[cfg_attr(feature = "clap", command(subcommand_value_name = "ACTION"))]
#[cfg_attr(feature = "clap", command(subcommand_help_heading = "Actions"))] #[cfg_attr(feature = "clap", command(subcommand_help_heading = "Actions"))]
@ -152,6 +153,10 @@ pub enum Action {
MoveColumnToFirst, MoveColumnToFirst,
/// Move the focused column to the end of the workspace. /// Move the focused column to the end of the workspace.
MoveColumnToLast, MoveColumnToLast,
/// Move the focused column to the left or to the monitor to the left.
MoveColumnLeftOrToMonitorLeft,
/// Move the focused column to the right or to the monitor to the right.
MoveColumnRightOrToMonitorRight,
/// Move the focused window down in a column. /// Move the focused window down in a column.
MoveWindowDown, MoveWindowDown,
/// Move the focused window up in a column. /// Move the focused window up in a column.
@ -273,7 +278,7 @@ pub enum Action {
} }
/// Change in window or column size. /// Change in window or column size.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema)]
pub enum SizeChange { pub enum SizeChange {
/// Set the size in logical pixels. /// Set the size in logical pixels.
SetFixed(i32), SetFixed(i32),
@ -286,7 +291,7 @@ pub enum SizeChange {
} }
/// Workspace reference (index or name) to operate on. /// Workspace reference (index or name) to operate on.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
pub enum WorkspaceReferenceArg { pub enum WorkspaceReferenceArg {
/// Index of the workspace. /// Index of the workspace.
Index(u8), Index(u8),
@ -295,7 +300,7 @@ pub enum WorkspaceReferenceArg {
} }
/// Layout to switch to. /// Layout to switch to.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema)]
pub enum LayoutSwitchTarget { pub enum LayoutSwitchTarget {
/// The next configured layout. /// The next configured layout.
Next, Next,
@ -306,7 +311,7 @@ pub enum LayoutSwitchTarget {
/// Output actions that niri can perform. /// Output actions that niri can perform.
// Variants in this enum should match the spelling of the ones in niri-config. Most thigs from // Variants in this enum should match the spelling of the ones in niri-config. Most thigs from
// niri-config should be present here. // niri-config should be present here.
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
#[cfg_attr(feature = "clap", derive(clap::Parser))] #[cfg_attr(feature = "clap", derive(clap::Parser))]
#[cfg_attr(feature = "clap", command(subcommand_value_name = "ACTION"))] #[cfg_attr(feature = "clap", command(subcommand_value_name = "ACTION"))]
#[cfg_attr(feature = "clap", command(subcommand_help_heading = "Actions"))] #[cfg_attr(feature = "clap", command(subcommand_help_heading = "Actions"))]
@ -357,7 +362,7 @@ pub enum OutputAction {
} }
/// Output mode to set. /// Output mode to set.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema)]
pub enum ModeToSet { pub enum ModeToSet {
/// Niri will pick the mode automatically. /// Niri will pick the mode automatically.
Automatic, Automatic,
@ -366,7 +371,7 @@ pub enum ModeToSet {
} }
/// Output mode as set in the config file. /// Output mode as set in the config file.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema)]
pub struct ConfiguredMode { pub struct ConfiguredMode {
/// Width in physical pixels. /// Width in physical pixels.
pub width: u16, pub width: u16,
@ -377,7 +382,7 @@ pub struct ConfiguredMode {
} }
/// Output scale to set. /// Output scale to set.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema)]
pub enum ScaleToSet { pub enum ScaleToSet {
/// Niri will pick the scale automatically. /// Niri will pick the scale automatically.
Automatic, Automatic,
@ -386,7 +391,7 @@ pub enum ScaleToSet {
} }
/// Output position to set. /// Output position to set.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema)]
#[cfg_attr(feature = "clap", derive(clap::Subcommand))] #[cfg_attr(feature = "clap", derive(clap::Subcommand))]
#[cfg_attr(feature = "clap", command(subcommand_value_name = "POSITION"))] #[cfg_attr(feature = "clap", command(subcommand_value_name = "POSITION"))]
#[cfg_attr(feature = "clap", command(subcommand_help_heading = "Position Values"))] #[cfg_attr(feature = "clap", command(subcommand_help_heading = "Position Values"))]
@ -400,7 +405,7 @@ pub enum PositionToSet {
} }
/// Output position as set in the config file. /// Output position as set in the config file.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, JsonSchema)]
#[cfg_attr(feature = "clap", derive(clap::Args))] #[cfg_attr(feature = "clap", derive(clap::Args))]
pub struct ConfiguredPosition { pub struct ConfiguredPosition {
/// Logical X position. /// Logical X position.
@ -410,7 +415,7 @@ pub struct ConfiguredPosition {
} }
/// Connected output. /// Connected output.
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub struct Output { pub struct Output {
/// Name of the output. /// Name of the output.
pub name: String, pub name: String,
@ -437,7 +442,7 @@ pub struct Output {
} }
/// Output mode. /// Output mode.
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, JsonSchema)]
pub struct Mode { pub struct Mode {
/// Width in physical pixels. /// Width in physical pixels.
pub width: u16, pub width: u16,
@ -450,7 +455,7 @@ pub struct Mode {
} }
/// Logical output in the compositor's coordinate space. /// Logical output in the compositor's coordinate space.
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, JsonSchema)]
pub struct LogicalOutput { pub struct LogicalOutput {
/// Logical X position. /// Logical X position.
pub x: i32, pub x: i32,
@ -467,7 +472,7 @@ pub struct LogicalOutput {
} }
/// Output transform, which goes counter-clockwise. /// Output transform, which goes counter-clockwise.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))] #[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
pub enum Transform { pub enum Transform {
/// Untransformed. /// Untransformed.
@ -495,7 +500,7 @@ pub enum Transform {
} }
/// Toplevel window. /// Toplevel window.
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
pub struct Window { pub struct Window {
/// Title, if set. /// Title, if set.
pub title: Option<String>, pub title: Option<String>,
@ -504,7 +509,7 @@ pub struct Window {
} }
/// Output configuration change result. /// Output configuration change result.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema)]
pub enum OutputConfigChanged { pub enum OutputConfigChanged {
/// The target output was connected and the change was applied. /// The target output was connected and the change was applied.
Applied, Applied,
@ -513,7 +518,7 @@ pub enum OutputConfigChanged {
} }
/// A workspace. /// A workspace.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
pub struct Workspace { pub struct Workspace {
/// Index of the workspace on its monitor. /// Index of the workspace on its monitor.
/// ///

View File

@ -571,6 +571,40 @@ impl State {
// FIXME: granular // FIXME: granular
self.niri.queue_redraw_all(); self.niri.queue_redraw_all();
} }
Action::MoveColumnLeftOrToMonitorLeft => {
if let Some(output) = self.niri.output_left() {
if self.niri.layout.move_column_left_or_to_output(&output)
&& !self.maybe_warp_cursor_to_focus_centered()
{
self.move_cursor_to_output(&output);
} else {
self.maybe_warp_cursor_to_focus();
}
} else {
self.niri.layout.move_left();
self.maybe_warp_cursor_to_focus();
}
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::MoveColumnRightOrToMonitorRight => {
if let Some(output) = self.niri.output_right() {
if self.niri.layout.move_column_right_or_to_output(&output)
&& !self.maybe_warp_cursor_to_focus_centered()
{
self.move_cursor_to_output(&output);
} else {
self.maybe_warp_cursor_to_focus();
}
} else {
self.niri.layout.move_right();
self.maybe_warp_cursor_to_focus();
}
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::MoveWindowDown => { Action::MoveWindowDown => {
self.niri.layout.move_down(); self.niri.layout.move_down();
self.maybe_warp_cursor_to_focus(); self.maybe_warp_cursor_to_focus();

View File

@ -1196,6 +1196,36 @@ impl<W: LayoutElement> Layout<W> {
monitor.move_column_to_last(); monitor.move_column_to_last();
} }
pub fn move_column_left_or_to_output(&mut self, output: &Output) -> bool {
if let Some(monitor) = self.active_monitor() {
let workspace = monitor.active_workspace();
let curr_idx = workspace.active_column_idx;
if !workspace.columns.is_empty() && curr_idx != 0 {
monitor.move_left();
return false;
}
}
self.move_column_to_output(output);
true
}
pub fn move_column_right_or_to_output(&mut self, output: &Output) -> bool {
if let Some(monitor) = self.active_monitor() {
let workspace = monitor.active_workspace();
let curr_idx = workspace.active_column_idx;
if !workspace.columns.is_empty() && curr_idx != workspace.columns.len() - 1 {
monitor.move_right();
return false;
}
}
self.move_column_to_output(output);
true
}
pub fn move_down(&mut self) { pub fn move_down(&mut self) {
let Some(monitor) = self.active_monitor() else { let Some(monitor) = self.active_monitor() else {
return; return;
@ -2797,6 +2827,8 @@ mod tests {
MoveColumnRight, MoveColumnRight,
MoveColumnToFirst, MoveColumnToFirst,
MoveColumnToLast, MoveColumnToLast,
MoveColumnLeftOrToMonitorLeft(#[proptest(strategy = "1..=2u8")] u8),
MoveColumnRightOrToMonitorRight(#[proptest(strategy = "1..=2u8")] u8),
MoveWindowDown, MoveWindowDown,
MoveWindowUp, MoveWindowUp,
MoveWindowDownOrToWorkspaceDown, MoveWindowDownOrToWorkspaceDown,
@ -3154,6 +3186,22 @@ mod tests {
Op::MoveColumnRight => layout.move_right(), Op::MoveColumnRight => layout.move_right(),
Op::MoveColumnToFirst => layout.move_column_to_first(), Op::MoveColumnToFirst => layout.move_column_to_first(),
Op::MoveColumnToLast => layout.move_column_to_last(), Op::MoveColumnToLast => layout.move_column_to_last(),
Op::MoveColumnLeftOrToMonitorLeft(id) => {
let name = format!("output{id}");
let Some(output) = layout.outputs().find(|o| o.name() == name).cloned() else {
return;
};
layout.move_column_left_or_to_output(&output);
}
Op::MoveColumnRightOrToMonitorRight(id) => {
let name = format!("output{id}");
let Some(output) = layout.outputs().find(|o| o.name() == name).cloned() else {
return;
};
layout.move_column_right_or_to_output(&output);
}
Op::MoveWindowDown => layout.move_down(), Op::MoveWindowDown => layout.move_down(),
Op::MoveWindowUp => layout.move_up(), Op::MoveWindowUp => layout.move_up(),
Op::MoveWindowDownOrToWorkspaceDown => layout.move_down_or_to_workspace_down(), Op::MoveWindowDownOrToWorkspaceDown => layout.move_down_or_to_workspace_down(),
@ -3384,6 +3432,8 @@ mod tests {
Op::FocusWindowOrWorkspaceDown, Op::FocusWindowOrWorkspaceDown,
Op::MoveColumnLeft, Op::MoveColumnLeft,
Op::MoveColumnRight, Op::MoveColumnRight,
Op::MoveColumnLeftOrToMonitorLeft(0),
Op::MoveColumnRightOrToMonitorRight(1),
Op::ConsumeWindowIntoColumn, Op::ConsumeWindowIntoColumn,
Op::ExpelWindowFromColumn, Op::ExpelWindowFromColumn,
Op::CenterColumn, Op::CenterColumn,
@ -3563,6 +3613,8 @@ mod tests {
Op::FocusWindowOrWorkspaceDown, Op::FocusWindowOrWorkspaceDown,
Op::MoveColumnLeft, Op::MoveColumnLeft,
Op::MoveColumnRight, Op::MoveColumnRight,
Op::MoveColumnLeftOrToMonitorLeft(0),
Op::MoveColumnRightOrToMonitorRight(1),
Op::ConsumeWindowIntoColumn, Op::ConsumeWindowIntoColumn,
Op::ExpelWindowFromColumn, Op::ExpelWindowFromColumn,
Op::CenterColumn, Op::CenterColumn,