aboutsummaryrefslogtreecommitdiff
path: root/src/niri.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-08-16 08:03:20 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-08-16 08:03:20 +0400
commitd96daf68a7d1b843b5231e2c416349214c5629d2 (patch)
tree6188bf97bc2aee9455d5148bce5427c942caa278 /src/niri.rs
parent81e8e6e7ce9e933298366141ed00905e7dfd725e (diff)
downloadniri-d96daf68a7d1b843b5231e2c416349214c5629d2.tar.gz
niri-d96daf68a7d1b843b5231e2c416349214c5629d2.tar.bz2
niri-d96daf68a7d1b843b5231e2c416349214c5629d2.zip
Add binds to move between monitors
Diffstat (limited to 'src/niri.rs')
-rw-r--r--src/niri.rs94
1 files changed, 91 insertions, 3 deletions
diff --git a/src/niri.rs b/src/niri.rs
index afc1d305..32a5d319 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -15,7 +15,7 @@ use smithay::desktop::{
layer_map_for_output, LayerSurface, PopupManager, Space, Window, WindowSurfaceType,
};
use smithay::input::keyboard::XkbConfig;
-use smithay::input::pointer::{CursorImageAttributes, CursorImageStatus};
+use smithay::input::pointer::{CursorImageAttributes, CursorImageStatus, MotionEvent};
use smithay::input::{Seat, SeatState};
use smithay::output::Output;
use smithay::reexports::calloop::generic::Generic;
@@ -26,7 +26,7 @@ use smithay::reexports::wayland_server::backend::{
};
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::reexports::wayland_server::{Display, DisplayHandle};
-use smithay::utils::{IsAlive, Logical, Physical, Point, Scale, SERIAL_COUNTER};
+use smithay::utils::{IsAlive, Logical, Physical, Point, Rectangle, Scale, SERIAL_COUNTER};
use smithay::wayland::compositor::{with_states, CompositorClientState, CompositorState};
use smithay::wayland::data_device::DataDeviceState;
use smithay::wayland::output::OutputManagerState;
@@ -38,7 +38,7 @@ use smithay::wayland::socket::ListeningSocketSource;
use crate::backend::Backend;
use crate::frame_clock::FrameClock;
use crate::layout::{MonitorRenderElement, MonitorSet};
-use crate::utils::load_default_cursor;
+use crate::utils::{center, get_monotonic_time, load_default_cursor};
use crate::LoopData;
pub struct Niri {
@@ -268,6 +268,94 @@ impl Niri {
self.global_space.output_under(pos).next().cloned()
}
+ pub fn output_left(&self) -> Option<Output> {
+ let active = self.monitor_set.active_output()?;
+ let active_geo = self.global_space.output_geometry(active).unwrap();
+ let extended_geo = Rectangle::from_loc_and_size(
+ (i32::MIN / 2, active_geo.loc.y),
+ (i32::MAX, active_geo.size.h),
+ );
+
+ self.global_space
+ .outputs()
+ .map(|output| (output, self.global_space.output_geometry(output).unwrap()))
+ .filter(|(_, geo)| center(*geo).x < center(active_geo).x && geo.overlaps(extended_geo))
+ .min_by_key(|(_, geo)| center(active_geo).x - center(*geo).x)
+ .map(|(output, _)| output)
+ .cloned()
+ }
+
+ pub fn output_right(&self) -> Option<Output> {
+ let active = self.monitor_set.active_output()?;
+ let active_geo = self.global_space.output_geometry(active).unwrap();
+ let extended_geo = Rectangle::from_loc_and_size(
+ (i32::MIN / 2, active_geo.loc.y),
+ (i32::MAX, active_geo.size.h),
+ );
+
+ self.global_space
+ .outputs()
+ .map(|output| (output, self.global_space.output_geometry(output).unwrap()))
+ .filter(|(_, geo)| center(*geo).x > center(active_geo).x && geo.overlaps(extended_geo))
+ .min_by_key(|(_, geo)| center(*geo).x - center(active_geo).x)
+ .map(|(output, _)| output)
+ .cloned()
+ }
+
+ pub fn output_up(&self) -> Option<Output> {
+ let active = self.monitor_set.active_output()?;
+ let active_geo = self.global_space.output_geometry(active).unwrap();
+ let extended_geo = Rectangle::from_loc_and_size(
+ (active_geo.loc.x, i32::MIN / 2),
+ (active_geo.size.w, i32::MAX),
+ );
+
+ self.global_space
+ .outputs()
+ .map(|output| (output, self.global_space.output_geometry(output).unwrap()))
+ .filter(|(_, geo)| center(*geo).y < center(active_geo).y && geo.overlaps(extended_geo))
+ .min_by_key(|(_, geo)| center(active_geo).y - center(*geo).y)
+ .map(|(output, _)| output)
+ .cloned()
+ }
+
+ pub fn output_down(&self) -> Option<Output> {
+ let active = self.monitor_set.active_output()?;
+ let active_geo = self.global_space.output_geometry(active).unwrap();
+ let extended_geo = Rectangle::from_loc_and_size(
+ (active_geo.loc.x, i32::MIN / 2),
+ (active_geo.size.w, i32::MAX),
+ );
+
+ self.global_space
+ .outputs()
+ .map(|output| (output, self.global_space.output_geometry(output).unwrap()))
+ .filter(|(_, geo)| center(active_geo).y < center(*geo).y && geo.overlaps(extended_geo))
+ .min_by_key(|(_, geo)| center(*geo).y - center(active_geo).y)
+ .map(|(output, _)| output)
+ .cloned()
+ }
+
+ pub fn move_cursor(&mut self, location: Point<f64, Logical>) {
+ let under = self.surface_under_and_global_space(location);
+ self.seat.get_pointer().unwrap().motion(
+ self,
+ under,
+ &MotionEvent {
+ location,
+ serial: SERIAL_COUNTER.next_serial(),
+ time: get_monotonic_time().as_millis() as u32,
+ },
+ );
+ // FIXME: granular
+ self.queue_redraw_all();
+ }
+
+ pub fn move_cursor_to_output(&mut self, output: &Output) {
+ let geo = self.global_space.output_geometry(output).unwrap();
+ self.move_cursor(center(geo).to_f64());
+ }
+
fn layer_surface_focus(&self) -> Option<WlSurface> {
let output = self.monitor_set.active_output()?;
let layers = layer_map_for_output(output);