aboutsummaryrefslogtreecommitdiff
path: root/src/input.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-05-11 13:21:05 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-11 13:21:05 +0400
commitbeba87354a1fd30a95eaaf6c98eec72797e4baa7 (patch)
tree0298d7911dd5daee544b39ae7ee1f537e119cadf /src/input.rs
parent078724369d464d5184a3d93a1b71c10092092d0a (diff)
downloadniri-beba87354a1fd30a95eaaf6c98eec72797e4baa7.tar.gz
niri-beba87354a1fd30a95eaaf6c98eec72797e4baa7.tar.bz2
niri-beba87354a1fd30a95eaaf6c98eec72797e4baa7.zip
Group input-related things in a subfolder
Diffstat (limited to 'src/input.rs')
-rw-r--r--src/input.rs2561
1 files changed, 0 insertions, 2561 deletions
diff --git a/src/input.rs b/src/input.rs
deleted file mode 100644
index ee618068..00000000
--- a/src/input.rs
+++ /dev/null
@@ -1,2561 +0,0 @@
-use std::any::Any;
-use std::collections::hash_map::Entry;
-use std::collections::HashSet;
-use std::time::Duration;
-
-use calloop::timer::{TimeoutAction, Timer};
-use input::event::gesture::GestureEventCoordinates as _;
-use niri_config::{Action, Bind, Binds, Key, Modifiers, Trigger};
-use niri_ipc::LayoutSwitchTarget;
-use smithay::backend::input::{
- AbsolutePositionEvent, Axis, AxisSource, ButtonState, Device, DeviceCapability, Event,
- GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _,
- InputBackend, InputEvent, KeyState, KeyboardKeyEvent, MouseButton, PointerAxisEvent,
- PointerButtonEvent, PointerMotionEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent,
- TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent,
-};
-use smithay::backend::libinput::LibinputInputBackend;
-use smithay::input::keyboard::{keysyms, FilterResult, Keysym, ModifiersState};
-use smithay::input::pointer::{
- AxisFrame, ButtonEvent, CursorImageStatus, Focus, GestureHoldBeginEvent, GestureHoldEndEvent,
- GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
- GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData,
- MotionEvent, RelativeMotionEvent,
-};
-use smithay::input::touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent};
-use smithay::utils::{Logical, Point, SERIAL_COUNTER};
-use smithay::wayland::pointer_constraints::{with_pointer_constraint, PointerConstraint};
-use smithay::wayland::tablet_manager::{TabletDescriptor, TabletSeatTrait};
-
-use crate::niri::State;
-use crate::resize_grab::ResizeGrab;
-use crate::ui::screenshot_ui::ScreenshotUi;
-use crate::utils::spawning::spawn;
-use crate::utils::{center, get_monotonic_time, ResizeEdge};
-
-pub const DOUBLE_CLICK_TIME: Duration = Duration::from_millis(400);
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum CompositorMod {
- Super,
- Alt,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub struct TabletData {
- pub aspect_ratio: f64,
-}
-
-impl State {
- pub fn process_input_event<I: InputBackend + 'static>(&mut self, event: InputEvent<I>)
- where
- I::Device: 'static, // Needed for downcasting.
- {
- let _span = tracy_client::span!("process_input_event");
-
- // A bit of a hack, but animation end runs some logic (i.e. workspace clean-up) and it
- // doesn't always trigger due to damage, etc. So run it here right before it might prove
- // important. Besides, animations affect the input, so it's best to have up-to-date values
- // here.
- self.niri.layout.advance_animations(get_monotonic_time());
-
- if self.niri.monitors_active {
- // Notify the idle-notifier of activity.
- if should_notify_activity(&event) {
- let _span = tracy_client::span!("IdleNotifierState::notify_activity");
- self.niri
- .idle_notifier_state
- .notify_activity(&self.niri.seat);
- }
- } else {
- // Power on monitors if they were off.
- if should_activate_monitors(&event) {
- self.niri.activate_monitors(&mut self.backend);
-
- // Notify the idle-notifier of activity only if we're also powering on the
- // monitors.
- self.niri
- .idle_notifier_state
- .notify_activity(&self.niri.seat);
- }
- }
-
- let hide_hotkey_overlay =
- self.niri.hotkey_overlay.is_open() && should_hide_hotkey_overlay(&event);
-
- let hide_exit_confirm_dialog = self
- .niri
- .exit_confirm_dialog
- .as_ref()
- .map_or(false, |d| d.is_open())
- && should_hide_exit_confirm_dialog(&event);
-
- use InputEvent::*;
- match event {
- DeviceAdded { device } => self.on_device_added(device),
- DeviceRemoved { device } => self.on_device_removed(device),
- Keyboard { event } => self.on_keyboard::<I>(event),
- PointerMotion { event } => self.on_pointer_motion::<I>(event),
- PointerMotionAbsolute { event } => self.on_pointer_motion_absolute::<I>(event),
- PointerButton { event } => self.on_pointer_button::<I>(event),
- PointerAxis { event } => self.on_pointer_axis::<I>(event),
- TabletToolAxis { event } => self.on_tablet_tool_axis::<I>(event),
- TabletToolTip { event } => self.on_tablet_tool_tip::<I>(event),
- TabletToolProximity { event } => self.on_tablet_tool_proximity::<I>(event),
- TabletToolButton { event } => self.on_tablet_tool_button::<I>(event),
- GestureSwipeBegin { event } => self.on_gesture_swipe_begin::<I>(event),
- GestureSwipeUpdate { event } => self.on_gesture_swipe_update::<I>(event),
- GestureSwipeEnd { event } => self.on_gesture_swipe_end::<I>(event),
- GesturePinchBegin { event } => self.on_gesture_pinch_begin::<I>(event),
- GesturePinchUpdate { event } => self.on_gesture_pinch_update::<I>(event),
- GesturePinchEnd { event } => self.on_gesture_pinch_end::<I>(event),
- GestureHoldBegin { event } => self.on_gesture_hold_begin::<I>(event),
- GestureHoldEnd { event } => self.on_gesture_hold_end::<I>(event),
- TouchDown { event } => self.on_touch_down::<I>(event),
- TouchMotion { event } => self.on_touch_motion::<I>(event),
- TouchUp { event } => self.on_touch_up::<I>(event),
- TouchCancel { event } => self.on_touch_cancel::<I>(event),
- TouchFrame { event } => self.on_touch_frame::<I>(event),
- SwitchToggle { .. } => (),
- Special(_) => (),
- }
-
- // Do this last so that screenshot still gets it.
- // FIXME: do this in a less cursed fashion somehow.
- if hide_hotkey_overlay && self.niri.hotkey_overlay.hide() {
- self.niri.queue_redraw_all();
- }
-
- if let Some(dialog) = &mut self.niri.exit_confirm_dialog {
- if hide_exit_confirm_dialog && dialog.hide() {
- self.niri.queue_redraw_all();
- }
- }
- }
-
- pub fn process_libinput_event(&mut self, event: &mut InputEvent<LibinputInputBackend>) {
- let _span = tracy_client::span!("process_libinput_event");
-
- match event {
- InputEvent::DeviceAdded { device } => {
- self.niri.devices.insert(device.clone());
-
- if device.has_capability(input::DeviceCapability::TabletTool) {
- match device.size() {
- Some((w, h)) => {
- let aspect_ratio = w / h;
- let data = TabletData { aspect_ratio };
- self.niri.tablets.insert(device.clone(), data);
- }
- None => {
- warn!("tablet tool device has no size");
- }
- }
- }
-
- if device.has_capability(input::DeviceCapability::Keyboard) {
- if let Some(led_state) = self
- .niri
- .seat
- .get_keyboard()
- .map(|keyboard| keyboard.led_state())
- {
- device.led_update(led_state.into());
- }
- }
-
- if device.has_capability(input::DeviceCapability::Touch) {
- self.niri.touch.insert(device.clone());
- }
-
- apply_libinput_settings(&self.niri.config.borrow().input, device);
- }
- InputEvent::DeviceRemoved { device } => {
- self.niri.touch.remove(device);
- self.niri.tablets.remove(device);
- self.niri.devices.remove(device);
- }
- _ => (),
- }
- }
-
- fn on_device_added(&mut self, device: impl Device) {
- if device.has_capability(DeviceCapability::TabletTool) {
- let tablet_seat = self.niri.seat.tablet_seat();
-
- let desc = TabletDescriptor::from(&device);
- tablet_seat.add_tablet::<Self>(&self.niri.display_handle, &desc);
- }
- if device.has_capability(DeviceCapability::Touch) && self.niri.seat.get_touch().is_none() {
- self.niri.seat.add_touch();
- }
- }
-
- fn on_device_removed(&mut self, device: impl Device) {
- if device.has_capability(DeviceCapability::TabletTool) {
- let tablet_seat = self.niri.seat.tablet_seat();
-
- let desc = TabletDescriptor::from(&device);
- tablet_seat.remove_tablet(&desc);
-
- // If there are no tablets in seat we can remove all tools
- if tablet_seat.count_tablets() == 0 {
- tablet_seat.clear_tools();
- }
- }
- if device.has_capability(DeviceCapability::Touch) && self.niri.touch.is_empty() {
- self.niri.seat.remove_touch();
- }
- }
-
- /// Computes the cursor position for the tablet event.
- ///
- /// This function handles the tablet output mapping, as well as coordinate clamping and aspect
- /// ratio correction.
- fn compute_tablet_position<I: InputBackend>(
- &self,
- event: &(impl Event<I> + TabletToolEvent<I>),
- ) -> Option<Point<f64, Logical>>
- where
- I::Device: 'static,
- {
- let output = self.niri.output_for_tablet()?;
- let output_geo = self.niri.global_space.output_geometry(output).unwrap();
-
- let mut pos = event.position_transformed(output_geo.size);
- pos.x /= output_geo.size.w as f64;
- pos.y /= output_geo.size.h as f64;
-
- let device = event.device();
- if let Some(device) = (&device as &dyn Any).downcast_ref::<input::Device>() {
- if let Some(data) = self.niri.tablets.get(device) {
- // This code does the same thing as mutter with "keep aspect ratio" enabled.
- let output_aspect_ratio = output_geo.size.w as f64 / output_geo.size.h as f64;
- let ratio = data.aspect_ratio / output_aspect_ratio;
-
- if ratio > 1. {
- pos.x *= ratio;
- } else {
- pos.y /= ratio;
- }
- }
- };
-
- pos.x *= output_geo.size.w as f64;
- pos.y *= output_geo.size.h as f64;
- pos.x = pos.x.clamp(0.0, output_geo.size.w as f64 - 1.);
- pos.y = pos.y.clamp(0.0, output_geo.size.h as f64 - 1.);
- Some(pos + output_geo.loc.to_f64())
- }
-
- fn on_keyboard<I: InputBackend>(&mut self, event: I::KeyboardKeyEvent) {
- let comp_mod = self.backend.mod_key();
-
- let serial = SERIAL_COUNTER.next_serial();
- let time = Event::time_msec(&event);
- let pressed = event.state() == KeyState::Pressed;
-
- let Some(Some(bind)) = self.niri.seat.get_keyboard().unwrap().input(
- self,
- event.key_code(),
- event.state(),
- serial,
- time,
- |this, mods, keysym| {
- let bindings = &this.niri.config.borrow().binds;
- let key_code = event.key_code();
- let modified = keysym.modified_sym();
- let raw = keysym.raw_latin_sym_or_raw_current_sym();
-
- if let Some(dialog) = &this.niri.exit_confirm_dialog {
- if dialog.is_open() && pressed && raw == Some(Keysym::Return) {
- info!("quitting after confirming exit dialog");
- this.niri.stop_signal.stop();
- }
- }
-
- should_intercept_key(
- &mut this.niri.suppressed_keys,
- bindings,
- comp_mod,
- key_code,
- modified,
- raw,
- pressed,
- *mods,
- &this.niri.screenshot_ui,
- this.niri.config.borrow().input.disable_power_key_handling,
- )
- },
- ) else {
- return;
- };
-
- // Filter actions when the key is released or the session is locked.
- if !pressed {
- return;
- }
-
- self.handle_bind(bind);
- }
-
- pub fn handle_bind(&mut self, bind: Bind) {
- let Some(cooldown) = bind.cooldown else {
- self.do_action(bind.action, bind.allow_when_locked);
- return;
- };
-
- // Check this first so that it doesn't trigger the cooldown.
- if self.niri.is_locked() && !(bind.allow_when_locked || allowed_when_locked(&bind.action)) {
- return;
- }
-
- match self.niri.bind_cooldown_timers.entry(bind.key) {
- // The bind is on cooldown.
- Entry::Occupied(_) => (),
- Entry::Vacant(entry) => {
- let timer = Timer::from_duration(cooldown);
- let token = self
- .niri
- .event_loop
- .insert_source(timer, move |_, _, state| {
- if state.niri.bind_cooldown_timers.remove(&bind.key).is_none() {
- error!("bind cooldown timer entry disappeared");
- }
- TimeoutAction::Drop
- })
- .unwrap();
- entry.insert(token);
-
- self.do_action(bind.action, bind.allow_when_locked);
- }
- }
- }
-
- pub fn do_action(&mut self, action: Action, allow_when_locked: bool) {
- if self.niri.is_locked() && !(allow_when_locked || allowed_when_locked(&action)) {
- return;
- }
-
- if let Some(touch) = self.niri.seat.get_touch() {
- touch.cancel(self);
- }
-
- match action {
- Action::Quit(skip_confirmation) => {
- if !skip_confirmation {
- if let Some(dialog) = &mut self.niri.exit_confirm_dialog {
- if dialog.show() {
- self.niri.queue_redraw_all();
- }
- return;
- }
- }
-
- info!("quitting as requested");
- self.niri.stop_signal.stop()
- }
- Action::ChangeVt(vt) => {
- self.backend.change_vt(vt);
- // Changing VT may not deliver the key releases, so clear the state.
- self.niri.suppressed_keys.clear();
- }
- Action::Suspend => {
- self.backend.suspend();
- // Suspend may not deliver the key releases, so clear the state.
- self.niri.suppressed_keys.clear();
- }
- Action::PowerOffMonitors => {
- self.niri.deactivate_monitors(&mut self.backend);
- }
- Action::ToggleDebugTint => {
- self.backend.toggle_debug_tint();
- self.niri.queue_redraw_all();
- }
- Action::DebugToggleOpaqueRegions => {
- self.niri.debug_draw_opaque_regions = !self.niri.debug_draw_opaque_regions;
- self.niri.queue_redraw_all();
- }
- Action::DebugToggleDamage => {
- self.niri.debug_toggle_damage();
- }
- Action::Spawn(command) => {
- spawn(command);
- }
- Action::DoScreenTransition(delay_ms) => {
- self.backend.with_primary_renderer(|renderer| {
- self.niri.do_screen_transition(renderer, delay_ms);
- });
- }
- Action::ScreenshotScreen => {
- let active = self.niri.layout.active_output().cloned();
- if let Some(active) = active {
- self.backend.with_primary_renderer(|renderer| {
- if let Err(err) = self.niri.screenshot(renderer, &active) {
- warn!("error taking screenshot: {err:?}");
- }
- });
- }
- }
- Action::ConfirmScreenshot => {
- self.backend.with_primary_renderer(|renderer| {
- match self.niri.screenshot_ui.capture(renderer) {
- Ok((size, pixels)) => {
- if let Err(err) = self.niri.save_screenshot(size, pixels) {
- warn!("error saving screenshot: {err:?}");
- }
- }
- Err(err) => {
- warn!("error capturing screenshot: {err:?}");
- }
- }
- });
-
- self.niri.screenshot_ui.close();
- self.niri
- .cursor_manager
- .set_cursor_image(CursorImageStatus::default_named());
- self.niri.queue_redraw_all();
- }
- Action::CancelScreenshot => {
- self.niri.screenshot_ui.close();
- self.niri
- .cursor_manager
- .set_cursor_image(CursorImageStatus::default_named());
- self.niri.queue_redraw_all();
- }
- Action::Screenshot => {
- self.backend.with_primary_renderer(|renderer| {
- self.niri.open_screenshot_ui(renderer);
- });
- }
- Action::ScreenshotWindow => {
- let active = self.niri.layout.active_window();
- if let Some((mapped, output)) = active {
- self.backend.with_primary_renderer(|renderer| {
- if let Err(err) = self.niri.screenshot_window(renderer, output, mapped) {
- warn!("error taking screenshot: {err:?}");
- }
- });
- }
- }
- Action::CloseWindow => {
- if let Some(mapped) = self.niri.layout.focus() {
- mapped.toplevel().send_close();
- }
- }
- Action::FullscreenWindow => {
- let focus = self.niri.layout.focus().map(|m| m.window.clone());
- if let Some(window) = focus {
- self.niri.layout.toggle_fullscreen(&window);
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- }
- Action::SwitchLayout(action) => {
- self.niri.seat.get_keyboard().unwrap().with_xkb_state(
- self,
- |mut state| match action {
- LayoutSwitchTarget::Next => state.cycle_next_layout(),
- LayoutSwitchTarget::Prev => state.cycle_prev_layout(),
- },
- );
- }
- Action::MoveColumnLeft => {
- 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();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveColumnToFirst => {
- self.niri.layout.move_column_to_first();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveColumnToLast => {
- self.niri.layout.move_column_to_last();
- 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();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveWindowUp => {
- self.niri.layout.move_up();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveWindowDownOrToWorkspaceDown => {
- self.niri.layout.move_down_or_to_workspace_down();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveWindowUpOrToWorkspaceUp => {
- self.niri.layout.move_up_or_to_workspace_up();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::ConsumeOrExpelWindowLeft => {
- self.niri.layout.consume_or_expel_window_left();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::ConsumeOrExpelWindowRight => {
- self.niri.layout.consume_or_expel_window_right();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusColumnLeft => {
- self.niri.layout.focus_left();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusColumnRight => {
- self.niri.layout.focus_right();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusColumnFirst => {
- self.niri.layout.focus_column_first();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusColumnLast => {
- self.niri.layout.focus_column_last();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusWindowDown => {
- self.niri.layout.focus_down();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusWindowUp => {
- self.niri.layout.focus_up();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusWindowOrWorkspaceDown => {
- self.niri.layout.focus_window_or_workspace_down();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusWindowOrWorkspaceUp => {
- self.niri.layout.focus_window_or_workspace_up();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveWindowToWorkspaceDown => {
- self.niri.layout.move_to_workspace_down();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveWindowToWorkspaceUp => {
- self.niri.layout.move_to_workspace_up();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveWindowToWorkspace(idx) => {
- let idx = idx.saturating_sub(1) as usize;
- self.niri.layout.move_to_workspace(idx);
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveColumnToWorkspaceDown => {
- self.niri.layout.move_column_to_workspace_down();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveColumnToWorkspaceUp => {
- self.niri.layout.move_column_to_workspace_up();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveColumnToWorkspace(idx) => {
- let idx = idx.saturating_sub(1) as usize;
- self.niri.layout.move_column_to_workspace(idx);
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusWorkspaceDown => {
- self.niri.layout.switch_workspace_down();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusWorkspaceUp => {
- self.niri.layout.switch_workspace_up();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusWorkspace(idx) => {
- let idx = idx.saturating_sub(1) as usize;
-
- let config = &self.niri.config;
- if config.borrow().input.workspace_auto_back_and_forth {
- self.niri.layout.switch_workspace_auto_back_and_forth(idx);
- } else {
- self.niri.layout.switch_workspace(idx);
- }
-
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::FocusWorkspacePrevious => {
- self.niri.layout.switch_workspace_previous();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveWorkspaceDown => {
- self.niri.layout.move_workspace_down();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MoveWorkspaceUp => {
- self.niri.layout.move_workspace_up();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::ConsumeWindowIntoColumn => {
- self.niri.layout.consume_into_column();
- // This does not cause immediate focus or window size change, so warping mouse to
- // focus won't do anything here.
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::ExpelWindowFromColumn => {
- self.niri.layout.expel_from_column();
- self.maybe_warp_cursor_to_focus();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::SwitchPresetColumnWidth => {
- self.niri.layout.toggle_width();
- }
- Action::CenterColumn => {
- self.niri.layout.center_column();
- // FIXME: granular
- self.niri.queue_redraw_all();
- }
- Action::MaximizeColumn => {
- self.niri.layout.toggle_full_width();
- }
- Action::FocusMonitorLeft => {
- if let Some(output) = self.niri.output_left() {
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::FocusMonitorRight => {
- if let Some(output) = self.niri.output_right() {
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::FocusMonitorDown => {
- if let Some(output) = self.niri.output_down() {
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::FocusMonitorUp => {
- if let Some(output) = self.niri.output_up() {
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveWindowToMonitorLeft => {
- if let Some(output) = self.niri.output_left() {
- self.niri.layout.move_to_output(&output);
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveWindowToMonitorRight => {
- if let Some(output) = self.niri.output_right() {
- self.niri.layout.move_to_output(&output);
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveWindowToMonitorDown => {
- if let Some(output) = self.niri.output_down() {
- self.niri.layout.move_to_output(&output);
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveWindowToMonitorUp => {
- if let Some(output) = self.niri.output_up() {
- self.niri.layout.move_to_output(&output);
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveColumnToMonitorLeft => {
- if let Some(output) = self.niri.output_left() {
- self.niri.layout.move_column_to_output(&output);
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveColumnToMonitorRight => {
- if let Some(output) = self.niri.output_right() {
- self.niri.layout.move_column_to_output(&output);
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveColumnToMonitorDown => {
- if let Some(output) = self.niri.output_down() {
- self.niri.layout.move_column_to_output(&output);
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveColumnToMonitorUp => {
- if let Some(output) = self.niri.output_up() {
- self.niri.layout.move_column_to_output(&output);
- self.niri.layout.focus_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::SetColumnWidth(change) => {
- self.niri.layout.set_column_width(change);
- }
- Action::SetWindowHeight(change) => {
- self.niri.layout.set_window_height(change);
- }
- Action::ResetWindowHeight => {
- self.niri.layout.reset_window_height();
- }
- Action::ShowHotkeyOverlay => {
- if self.niri.hotkey_overlay.show() {
- self.niri.queue_redraw_all();
- }
- }
- Action::MoveWorkspaceToMonitorLeft => {
- if let Some(output) = self.niri.output_left() {
- self.niri.layout.move_workspace_to_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveWorkspaceToMonitorRight => {
- if let Some(output) = self.niri.output_right() {
- self.niri.layout.move_workspace_to_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveWorkspaceToMonitorDown => {
- if let Some(output) = self.niri.output_down() {
- self.niri.layout.move_workspace_to_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- Action::MoveWorkspaceToMonitorUp => {
- if let Some(output) = self.niri.output_up() {
- self.niri.layout.move_workspace_to_output(&output);
- if !self.maybe_warp_cursor_to_focus_centered() {
- self.move_cursor_to_output(&output);
- }
- }
- }
- }
- }
-
- fn on_pointer_motion<I: InputBackend>(&mut self, event: I::PointerMotionEvent) {
- // We need an output to be able to move the pointer.
- if self.niri.global_space.outputs().next().is_none() {
- return;
- }
-
- let serial = SERIAL_COUNTER.next_serial();
-
- let pointer = self.niri.seat.get_pointer().unwrap();
-
- let pos = pointer.current_location();
-
- // We have an output, so we can compute the new location and focus.
- let mut new_pos = pos + event.delta();
-
- // We received an event for the regular pointer, so show it now.
- self.niri.pointer_hidden = false;
- self.niri.tablet_cursor_location = None;
-
- // Check if we have an active pointer constraint.
- let mut pointer_confined = None;
- if let Some(focus) = &self.niri.pointer_focus.surface {
- let pos_within_surface = pos.to_i32_round() - focus.1;
-
- let mut pointer_locked = false;
- with_pointer_constraint(&focus.0, &pointer, |constraint| {
- let Some(constraint) = constraint else { return };
- if !constraint.is_active() {
- return;
- }
-
- // Constraint does not apply if not within region.
- if let Some(region) = constraint.region() {
- if !region.contains(pos_within_surface) {
- return;
- }
- }
-
- match &*constraint {
- PointerConstraint::Locked(_locked) => {
- pointer_locked = true;
- }
- PointerConstraint::Confined(confine) => {
- pointer_confined = Some((focus.clone(), confine.region().cloned()));
- }
- }
- });
-
- // If the pointer is locked, only send relative motion.
- if pointer_locked {
- pointer.relative_motion(
- self,
- Some(focus.clone()),
- &RelativeMotionEvent {
- delta: event.delta(),
- delta_unaccel: event.delta_unaccel(),
- utime: event.time(),
- },
- );
-
- pointer.frame(self);
-
- // I guess a redraw to hide the tablet cursor could be nice? Doesn't matter too
- // much here I think.