From f9fe86ee3e82ff02ac9f75869cc4219850ae3f4c Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 9 Jul 2024 14:25:02 +0400 Subject: [PATCH 1/2] Restore VRR on TTY switch --- src/backend/tty.rs | 109 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 26 deletions(-) diff --git a/src/backend/tty.rs b/src/backend/tty.rs index dc0954d..bdd3c8c 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -405,6 +405,8 @@ impl Tty { self.device_changed(node.dev_id(), niri); // Apply pending gamma changes and restore our existing gamma. + // + // Also, restore our VRR. let device = self.devices.get_mut(&node).unwrap(); for (crtc, surface) in device.surfaces.iter_mut() { if let Some(ramp) = surface.pending_gamma_change.take() { @@ -422,6 +424,45 @@ impl Tty { warn!("error restoring gamma: {err:?}"); } } + + // Restore VRR. + let Some(connector) = + surface.compositor.pending_connectors().into_iter().next() + else { + error!("surface pending connectors is empty"); + continue; + }; + let Some(connector) = device.drm_scanner.connectors().get(&connector) + else { + error!("missing enabled connector in drm_scanner"); + continue; + }; + + let output = niri + .global_space + .outputs() + .find(|output| { + let tty_state: &TtyOutputState = output.user_data().get().unwrap(); + tty_state.node == node && tty_state.crtc == *crtc + }) + .cloned(); + let Some(output) = output else { + error!("missing output for crtc: {crtc:?}"); + continue; + }; + let Some(output_state) = niri.output_state.get_mut(&output) else { + error!("missing state for output {:?}", surface.name); + continue; + }; + + try_to_change_vrr( + &device.drm, + connector, + *crtc, + surface, + output_state, + surface.vrr_enabled, + ); } } @@ -1671,32 +1712,14 @@ impl Tty { }; if change_vrr { - if is_vrr_capable(&device.drm, connector.handle()) == Some(true) { - let word = if config.variable_refresh_rate { - "enabling" - } else { - "disabling" - }; - - match set_vrr_enabled(&device.drm, crtc, config.variable_refresh_rate) { - Ok(enabled) => { - if enabled != config.variable_refresh_rate { - warn!("output {:?}: failed {} VRR", surface.name, word); - } - - surface.vrr_enabled = enabled; - output_state.frame_clock.set_vrr(enabled); - } - Err(err) => { - warn!("output {:?}: error {} VRR: {err:?}", surface.name, word); - } - } - } else if config.variable_refresh_rate { - warn!( - "output {:?}: cannot enable VRR because connector is not vrr_capable", - surface.name - ); - } + try_to_change_vrr( + &device.drm, + connector, + crtc, + surface, + output_state, + config.variable_refresh_rate, + ); } if change_mode { @@ -2345,6 +2368,40 @@ pub fn set_gamma_for_crtc( Ok(()) } +fn try_to_change_vrr( + device: &DrmDevice, + connector: &connector::Info, + crtc: crtc::Handle, + surface: &mut Surface, + output_state: &mut crate::niri::OutputState, + enable_vrr: bool, +) { + let _span = tracy_client::span!("try_to_change_vrr"); + + if is_vrr_capable(device, connector.handle()) == Some(true) { + let word = if enable_vrr { "enabling" } else { "disabling" }; + + match set_vrr_enabled(device, crtc, enable_vrr) { + Ok(enabled) => { + if enabled != enable_vrr { + warn!("output {:?}: failed {} VRR", surface.name, word); + } + + surface.vrr_enabled = enabled; + output_state.frame_clock.set_vrr(enabled); + } + Err(err) => { + warn!("output {:?}: error {} VRR: {err:?}", surface.name, word); + } + } + } else if enable_vrr { + warn!( + "output {:?}: cannot enable VRR because connector is not vrr_capable", + surface.name + ); + } +} + #[cfg(test)] mod tests { use super::*; From a283c34dbbad44dfddfa4b5eafa6d8e3b47b7c14 Mon Sep 17 00:00:00 2001 From: Winter <102400503+exoess@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:52:48 -0700 Subject: [PATCH 2/2] 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 --- niri-config/src/lib.rs | 6 +++++ niri-ipc/src/lib.rs | 4 ++++ src/input/mod.rs | 34 +++++++++++++++++++++++++++ src/layout/mod.rs | 52 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index 114027f..d2343ff 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -995,6 +995,8 @@ pub enum Action { MoveColumnRight, MoveColumnToFirst, MoveColumnToLast, + MoveColumnLeftOrToMonitorLeft, + MoveColumnRightOrToMonitorRight, MoveWindowDown, MoveWindowUp, MoveWindowDownOrToWorkspaceDown, @@ -1075,6 +1077,10 @@ impl From 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 => { diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index 931898b..16817df 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -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. diff --git a/src/input/mod.rs b/src/input/mod.rs index d96de0c..148129c 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -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(); diff --git a/src/layout/mod.rs b/src/layout/mod.rs index fadde1f..21e9066 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1196,6 +1196,36 @@ impl Layout { 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; @@ -2797,6 +2827,8 @@ mod tests { MoveColumnRight, MoveColumnToFirst, MoveColumnToLast, + MoveColumnLeftOrToMonitorLeft(#[proptest(strategy = "1..=2u8")] u8), + MoveColumnRightOrToMonitorRight(#[proptest(strategy = "1..=2u8")] u8), MoveWindowDown, MoveWindowUp, MoveWindowDownOrToWorkspaceDown, @@ -3154,6 +3186,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 +3432,8 @@ mod tests { Op::FocusWindowOrWorkspaceDown, Op::MoveColumnLeft, Op::MoveColumnRight, + Op::MoveColumnLeftOrToMonitorLeft(0), + Op::MoveColumnRightOrToMonitorRight(1), Op::ConsumeWindowIntoColumn, Op::ExpelWindowFromColumn, Op::CenterColumn, @@ -3563,6 +3613,8 @@ mod tests { Op::FocusWindowOrWorkspaceDown, Op::MoveColumnLeft, Op::MoveColumnRight, + Op::MoveColumnLeftOrToMonitorLeft(0), + Op::MoveColumnRightOrToMonitorRight(1), Op::ConsumeWindowIntoColumn, Op::ExpelWindowFromColumn, Op::CenterColumn,