diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-11 13:21:05 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-11 13:21:05 +0400 |
| commit | beba87354a1fd30a95eaaf6c98eec72797e4baa7 (patch) | |
| tree | 0298d7911dd5daee544b39ae7ee1f537e119cadf /src/input.rs | |
| parent | 078724369d464d5184a3d93a1b71c10092092d0a (diff) | |
| download | niri-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.rs | 2561 |
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. |
