Skip to content

Commit

Permalink
Implement relative pointer protocol
Browse files Browse the repository at this point in the history
Add helper for the relative pointer protocol, and a way to send relative
pointer events to clients. This also exposes unaccelerated vectors and
microsecond timestamps in pointer events from the libinput backend.

Enables `wlcs` relative pointer test, though what `wlcs` currently
handles seems to be limited at this point.

Adds relative pointer support for Anvil, exposing the global only on the
`udev` backend so clients won't use the protocol but get no events.
  • Loading branch information
ids1024 committed Jan 23, 2023
1 parent ffbc84e commit e271425
Show file tree
Hide file tree
Showing 24 changed files with 571 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ jobs:
gtest_filter: "XdgOutputV1Test*"
flag: output
- job_name: "Pointer input tests"
gtest_filter: "*/SurfacePointerMotionTest*"
gtest_filter: "*/SurfacePointerMotionTest*:RelativePointer*"
flag: pointer-input

name: "WLCS: ${{ matrix.job_name }}"
Expand Down
14 changes: 13 additions & 1 deletion anvil/src/focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub use smithay::{
desktop::{LayerSurface, PopupKind},
input::{
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget},
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget, RelativeMotionEvent},
Seat,
},
reexports::wayland_server::{backend::ObjectId, protocol::wl_surface::WlSurface, Resource},
Expand Down Expand Up @@ -64,6 +64,18 @@ impl<BackendData: Backend> PointerTarget<AnvilState<BackendData>> for FocusTarge
FocusTarget::Popup(p) => PointerTarget::motion(p.wl_surface(), seat, data, event),
}
}
fn relative_motion(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &RelativeMotionEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::relative_motion(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::relative_motion(l.wl_surface(), seat, data, event),
FocusTarget::Popup(p) => PointerTarget::relative_motion(p.wl_surface(), seat, data, event),
}
}
fn button(
&self,
seat: &Seat<AnvilState<BackendData>>,
Expand Down
14 changes: 12 additions & 2 deletions anvil/src/input_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use smithay::{
desktop::{layer_map_for_output, WindowSurfaceType},
input::{
keyboard::{keysyms as xkb, FilterResult, Keysym, ModifiersState},
pointer::{AxisFrame, ButtonEvent, MotionEvent},
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
},
output::Scale,
reexports::wayland_server::{protocol::wl_pointer, DisplayHandle},
Expand Down Expand Up @@ -646,13 +646,23 @@ impl AnvilState<UdevData> {
if let Some(ptr) = self.seat.get_pointer() {
ptr.motion(
self,
under,
under.clone(),
&MotionEvent {
location: self.pointer_location,
serial,
time: evt.time(),
},
);

ptr.relative_motion(
self,
under,
&RelativeMotionEvent {
delta: evt.delta(),
delta_unaccel: evt.delta_unaccel(),
utime: evt.utime(),
},
)
}
}

Expand Down
17 changes: 16 additions & 1 deletion anvil/src/shell/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use smithay::{
desktop::{space::SpaceElement, utils::OutputPresentationFeedback, Window, WindowSurfaceType},
input::{
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget},
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget, RelativeMotionEvent},
Seat,
},
output::Output,
Expand Down Expand Up @@ -227,6 +227,21 @@ impl<Backend: crate::state::Backend> PointerTarget<AnvilState<Backend>> for Wind
};
}
}
fn relative_motion(
&self,
seat: &Seat<AnvilState<Backend>>,
data: &mut AnvilState<Backend>,
event: &RelativeMotionEvent,
) {
let state = self.decoration_state();
if !state.is_ssd || state.ptr_entered_window {
match self {
WindowElement::Wayland(w) => PointerTarget::relative_motion(w, seat, data, event),
#[cfg(feature = "xwayland")]
WindowElement::X11(w) => PointerTarget::relative_motion(w, seat, data, event),
}
}
}
fn button(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, event: &ButtonEvent) {
let mut state = self.decoration_state();
if state.is_ssd {
Expand Down
22 changes: 21 additions & 1 deletion anvil/src/shell/grabs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use smithay::{
desktop::space::SpaceElement,
input::pointer::{
AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab,
PointerInnerHandle,
PointerInnerHandle, RelativeMotionEvent,
},
reexports::wayland_protocols::xdg::shell::server::xdg_toplevel,
utils::{IsAlive, Logical, Point, Serial, Size},
Expand Down Expand Up @@ -43,6 +43,16 @@ impl<BackendData: Backend> PointerGrab<AnvilState<BackendData>> for MoveSurfaceG
.map_element(self.window.clone(), new_location.to_i32_round(), true);
}

fn relative_motion(
&mut self,
data: &mut AnvilState<BackendData>,
handle: &mut PointerInnerHandle<'_, AnvilState<BackendData>>,
focus: Option<(FocusTarget, Point<i32, Logical>)>,
event: &RelativeMotionEvent,
) {
handle.relative_motion(data, focus, event);
}

fn button(
&mut self,
data: &mut AnvilState<BackendData>,
Expand Down Expand Up @@ -241,6 +251,16 @@ impl<BackendData: Backend> PointerGrab<AnvilState<BackendData>> for ResizeSurfac
}
}

fn relative_motion(
&mut self,
data: &mut AnvilState<BackendData>,
handle: &mut PointerInnerHandle<'_, AnvilState<BackendData>>,
focus: Option<(FocusTarget, Point<i32, Logical>)>,
event: &RelativeMotionEvent,
) {
handle.relative_motion(data, focus, event);
}

fn button(
&mut self,
data: &mut AnvilState<BackendData>,
Expand Down
14 changes: 11 additions & 3 deletions anvil/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use smithay::{
backend::renderer::element::{default_primary_scanout_output_compare, RenderElementStates},
delegate_compositor, delegate_data_device, delegate_fractional_scale, delegate_input_method_manager,
delegate_keyboard_shortcuts_inhibit, delegate_layer_shell, delegate_output, delegate_presentation,
delegate_primary_selection, delegate_seat, delegate_shm, delegate_tablet_manager,
delegate_text_input_manager, delegate_viewporter, delegate_virtual_keyboard_manager,
delegate_xdg_activation, delegate_xdg_decoration, delegate_xdg_shell,
delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_shm,
delegate_tablet_manager, delegate_text_input_manager, delegate_viewporter,
delegate_virtual_keyboard_manager, delegate_xdg_activation, delegate_xdg_decoration, delegate_xdg_shell,
desktop::{
utils::{
surface_presentation_feedback_flags_from_states, surface_primary_scanout_output,
Expand Down Expand Up @@ -46,6 +46,7 @@ use smithay::{
output::OutputManagerState,
presentation::PresentationState,
primary_selection::{set_primary_focus, PrimarySelectionHandler, PrimarySelectionState},
relative_pointer::RelativePointerManagerState,
seat::WaylandFocus,
shell::{
wlr_layer::WlrLayerShellState,
Expand Down Expand Up @@ -224,6 +225,8 @@ delegate_keyboard_shortcuts_inhibit!(@<BackendData: Backend + 'static> AnvilStat

delegate_virtual_keyboard_manager!(@<BackendData: Backend + 'static> AnvilState<BackendData>);

delegate_relative_pointer!(@<BackendData: Backend + 'static> AnvilState<BackendData>);

delegate_viewporter!(@<BackendData: Backend + 'static> AnvilState<BackendData>);

impl<BackendData: Backend> XdgActivationHandler for AnvilState<BackendData> {
Expand Down Expand Up @@ -449,6 +452,10 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
TextInputManagerState::new::<Self>(&dh);
InputMethodManagerState::new::<Self>(&dh);
VirtualKeyboardManagerState::new::<Self, _>(&dh, |_client| true);
// Expose global only if backend supports relative motion events
if BackendData::HAS_RELATIVE_MOTION {
RelativePointerManagerState::new::<Self>(&dh);
}

// init input
let seat_name = backend_data.seat_name();
Expand Down Expand Up @@ -634,6 +641,7 @@ pub fn take_presentation_feedback(
}

pub trait Backend {
const HAS_RELATIVE_MOTION: bool = false;
fn seat_name(&self) -> String;
fn reset_buffers(&mut self, output: &Output);
fn early_import(&mut self, surface: &WlSurface);
Expand Down
2 changes: 2 additions & 0 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ impl DmabufHandler for AnvilState<UdevData> {
delegate_dmabuf!(AnvilState<UdevData>);

impl Backend for UdevData {
const HAS_RELATIVE_MOTION: bool = true;

fn seat_name(&self) -> String {
self.session.seat()
}
Expand Down
12 changes: 11 additions & 1 deletion smallvil/src/grabs/move_grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use smithay::{
desktop::Window,
input::pointer::{
AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab,
PointerInnerHandle,
PointerInnerHandle, RelativeMotionEvent,
},
reexports::wayland_server::protocol::wl_surface::WlSurface,
utils::{Logical, Point},
Expand Down Expand Up @@ -32,6 +32,16 @@ impl PointerGrab<Smallvil> for MoveSurfaceGrab {
.map_element(self.window.clone(), new_location.to_i32_round(), true);
}

fn relative_motion(
&mut self,
data: &mut Smallvil,
handle: &mut PointerInnerHandle<'_, Smallvil>,
focus: Option<(WlSurface, Point<i32, Logical>)>,
event: &RelativeMotionEvent,
) {
handle.relative_motion(data, focus, event);
}

fn button(
&mut self,
data: &mut Smallvil,
Expand Down
12 changes: 11 additions & 1 deletion smallvil/src/grabs/resize_grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use smithay::{
desktop::{Space, Window},
input::pointer::{
AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab,
PointerInnerHandle,
PointerInnerHandle, RelativeMotionEvent,
},
reexports::{
wayland_protocols::xdg::shell::server::xdg_toplevel, wayland_server::protocol::wl_surface::WlSurface,
Expand Down Expand Up @@ -125,6 +125,16 @@ impl PointerGrab<Smallvil> for ResizeSurfaceGrab {
xdg.send_configure();
}

fn relative_motion(
&mut self,
data: &mut Smallvil,
handle: &mut PointerInnerHandle<'_, Smallvil>,
focus: Option<(WlSurface, Point<i32, Logical>)>,
event: &RelativeMotionEvent,
) {
handle.relative_motion(data, focus, event);
}

fn button(
&mut self,
data: &mut Smallvil,
Expand Down
29 changes: 29 additions & 0 deletions src/backend/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,27 @@ pub trait PointerMotionEvent<B: InputBackend>: Event<B> {
(self.delta_x(), self.delta_y()).into()
}

/// Unaccelerated delta between the last and new pointer device position
fn delta_unaccel(&self) -> Point<f64, Logical> {
(self.delta_x_unaccel(), self.delta_y_unaccel()).into()
}

/// Delta on the x axis between the last and new pointer device position interpreted as pixel movement
fn delta_x(&self) -> f64;

/// Delta on the y axis between the last and new pointer device position interpreted as pixel movement
fn delta_y(&self) -> f64;

/// Unaccelerated delta on the x axis between the last and new pointer device position
fn delta_x_unaccel(&self) -> f64;

/// Unaccelerated delta on the y axis between the last and new pointer device position
fn delta_y_unaccel(&self) -> f64;

/// Returns an upward counting variable useful for event ordering, in microseconds.
///
/// Makes no guarantees about actual time passed between events.
fn utime(&self) -> u64;
}

impl<B: InputBackend> PointerMotionEvent<B> for UnusedEvent {
Expand All @@ -273,6 +290,18 @@ impl<B: InputBackend> PointerMotionEvent<B> for UnusedEvent {
fn delta_y(&self) -> f64 {
match *self {}
}

fn delta_x_unaccel(&self) -> f64 {
match *self {}
}

fn delta_y_unaccel(&self) -> f64 {
match *self {}
}

fn utime(&self) -> u64 {
match *self {}
}
}

/// Trait for pointer events generated by absolute device positioning.
Expand Down
13 changes: 13 additions & 0 deletions src/backend/libinput/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,22 @@ impl backend::PointerMotionEvent<LibinputInputBackend> for event::pointer::Point
fn delta_x(&self) -> f64 {
self.dx()
}

fn delta_y(&self) -> f64 {
self.dy()
}

fn delta_x_unaccel(&self) -> f64 {
self.dx_unaccelerated()
}

fn delta_y_unaccel(&self) -> f64 {
self.dy_unaccelerated()
}

fn utime(&self) -> u64 {
event::pointer::PointerEventTrait::time_usec(self)
}
}

impl backend::Event<LibinputInputBackend> for event::pointer::PointerMotionAbsoluteEvent {
Expand Down
7 changes: 6 additions & 1 deletion src/desktop/wayland/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
desktop::{utils::*, PopupManager},
input::{
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget},
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget, RelativeMotionEvent},
Seat, SeatHandler,
},
output::{Output, WeakOutput},
Expand Down Expand Up @@ -669,6 +669,11 @@ impl<D: SeatHandler + 'static> PointerTarget<D> for LayerSurface {
fn motion(&self, seat: &Seat<D>, data: &mut D, event: &MotionEvent) {
PointerTarget::<D>::enter(self, seat, data, event)
}
fn relative_motion(&self, seat: &Seat<D>, data: &mut D, event: &RelativeMotionEvent) {
if let Some(surface) = self.0.focused_surface.lock().unwrap().as_ref() {
PointerTarget::<D>::relative_motion(surface, seat, data, event)
}
}
fn button(&self, seat: &Seat<D>, data: &mut D, event: &ButtonEvent) {
if let Some(surface) = self.0.focused_surface.lock().unwrap().as_ref() {
PointerTarget::<D>::button(surface, seat, data, event)
Expand Down
12 changes: 11 additions & 1 deletion src/desktop/wayland/popup/grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
},
pointer::{
AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab,
PointerInnerHandle,
PointerInnerHandle, RelativeMotionEvent,
},
SeatHandler,
},
Expand Down Expand Up @@ -573,6 +573,16 @@ where
}
}

fn relative_motion(
&mut self,
data: &mut D,
handle: &mut PointerInnerHandle<'_, D>,
focus: Option<(<D as SeatHandler>::PointerFocus, Point<i32, Logical>)>,
event: &RelativeMotionEvent,
) {
handle.relative_motion(data, focus, event);
}

fn button(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>, event: &ButtonEvent) {
let serial = event.serial;
let time = event.time;
Expand Down
7 changes: 6 additions & 1 deletion src/desktop/wayland/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
desktop::{space::RenderZindex, utils::*, PopupManager},
input::{
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget},
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget, RelativeMotionEvent},
Seat, SeatHandler,
},
output::Output,
Expand Down Expand Up @@ -276,6 +276,11 @@ impl<D: SeatHandler + 'static> PointerTarget<D> for Window {
fn motion(&self, seat: &Seat<D>, data: &mut D, event: &MotionEvent) {
PointerTarget::<D>::enter(self, seat, data, event)
}
fn relative_motion(&self, seat: &Seat<D>, data: &mut D, event: &RelativeMotionEvent) {
if let Some(surface) = self.0.focused_surface.lock().unwrap().as_ref() {
PointerTarget::<D>::relative_motion(surface, seat, data, event)
}
}
fn button(&self, seat: &Seat<D>, data: &mut D, event: &ButtonEvent) {
if let Some(surface) = self.0.focused_surface.lock().unwrap().as_ref() {
PointerTarget::<D>::button(surface, seat, data, event)
Expand Down
Loading

0 comments on commit e271425

Please sign in to comment.