mirror of
https://github.com/YaLTeR/niri.git
synced 2024-08-17 08:11:00 +03:00
Compare commits
3 Commits
a9ef14acff
...
812e6d7bfd
Author | SHA1 | Date | |
---|---|---|---|
|
812e6d7bfd | ||
|
a283c34dbb | ||
|
e9a93cae11 |
@ -995,6 +995,8 @@ pub enum Action {
|
||||
MoveColumnRight,
|
||||
MoveColumnToFirst,
|
||||
MoveColumnToLast,
|
||||
MoveColumnLeftOrToMonitorLeft,
|
||||
MoveColumnRightOrToMonitorRight,
|
||||
MoveWindowDown,
|
||||
MoveWindowUp,
|
||||
MoveWindowDownOrToWorkspaceDown,
|
||||
@ -1075,6 +1077,10 @@ impl From<niri_ipc::Action> for Action {
|
||||
niri_ipc::Action::MoveColumnRight => Self::MoveColumnRight,
|
||||
niri_ipc::Action::MoveColumnToFirst => Self::MoveColumnToFirst,
|
||||
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::MoveWindowUp => Self::MoveWindowUp,
|
||||
niri_ipc::Action::MoveWindowDownOrToWorkspaceDown => {
|
||||
|
@ -152,6 +152,10 @@ pub enum Action {
|
||||
MoveColumnToFirst,
|
||||
/// Move the focused column to the end of the workspace.
|
||||
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.
|
||||
MoveWindowDown,
|
||||
/// Move the focused window up in a column.
|
||||
@ -495,7 +499,7 @@ pub enum Transform {
|
||||
}
|
||||
|
||||
/// Toplevel window.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Eq, PartialEq, Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Window {
|
||||
/// Title, if set.
|
||||
pub title: Option<String>,
|
||||
@ -527,6 +531,8 @@ pub struct Workspace {
|
||||
pub output: Option<String>,
|
||||
/// Whether the workspace is currently active on its output.
|
||||
pub is_active: bool,
|
||||
/// The windows currently on this workspace
|
||||
pub windows: Vec<Window>,
|
||||
}
|
||||
|
||||
impl FromStr for WorkspaceReferenceArg {
|
||||
|
@ -571,6 +571,40 @@ impl State {
|
||||
// FIXME: granular
|
||||
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 => {
|
||||
self.niri.layout.move_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
|
@ -147,23 +147,12 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply {
|
||||
Response::Outputs(outputs.collect())
|
||||
}
|
||||
Request::FocusedWindow => {
|
||||
let window = ctx.ipc_focused_window.lock().unwrap().clone();
|
||||
let window = window.map(|window| {
|
||||
let wl_surface = window.toplevel().expect("no X11 support").wl_surface();
|
||||
with_states(wl_surface, |states| {
|
||||
let role = states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap();
|
||||
|
||||
niri_ipc::Window {
|
||||
title: role.title.clone(),
|
||||
app_id: role.app_id.clone(),
|
||||
}
|
||||
})
|
||||
});
|
||||
let window = ctx
|
||||
.ipc_focused_window
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.map(smithay_window_to_ipc);
|
||||
Response::FocusedWindow(window)
|
||||
}
|
||||
Request::Action(action) => {
|
||||
@ -239,3 +228,20 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply {
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub fn smithay_window_to_ipc(window: &smithay::desktop::Window) -> niri_ipc::Window {
|
||||
let wl_surface = window.toplevel().expect("no X11 support").wl_surface();
|
||||
with_states(wl_surface, |states| {
|
||||
let role = states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap();
|
||||
|
||||
niri_ipc::Window {
|
||||
title: role.title.clone(),
|
||||
app_id: role.app_id.clone(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ use smithay::utils::{Logical, Point, Scale, Serial, Size, Transform};
|
||||
pub use self::monitor::MonitorRenderElement;
|
||||
use self::monitor::{Monitor, WorkspaceSwitch};
|
||||
use self::workspace::{compute_working_area, Column, ColumnWidth, OutputId, Workspace};
|
||||
use crate::ipc::server::smithay_window_to_ipc;
|
||||
use crate::niri_render_elements;
|
||||
use crate::render_helpers::renderer::NiriRenderer;
|
||||
use crate::render_helpers::snapshot::RenderSnapshot;
|
||||
@ -53,7 +54,7 @@ use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderEleme
|
||||
use crate::render_helpers::texture::TextureBuffer;
|
||||
use crate::render_helpers::{BakedBuffer, RenderTarget, SplitElements};
|
||||
use crate::utils::{output_size, round_logical_in_physical_max1, ResizeEdge};
|
||||
use crate::window::ResolvedWindowRules;
|
||||
use crate::window::{Mapped, ResolvedWindowRules};
|
||||
|
||||
pub mod closing_window;
|
||||
pub mod focus_ring;
|
||||
@ -1196,6 +1197,36 @@ impl<W: LayoutElement> Layout<W> {
|
||||
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) {
|
||||
let Some(monitor) = self.active_monitor() else {
|
||||
return;
|
||||
@ -2440,7 +2471,9 @@ impl<W: LayoutElement> Layout<W> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout<Mapped> {
|
||||
pub fn ipc_workspaces(&self) -> Vec<niri_ipc::Workspace> {
|
||||
match &self.monitor_set {
|
||||
MonitorSet::Normal {
|
||||
@ -2457,6 +2490,10 @@ impl<W: LayoutElement> Layout<W> {
|
||||
name: workspace.name.clone(),
|
||||
output: Some(monitor.output.name()),
|
||||
is_active: monitor.active_workspace_idx == idx,
|
||||
windows: workspace
|
||||
.windows()
|
||||
.map(|mapped| smithay_window_to_ipc(&mapped.window))
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -2471,6 +2508,10 @@ impl<W: LayoutElement> Layout<W> {
|
||||
name: ws.name.clone(),
|
||||
output: None,
|
||||
is_active: false,
|
||||
windows: ws
|
||||
.windows()
|
||||
.map(|mapped| smithay_window_to_ipc(&mapped.window))
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
@ -2797,6 +2838,8 @@ mod tests {
|
||||
MoveColumnRight,
|
||||
MoveColumnToFirst,
|
||||
MoveColumnToLast,
|
||||
MoveColumnLeftOrToMonitorLeft(#[proptest(strategy = "1..=2u8")] u8),
|
||||
MoveColumnRightOrToMonitorRight(#[proptest(strategy = "1..=2u8")] u8),
|
||||
MoveWindowDown,
|
||||
MoveWindowUp,
|
||||
MoveWindowDownOrToWorkspaceDown,
|
||||
@ -3154,6 +3197,22 @@ mod tests {
|
||||
Op::MoveColumnRight => layout.move_right(),
|
||||
Op::MoveColumnToFirst => layout.move_column_to_first(),
|
||||
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::MoveWindowUp => layout.move_up(),
|
||||
Op::MoveWindowDownOrToWorkspaceDown => layout.move_down_or_to_workspace_down(),
|
||||
@ -3384,6 +3443,8 @@ mod tests {
|
||||
Op::FocusWindowOrWorkspaceDown,
|
||||
Op::MoveColumnLeft,
|
||||
Op::MoveColumnRight,
|
||||
Op::MoveColumnLeftOrToMonitorLeft(0),
|
||||
Op::MoveColumnRightOrToMonitorRight(1),
|
||||
Op::ConsumeWindowIntoColumn,
|
||||
Op::ExpelWindowFromColumn,
|
||||
Op::CenterColumn,
|
||||
@ -3563,6 +3624,8 @@ mod tests {
|
||||
Op::FocusWindowOrWorkspaceDown,
|
||||
Op::MoveColumnLeft,
|
||||
Op::MoveColumnRight,
|
||||
Op::MoveColumnLeftOrToMonitorLeft(0),
|
||||
Op::MoveColumnRightOrToMonitorRight(1),
|
||||
Op::ConsumeWindowIntoColumn,
|
||||
Op::ExpelWindowFromColumn,
|
||||
Op::CenterColumn,
|
||||
|
Loading…
Reference in New Issue
Block a user