diff options
| author | nyx <nnyyxxxx@protonmail.com> | 2025-03-29 03:40:21 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-29 07:40:21 +0000 |
| commit | 7dc015e16b30be457a227601de85f085e5af1dda (patch) | |
| tree | 061bcf50826d4ad03f6f7b16535d6e2ea94655de | |
| parent | 0db48e2f1bf001bfd05c686002ff1998d0f1205b (diff) | |
| download | niri-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>
| -rw-r--r-- | src/input/mod.rs | 71 | ||||
| -rw-r--r-- | src/layout/floating.rs | 2 | ||||
| -rw-r--r-- | src/ui/screenshot_ui.rs | 158 |
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 { |
