aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authornyx <nnyyxxxx@protonmail.com>2025-03-29 03:40:21 -0400
committerGitHub <noreply@github.com>2025-03-29 07:40:21 +0000
commit7dc015e16b30be457a227601de85f085e5af1dda (patch)
tree061bcf50826d4ad03f6f7b16535d6e2ea94655de /src
parent0db48e2f1bf001bfd05c686002ff1998d0f1205b (diff)
downloadniri-7dc015e16b30be457a227601de85f085e5af1dda.tar.gz
niri-7dc015e16b30be457a227601de85f085e5af1dda.tar.bz2
niri-7dc015e16b30be457a227601de85f085e5af1dda.zip
screenshot: make selection area modifiable via move/resize keybinds (#1279)
* screenshot: make selection area modifiable via keybinds * input: run fmt * Reimplement screenshot UI binds in a better way --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/input/mod.rs71
-rw-r--r--src/layout/floating.rs2
-rw-r--r--src/ui/screenshot_ui.rs158
3 files changed, 219 insertions, 12 deletions
diff --git a/src/input/mod.rs b/src/input/mod.rs
index 961df54a..c6b5441a 100644
--- a/src/input/mod.rs
+++ b/src/input/mod.rs
@@ -740,14 +740,24 @@ impl State {
});
}
Action::MoveColumnLeft => {
- self.niri.layout.move_left();
- self.maybe_warp_cursor_to_focus();
+ if self.niri.screenshot_ui.is_open() {
+ self.niri.screenshot_ui.move_left();
+ } else {
+ self.niri.layout.move_left();
+ self.maybe_warp_cursor_to_focus();
+ }
+
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::MoveColumnRight => {
- self.niri.layout.move_right();
- self.maybe_warp_cursor_to_focus();
+ if self.niri.screenshot_ui.is_open() {
+ self.niri.screenshot_ui.move_right();
+ } else {
+ self.niri.layout.move_right();
+ self.maybe_warp_cursor_to_focus();
+ }
+
// FIXME: granular
self.niri.queue_redraw_all();
}
@@ -798,14 +808,24 @@ impl State {
self.niri.queue_redraw_all();
}
Action::MoveWindowDown => {
- self.niri.layout.move_down();
- self.maybe_warp_cursor_to_focus();
+ if self.niri.screenshot_ui.is_open() {
+ self.niri.screenshot_ui.move_down();
+ } else {
+ self.niri.layout.move_down();
+ self.maybe_warp_cursor_to_focus();
+ }
+
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::MoveWindowUp => {
- self.niri.layout.move_up();
- self.maybe_warp_cursor_to_focus();
+ if self.niri.screenshot_ui.is_open() {
+ self.niri.screenshot_ui.move_up();
+ } else {
+ self.niri.layout.move_up();
+ self.maybe_warp_cursor_to_focus();
+ }
+
// FIXME: granular
self.niri.queue_redraw_all();
}
@@ -1589,10 +1609,24 @@ impl State {
}
}
Action::SetColumnWidth(change) => {
- self.niri.layout.set_column_width(change);
+ if self.niri.screenshot_ui.is_open() {
+ self.niri.screenshot_ui.set_width(change);
+
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ } else {
+ self.niri.layout.set_column_width(change);
+ }
}
Action::SetWindowWidth(change) => {
- self.niri.layout.set_window_width(None, change);
+ if self.niri.screenshot_ui.is_open() {
+ self.niri.screenshot_ui.set_width(change);
+
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ } else {
+ self.niri.layout.set_window_width(None, change);
+ }
}
Action::SetWindowWidthById { id, change } => {
let window = self.niri.layout.windows().find(|(_, m)| m.id().get() == id);
@@ -1602,7 +1636,14 @@ impl State {
}
}
Action::SetWindowHeight(change) => {
- self.niri.layout.set_window_height(None, change);
+ if self.niri.screenshot_ui.is_open() {
+ self.niri.screenshot_ui.set_height(change);
+
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ } else {
+ self.niri.layout.set_window_height(None, change);
+ }
}
Action::SetWindowHeightById { id, change } => {
let window = self.niri.layout.windows().find(|(_, m)| m.id().get() == id);
@@ -3418,6 +3459,14 @@ fn allowed_during_screenshot(action: &Action) -> bool {
| Action::Suspend
| Action::PowerOffMonitors
| Action::PowerOnMonitors
+ // The screenshot UI can handle these.
+ | Action::MoveColumnLeft
+ | Action::MoveColumnRight
+ | Action::MoveWindowUp
+ | Action::MoveWindowDown
+ | Action::SetWindowWidth(_)
+ | Action::SetWindowHeight(_)
+ | Action::SetColumnWidth(_)
)
}
diff --git a/src/layout/floating.rs b/src/layout/floating.rs
index 4fd7c7ee..a88e5bf4 100644
--- a/src/layout/floating.rs
+++ b/src/layout/floating.rs
@@ -26,7 +26,7 @@ use crate::utils::{
use crate::window::ResolvedWindowRules;
/// By how many logical pixels the directional move commands move floating windows.
-const DIRECTIONAL_MOVE_PX: f64 = 50.;
+pub const DIRECTIONAL_MOVE_PX: f64 = 50.;
/// Space for floating windows.
#[derive(Debug)]
diff --git a/src/ui/screenshot_ui.rs b/src/ui/screenshot_ui.rs
index 14675f7b..46a8d1b6 100644
--- a/src/ui/screenshot_ui.rs
+++ b/src/ui/screenshot_ui.rs
@@ -7,6 +7,7 @@ use std::rc::Rc;
use anyhow::Context;
use arrayvec::ArrayVec;
use niri_config::{Action, Config};
+use niri_ipc::SizeChange;
use pango::{Alignment, FontDescription};
use pangocairo::cairo::{self, ImageSurface};
use smithay::backend::allocator::Fourcc;
@@ -20,6 +21,7 @@ use smithay::output::{Output, WeakOutput};
use smithay::utils::{Physical, Point, Rectangle, Scale, Size, Transform};
use crate::animation::{Animation, Clock};
+use crate::layout::floating::DIRECTIONAL_MOVE_PX;
use crate::niri_render_elements;
use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement;
use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
@@ -238,6 +240,162 @@ impl ScreenshotUi {
matches!(self, ScreenshotUi::Open { .. })
}
+ pub fn move_left(&mut self) {
+ let Self::Open {
+ selection: (output, a, b),
+ output_data,
+ ..
+ } = self
+ else {
+ return;
+ };
+
+ let data = &output_data[output];
+
+ let delta: i32 = to_physical_precise_round(data.scale, DIRECTIONAL_MOVE_PX);
+ let delta = min(delta, min(a.x, b.x));
+ a.x -= delta;
+ b.x -= delta;
+
+ self.update_buffers();
+ }
+
+ pub fn move_right(&mut self) {
+ let Self::Open {
+ selection: (output, a, b),
+ output_data,
+ ..
+ } = self
+ else {
+ return;
+ };
+
+ let data = &output_data[output];
+
+ let delta: i32 = to_physical_precise_round(data.scale, DIRECTIONAL_MOVE_PX);
+ let delta = min(delta, data.size.w - max(a.x, b.x) - 1);
+ a.x += delta;
+ b.x += delta;
+
+ self.update_buffers();
+ }
+
+ pub fn move_up(&mut self) {
+ let Self::Open {
+ selection: (output, a, b),
+ output_data,
+ ..
+ } = self
+ else {
+ return;
+ };
+
+ let data = &output_data[output];
+
+ let delta: i32 = to_physical_precise_round(data.scale, DIRECTIONAL_MOVE_PX);
+ let delta = min(delta, min(a.y, b.y));
+ a.y -= delta;
+ b.y -= delta;
+
+ self.update_buffers();
+ }
+
+ pub fn move_down(&mut self) {
+ let Self::Open {
+ selection: (output, a, b),
+ output_data,
+ ..
+ } = self
+ else {
+ return;
+ };
+
+ let data = &output_data[output];
+
+ let delta: i32 = to_physical_precise_round(data.scale, DIRECTIONAL_MOVE_PX);
+ let delta = min(delta, data.size.h - max(a.y, b.y) - 1);
+ a.y += delta;
+ b.y += delta;
+
+ self.update_buffers();
+ }
+
+ pub fn set_width(&mut self, change: SizeChange) {
+ let Self::Open {
+ selection: (output, a, b),
+ output_data,
+ ..
+ } = self
+ else {
+ return;
+ };
+
+ let data = &output_data[output];
+
+ let available_size = f64::from(data.size.w);
+ let current_size = max(a.x, b.x) + 1 - min(a.x, b.x);
+
+ let new_size = match change {
+ SizeChange::SetFixed(fixed) => to_physical_precise_round(data.scale, fixed),
+ SizeChange::SetProportion(prop) => {
+ let prop = (prop / 100.).clamp(0., 1.);
+ (available_size * prop).round() as i32
+ }
+ SizeChange::AdjustFixed(delta) => {
+ let delta = to_physical_precise_round(data.scale, delta);
+ current_size.saturating_add(delta)
+ }
+ SizeChange::AdjustProportion(delta) => {
+ let current_prop = f64::from(current_size) / available_size;
+ let prop = (current_prop + delta / 100.).clamp(0., 1.);
+ (available_size * prop).round() as i32
+ }
+ };
+ let new_size = new_size.clamp(1, data.size.w - min(a.x, b.x)) - 1;
+ a.x = min(a.x, b.x);
+ b.x = a.x + new_size;
+
+ self.update_buffers();
+ }
+
+ pub fn set_height(&mut self, change: SizeChange) {
+ let Self::Open {
+ selection: (output, a, b),
+ output_data,
+ ..
+ } = self
+ else {
+ return;
+ };
+
+ let data = &output_data[output];
+
+ let available_size = f64::from(data.size.h);
+ let current_size = max(a.y, b.y) + 1 - min(a.y, b.y);
+
+ let new_size = match change {
+ SizeChange::SetFixed(fixed) => to_physical_precise_round(data.scale, fixed),
+ SizeChange::SetProportion(prop) => {
+ let prop = (prop / 100.).clamp(0., 1.);
+ (available_size * prop).round() as i32
+ }
+ SizeChange::AdjustFixed(delta) => {
+ let delta = to_physical_precise_round(data.scale, delta);
+ current_size.saturating_add(delta)
+ }
+ SizeChange::AdjustProportion(delta) => {
+ let current_prop = f64::from(current_size) / available_size;
+ let prop = (current_prop + delta / 100.).clamp(0., 1.);
+ (available_size * prop).round() as i32
+ }
+ };
+ let new_size = new_size.clamp(1, data.size.h - min(a.y, b.y)) - 1;
+ a.y = min(a.y, b.y);
+ b.y = a.y + new_size;
+
+ self.update_buffers();
+ }
+
pub fn advance_animations(&mut self) {}
pub fn are_animations_ongoing(&self) -> bool {