feat: space switches region mode to window mode
This commit is contained in:
1 parent
5034cdc54f
commit
d362ee060c
4 files changed
+51
-12
No files matched your search
+10
-3
@@ -172,9 +172,16 @@ fn capture(mode: Mode, common: Common) -> Result<()> {
|
|||||||
}
|
}
|
||||||
Mode::Region => {
|
Mode::Region => {
|
||||||
let frames = wl.capture(&outputs, cursor)?;
|
let frames = wl.capture(&outputs, cursor)?;
|
||||||
let (i, r) = region::select(&mut wl, &outputs, &frames)?;
|
match region::select(&mut wl, &outputs, &frames)? {
|
||||||
let source = frames[i].output.name.clone();
|
region::Choice::Region(i, r) => {
|
||||||
(vec![(frames[i].to_rgba(r), None)], 0, source)
|
let source = frames[i].output.name.clone();
|
||||||
|
(vec![(frames[i].to_rgba(r), None)], 0, source)
|
||||||
|
}
|
||||||
|
region::Choice::Window => {
|
||||||
|
drop(frames);
|
||||||
|
window_shot(&outputs, cursor)?
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Mode::Window => window_shot(&outputs, cursor)?,
|
Mode::Window => window_shot(&outputs, cursor)?,
|
||||||
};
|
};
|
||||||
|
|||||||
+19
-5
@@ -30,8 +30,14 @@ use crate::wayland::{Output, State, Wayland};
|
|||||||
|
|
||||||
pub const NAMESPACE: &str = "valw-overlay";
|
pub const NAMESPACE: &str = "valw-overlay";
|
||||||
|
|
||||||
/// What the user picked: an output index and a rectangle in its frame.
|
/// What the user chose in the overlay.
|
||||||
pub type Picked = (usize, PixelRect);
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Choice {
|
||||||
|
/// A rectangle in the frame of output `.0`.
|
||||||
|
Region(usize, PixelRect),
|
||||||
|
/// Space before dragging: capture a window instead.
|
||||||
|
Window,
|
||||||
|
}
|
||||||
|
|
||||||
/// One full-screen layer surface per output, showing the frozen frame.
|
/// One full-screen layer surface per output, showing the frozen frame.
|
||||||
pub struct Overlay {
|
pub struct Overlay {
|
||||||
@@ -39,7 +45,7 @@ pub struct Overlay {
|
|||||||
selection: Selection,
|
selection: Selection,
|
||||||
/// Output where the current drag started; the capture is clipped to it.
|
/// Output where the current drag started; the capture is clipped to it.
|
||||||
anchor: Option<usize>,
|
anchor: Option<usize>,
|
||||||
outcome: Option<Option<Picked>>,
|
outcome: Option<Option<Choice>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Surface {
|
struct Surface {
|
||||||
@@ -59,7 +65,8 @@ struct Surface {
|
|||||||
|
|
||||||
/// Shows the overlay on every output and waits for a selection.
|
/// Shows the overlay on every output and waits for a selection.
|
||||||
/// Returns `Cancelled` if the user presses Esc or right-clicks.
|
/// Returns `Cancelled` if the user presses Esc or right-clicks.
|
||||||
pub fn select(wl: &mut Wayland, outputs: &[Output], frames: &[Frame]) -> Result<Picked> {
|
/// Space before dragging returns `Choice::Window`.
|
||||||
|
pub fn select(wl: &mut Wayland, outputs: &[Output], frames: &[Frame]) -> Result<Choice> {
|
||||||
let qh = wl.queue.handle();
|
let qh = wl.queue.handle();
|
||||||
let s = &wl.state;
|
let s = &wl.state;
|
||||||
let layer_shell = s
|
let layer_shell = s
|
||||||
@@ -162,6 +169,13 @@ impl Overlay {
|
|||||||
self.outcome.get_or_insert(None);
|
self.outcome.get_or_insert(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn switch_to_window(&mut self) {
|
||||||
|
if self.selection.allows_window_switch() {
|
||||||
|
tracing::info!("switching to window mode");
|
||||||
|
self.outcome.get_or_insert(Some(Choice::Window));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn index_of(&self, surface: &WlSurface) -> Option<usize> {
|
fn index_of(&self, surface: &WlSurface) -> Option<usize> {
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.iter()
|
.iter()
|
||||||
@@ -266,7 +280,7 @@ impl Overlay {
|
|||||||
"selected {rect:?} on {} (logical {start:?} to {end:?})",
|
"selected {rect:?} on {} (logical {start:?} to {end:?})",
|
||||||
s.geom.name
|
s.geom.name
|
||||||
);
|
);
|
||||||
self.outcome = Some(Some((a, rect)));
|
self.outcome = Some(Some(Choice::Region(a, rect)));
|
||||||
}
|
}
|
||||||
// A click, not a drag: clear it and keep waiting.
|
// A click, not a drag: clear it and keep waiting.
|
||||||
None => self.redraw(a, qh),
|
None => self.redraw(a, qh),
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ impl Selection {
|
|||||||
Selection::Idle => None,
|
Selection::Idle => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Space switches to window mode only before a drag starts.
|
||||||
|
pub fn allows_window_switch(&self) -> bool {
|
||||||
|
*self == Selection::Idle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The part of the drag from `a` to `b` that falls on `out`, in the physical
|
/// The part of the drag from `a` to `b` that falls on `out`, in the physical
|
||||||
@@ -77,6 +82,16 @@ pub fn resolve(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn window_switch_only_before_a_drag() {
|
||||||
|
let mut s = Selection::default();
|
||||||
|
assert!(s.allows_window_switch());
|
||||||
|
s.press(Point { x: 1.0, y: 1.0 });
|
||||||
|
assert!(!s.allows_window_switch(), "Space during a drag is reserved");
|
||||||
|
s.release(Point { x: 5.0, y: 5.0 });
|
||||||
|
assert!(s.allows_window_switch());
|
||||||
|
}
|
||||||
|
|
||||||
fn out(name: &str, x: i32, y: i32, width: i32, height: i32) -> OutputGeom {
|
fn out(name: &str, x: i32, y: i32, width: i32, height: i32) -> OutputGeom {
|
||||||
OutputGeom {
|
OutputGeom {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
|
|||||||
+7
-4
@@ -449,10 +449,13 @@ impl KeyboardHandler for State {
|
|||||||
_: u32,
|
_: u32,
|
||||||
event: KeyEvent,
|
event: KeyEvent,
|
||||||
) {
|
) {
|
||||||
if event.keysym == Keysym::Escape
|
let Some(overlay) = &mut self.overlay else {
|
||||||
&& let Some(overlay) = &mut self.overlay
|
return;
|
||||||
{
|
};
|
||||||
overlay.cancel();
|
match event.keysym {
|
||||||
|
Keysym::Escape => overlay.cancel(),
|
||||||
|
Keysym::space => overlay.switch_to_window(),
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user