diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2023-12-09 09:22:58 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2023-12-09 09:22:58 +0400 |
| commit | 23a5bd36701f1a8da8e886d28d64e4fa8b46042b (patch) | |
| tree | e4485568b78b78ee3ebbdb2120e69bd798626f6b /src/input.rs | |
| parent | d397375d574bc64fdc0ecb91daa267a2fedff4fe (diff) | |
| download | niri-23a5bd36701f1a8da8e886d28d64e4fa8b46042b.tar.gz niri-23a5bd36701f1a8da8e886d28d64e4fa8b46042b.tar.bz2 niri-23a5bd36701f1a8da8e886d28d64e4fa8b46042b.zip | |
Extract input handlers to functions
Diffstat (limited to 'src/input.rs')
| -rw-r--r-- | src/input.rs | 1730 |
1 files changed, 887 insertions, 843 deletions
diff --git a/src/input.rs b/src/input.rs index 300577be..5b5e8b3d 100644 --- a/src/input.rs +++ b/src/input.rs @@ -53,952 +53,996 @@ impl State { self.niri.activate_monitors(&self.backend); } - let comp_mod = self.backend.mod_key(); - + use InputEvent::*; match event { - InputEvent::Keyboard { event, .. } => { - let serial = SERIAL_COUNTER.next_serial(); - let time = Event::time_msec(&event); - let pressed = event.state() == KeyState::Pressed; + 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 { .. } => (), + TouchMotion { .. } => (), + TouchUp { .. } => (), + TouchCancel { .. } => (), + TouchFrame { .. } => (), + Special(_) => (), + } + } - let Some(Some(action)) = 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(); - should_intercept_key( - &mut this.niri.suppressed_keys, - bindings, - comp_mod, - key_code, - modified, - raw, - pressed, - *mods, - &this.niri.screenshot_ui, - ) - }, - ) else { - return; - }; + pub fn process_libinput_event(&mut self, event: &mut InputEvent<LibinputInputBackend>) { + match event { + InputEvent::DeviceAdded { device } => { + // According to Mutter code, this setting is specific to touchpads. + let is_touchpad = device.config_tap_finger_count() > 0; + if is_touchpad { + let c = &self.niri.config.borrow().input.touchpad; + let _ = device.config_tap_set_enabled(c.tap); + let _ = device.config_scroll_set_natural_scroll_enabled(c.natural_scroll); + let _ = device.config_accel_set_speed(c.accel_speed); + } - // Filter actions when the key is released or the session is locked. - if !pressed { - return; + if device.has_capability(smithay::reexports::input::DeviceCapability::TabletTool) { + match device.size() { + Some((w, h)) => { + self.niri.tablets.insert( + device.clone(), + TabletData { + aspect_ratio: w / h, + }, + ); + } + None => { + warn!("tablet tool device has no size"); + } + } } + } + InputEvent::DeviceRemoved { device } => { + self.niri.tablets.remove(device); + } + _ => (), + } + } - if self.niri.is_locked() - && !matches!( - action, - Action::Quit - | Action::ChangeVt(_) - | Action::Suspend - | Action::PowerOffMonitors - | Action::SwitchLayout(_) - ) - { - return; + fn on_device_added(&mut self, device: impl Device) { + if device.has_capability(DeviceCapability::TabletTool) { + self.niri + .seat + .tablet_seat() + .add_tablet::<Self>(&self.niri.display_handle, &TabletDescriptor::from(&device)); + } + } + + fn on_device_removed(&mut self, device: impl Device) { + if device.has_capability(DeviceCapability::TabletTool) { + let tablet_seat = self.niri.seat.tablet_seat(); + + tablet_seat.remove_tablet(&TabletDescriptor::from(&device)); + + // If there are no tablets in seat we can remove all tools + if tablet_seat.count_tablets() == 0 { + tablet_seat.clear_tools(); + } + } + } + + fn compute_tablet_position<I: InputBackend>( + &mut 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; } + } + }; - match action { - Action::Quit => { - info!("quitting because quit bind was pressed"); - 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(&self.backend); - } - Action::ToggleDebugTint => { - self.backend.toggle_debug_tint(); - } - Action::Spawn(command) => { - spawn(command); - } - Action::ScreenshotScreen => { - let active = self.niri.layout.active_output().cloned(); - if let Some(active) = active { - if let Some(renderer) = self.backend.renderer() { - if let Err(err) = self.niri.screenshot(renderer, &active) { - warn!("error taking screenshot: {err:?}"); - } - } - } - } - Action::ConfirmScreenshot => { - if let Some(renderer) = self.backend.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:?}"); - } - } - } + 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()) + } - 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 => { - if let Some(renderer) = self.backend.renderer() { - self.niri.open_screenshot_ui(renderer); + 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(action)) = 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(); + should_intercept_key( + &mut this.niri.suppressed_keys, + bindings, + comp_mod, + key_code, + modified, + raw, + pressed, + *mods, + &this.niri.screenshot_ui, + ) + }, + ) else { + return; + }; + + // Filter actions when the key is released or the session is locked. + if !pressed { + return; + } + + if self.niri.is_locked() + && !matches!( + action, + Action::Quit + | Action::ChangeVt(_) + | Action::Suspend + | Action::PowerOffMonitors + | Action::SwitchLayout(_) + ) + { + return; + } + + match action { + Action::Quit => { + info!("quitting because quit bind was pressed"); + 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(&self.backend); + } + Action::ToggleDebugTint => { + self.backend.toggle_debug_tint(); + } + Action::Spawn(command) => { + spawn(command); + } + Action::ScreenshotScreen => { + let active = self.niri.layout.active_output().cloned(); + if let Some(active) = active { + if let Some(renderer) = self.backend.renderer() { + if let Err(err) = self.niri.screenshot(renderer, &active) { + warn!("error taking screenshot: {err:?}"); } } - Action::ScreenshotWindow => { - let active = self.niri.layout.active_window(); - if let Some((window, output)) = active { - if let Some(renderer) = self.backend.renderer() { - if let Err(err) = - self.niri.screenshot_window(renderer, &output, &window) - { - warn!("error taking screenshot: {err:?}"); - } + } + } + Action::ConfirmScreenshot => { + if let Some(renderer) = self.backend.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:?}"); } } - } - Action::CloseWindow => { - if let Some(window) = self.niri.layout.focus() { - window.toplevel().send_close(); + Err(err) => { + warn!("error capturing screenshot: {err:?}"); } } - Action::FullscreenWindow => { - let focus = self.niri.layout.focus().cloned(); - if let Some(window) = focus { - self.niri.layout.toggle_fullscreen(&window); - } - } - Action::SwitchLayout(action) => { - self.niri - .seat - .get_keyboard() - .unwrap() - .with_xkb_state(self, |mut state| match action { - LayoutAction::Next => state.cycle_next_layout(), - LayoutAction::Prev => state.cycle_prev_layout(), - }); - } - Action::MoveColumnLeft => { - self.niri.layout.move_left(); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::MoveColumnRight => { - self.niri.layout.move_right(); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::MoveWindowDown => { - self.niri.layout.move_down(); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::MoveWindowUp => { - self.niri.layout.move_up(); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::FocusColumnLeft => { - self.niri.layout.focus_left(); - } - Action::FocusColumnRight => { - self.niri.layout.focus_right(); - } - Action::FocusWindowDown => { - self.niri.layout.focus_down(); - } - Action::FocusWindowUp => { - self.niri.layout.focus_up(); - } - Action::MoveWindowToWorkspaceDown => { - self.niri.layout.move_to_workspace_down(); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::MoveWindowToWorkspaceUp => { - self.niri.layout.move_to_workspace_up(); - // 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); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::FocusWorkspaceDown => { - self.niri.layout.switch_workspace_down(); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::FocusWorkspaceUp => { - self.niri.layout.switch_workspace_up(); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::FocusWorkspace(idx) => { - let idx = idx.saturating_sub(1) as usize; - self.niri.layout.switch_workspace(idx); - // 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(); - // FIXME: granular - self.niri.queue_redraw_all(); - } - Action::ExpelWindowFromColumn => { - self.niri.layout.expel_from_column(); - // 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); - self.move_cursor_to_output(&output); - } - } - Action::FocusMonitorRight => { - if let Some(output) = self.niri.output_right() { - self.niri.layout.focus_output(&output); - self.move_cursor_to_output(&output); - } - } - Action::FocusMonitorDown => { - if let Some(output) = self.niri.output_down() { - self.niri.layout.focus_output(&output); - self.move_cursor_to_output(&output); - } - } - Action::FocusMonitorUp => { - if let Some(output) = self.niri.output_up() { - self.niri.layout.focus_output(&output); - self.move_cursor_to_output(&output); - } - } - Action::MoveWindowToMonitorLeft => { - if let Some(output) = self.niri.output_left() { - self.niri.layout.move_to_output(&output); - self.move_cursor_to_output(&output); - } - } - Action::MoveWindowToMonitorRight => { - if let Some(output) = self.niri.output_right() { - self.niri.layout.move_to_output(&output); - self.move_cursor_to_output(&output); - } - } - Action::MoveWindowToMonitorDown => { - if let Some(output) = self.niri.output_down() { - self.niri.layout.move_to_output(&output); - self.move_cursor_to_output(&output); - } - } - Action::MoveWindowToMonitorUp => { - if let Some(output) = self.niri.output_up() { - self.niri.layout.move_to_output(&output); - self.move_cursor_to_output(&output); + } + + 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 => { + if let Some(renderer) = self.backend.renderer() { + self.niri.open_screenshot_ui(renderer); + } + } + Action::ScreenshotWindow => { + let active = self.niri.layout.active_window(); + if let Some((window, output)) = active { + if let Some(renderer) = self.backend.renderer() { + if let Err(err) = self.niri.screenshot_window(renderer, &output, &window) { + warn!("error taking screenshot: {err:?}"); } } - Action::SetColumnWidth(change) => { - self.niri.layout.set_column_width(change); - } - Action::SetWindowHeight(change) => { - self.niri.layout.set_window_height(change); - } } } - InputEvent::PointerMotion { event, .. } => { - // We need an output to be able to move the pointer. - if self.niri.global_space.outputs().next().is_none() { - return; + Action::CloseWindow => { + if let Some(window) = self.niri.layout.focus() { + window.toplevel().send_close(); } + } + Action::FullscreenWindow => { + let focus = self.niri.layout.focus().cloned(); + if let Some(window) = focus { + self.niri.layout.toggle_fullscreen(&window); + } + } + Action::SwitchLayout(action) => { + self.niri.seat.get_keyboard().unwrap().with_xkb_state( + self, + |mut state| match action { + LayoutAction::Next => state.cycle_next_layout(), + LayoutAction::Prev => state.cycle_prev_layout(), + }, + ); + } + Action::MoveColumnLeft => { + self.niri.layout.move_left(); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::MoveColumnRight => { + self.niri.layout.move_right(); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::MoveWindowDown => { + self.niri.layout.move_down(); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::MoveWindowUp => { + self.niri.layout.move_up(); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::FocusColumnLeft => { + self.niri.layout.focus_left(); + } + Action::FocusColumnRight => { + self.niri.layout.focus_right(); + } + Action::FocusWindowDown => { + self.niri.layout.focus_down(); + } + Action::FocusWindowUp => { + self.niri.layout.focus_up(); + } + Action::MoveWindowToWorkspaceDown => { + self.niri.layout.move_to_workspace_down(); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::MoveWindowToWorkspaceUp => { + self.niri.layout.move_to_workspace_up(); + // 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); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::FocusWorkspaceDown => { + self.niri.layout.switch_workspace_down(); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::FocusWorkspaceUp => { + self.niri.layout.switch_workspace_up(); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::FocusWorkspace(idx) => { + let idx = idx.saturating_sub(1) as usize; + self.niri.layout.switch_workspace(idx); + // 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(); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::ExpelWindowFromColumn => { + self.niri.layout.expel_from_column(); + // 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); + self.move_cursor_to_output(&output); + } + } + Action::FocusMonitorRight => { + if let Some(output) = self.niri.output_right() { + self.niri.layout.focus_output(&output); + self.move_cursor_to_output(&output); + } + } + Action::FocusMonitorDown => { + if let Some(output) = self.niri.output_down() { + self.niri.layout.focus_output(&output); + self.move_cursor_to_output(&output); + } + } + Action::FocusMonitorUp => { + if let Some(output) = self.niri.output_up() { + self.niri.layout.focus_output(&output); + self.move_cursor_to_output(&output); + } + } + Action::MoveWindowToMonitorLeft => { + if let Some(output) = self.niri.output_left() { + self.niri.layout.move_to_output(&output); + self.move_cursor_to_output(&output); + } + } + Action::MoveWindowToMonitorRight => { + if let Some(output) = self.niri.output_right() { + self.niri.layout.move_to_output(&output); + self.move_cursor_to_output(&output); + } + } + Action::MoveWindowToMonitorDown => { + if let Some(output) = self.niri.output_down() { + self.niri.layout.move_to_output(&output); + self.move_cursor_to_output(&output); + } + } + Action::MoveWindowToMonitorUp => { + if let Some(output) = self.niri.output_up() { + self.niri.layout.move_to_output(&output); + 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); + } + } + } - let serial = SERIAL_COUNTER.next_serial(); + 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 pointer = self.niri.seat.get_pointer().unwrap(); + 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(); + + if self + .niri + .global_space + .output_under(new_pos) + .next() + .is_none() + { + // We ended up outside the outputs and need to clip the movement. + if let Some(output) = self.niri.global_space.output_under(pos).next() { + // The pointer was previously on some output. Clip the movement against its + // boundaries. + let geom = self.niri.global_space.output_geometry(output).unwrap(); + new_pos.x = new_pos + .x + .clamp(geom.loc.x as f64, (geom.loc.x + geom.size.w - 1) as f64); + new_pos.y = new_pos + .y + .clamp(geom.loc.y as f64, (geom.loc.y + geom.size.h - 1) as f64); + } else { + // The pointer was not on any output in the first place. Find one for it. + // Let's do the simple thing and just put it on the first output. + let output = self.niri.global_space.outputs().next().unwrap(); + let geom = self.niri.global_space.output_geometry(output).unwrap(); + new_pos = center(geom).to_f64(); + } + } - let pos = pointer.current_location(); + if let Some(output) = self.niri.screenshot_ui.selection_output() { + let geom = self.niri.global_space.output_geometry(output).unwrap(); + let mut point = new_pos; + point.x = point + .x + .clamp(geom.loc.x as f64, (geom.loc.x + geom.size.w - 1) as f64); + point.y = point + .y + .clamp(geom.loc.y as f64, (geom.loc.y + geom.size.h - 1) as f64); + let point = (point - geom.loc.to_f64()) + .to_physical(output.current_scale().fractional_scale()) + .to_i32_round(); + self.niri.screenshot_ui.pointer_motion(point); + } - // We have an output, so we can compute the new location and focus. - let mut new_pos = pos + event.delta(); + let under = self.niri.surface_under_and_global_space(new_pos); + self.niri.pointer_focus = under.clone(); + let under = under.map(|u| u.surface); + + pointer.motion( + self, + under.clone(), + &MotionEvent { + location: new_pos, + serial, + time: event.time_msec(), + }, + ); + + pointer.relative_motion( + self, + under, + &RelativeMotionEvent { + delta: event.delta(), + delta_unaccel: event.delta_unaccel(), + utime: event.time(), + }, + ); - if self - .niri - .global_space - .output_under(new_pos) - .next() - .is_none() - { - // We ended up outside the outputs and need to clip the movement. - if let Some(output) = self.niri.global_space.output_under(pos).next() { - // The pointer was previously on some output. Clip the movement against its - // boundaries. - let geom = self.niri.global_space.output_geometry(output).unwrap(); - new_pos.x = new_pos - .x - .clamp(geom.loc.x as f64, (geom.loc.x + geom.size.w - 1) as f64); - new_pos.y = new_pos - .y - .clamp(geom.loc.y as f64, (geom.loc.y + geom.size.h - 1) as f64); - } else { - // The pointer was not on any output in the first place. Find one for it. - // Let's do the simple thing and just put it on the first output. - let output = self.niri.global_space.outputs().next().unwrap(); - let geom = self.niri.global_space.output_geometry(output).unwrap(); - new_pos = center(geom).to_f64(); - } - } + pointer.frame(self); - if let Some(output) = self.niri.screenshot_ui.selection_output() { - let geom = self.niri.global_space.output_geometry(output).unwrap(); - let mut point = new_pos; - point.x = point - .x - .clamp(geom.loc.x as f64, (geom.loc.x + geom.size.w - 1) as f64); - point.y = point - .y - .clamp(geom.loc.y as f64, (geom.loc.y + geom.size.h - 1) as f64); - let point = (point - geom.loc.to_f64()) - .to_physical(output.current_scale().fractional_scale()) - .to_i32_round(); - self.niri.screenshot_ui.pointer_motion(point); - } + // We moved the regular pointer, so show it now. + self.niri.tablet_cursor_location = None; - let under = self.niri.surface_under_and_global_space(new_pos); - self.niri.pointer_focus = under.clone(); - let under = under.map(|u| u.surface); + // Redraw to update the cursor position. + // FIXME: redraw only outputs overlapping the cursor. + self.niri.queue_redraw_all(); + } - pointer.motion( - self, - under.clone(), - &MotionEvent { - location: new_pos, - serial, - time: event.time_msec(), - }, - ); + fn on_pointer_motion_absolute<I: InputBackend>( + |
