Compare commits

...

3 Commits

Author SHA1 Message Date
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
Ivan Molodetskikh
f9fe86ee3e Restore VRR on TTY switch 2024-07-09 14:25:02 +04:00
5 changed files with 179 additions and 26 deletions

View File

@ -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 => {

View File

@ -153,6 +153,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.

View File

@ -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::*;

View File

@ -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();

View File

@ -1196,6 +1196,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;
@ -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,