-
Notifications
You must be signed in to change notification settings - Fork 891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wayland: Add support for PinchGesture and RotationGesture #3656
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -281,7 +281,7 @@ pub enum WindowEvent { | |||||
/// | ||||||
/// ## Platform-specific | ||||||
/// | ||||||
/// - Only available on **macOS** and **iOS**. | ||||||
/// - Only available on **macOS**, **iOS** and **Wayland**. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// - On iOS, not recognized by default. It must be enabled when needed. | ||||||
PinchGesture { | ||||||
device_id: DeviceId, | ||||||
|
@@ -297,7 +297,7 @@ pub enum WindowEvent { | |||||
/// | ||||||
/// ## Platform-specific | ||||||
/// | ||||||
/// - Only available on **iOS**. | ||||||
/// - Only available on **iOS** and **Wayland**. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// - On iOS, not recognized by default. It must be enabled when needed. | ||||||
PanGesture { | ||||||
device_id: DeviceId, | ||||||
|
@@ -333,7 +333,7 @@ pub enum WindowEvent { | |||||
/// | ||||||
/// ## Platform-specific | ||||||
/// | ||||||
/// - Only available on **macOS** and **iOS**. | ||||||
/// - Only available on **macOS**, **iOS** and **Wayland**. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// - On iOS, not recognized by default. It must be enabled when needed. | ||||||
RotationGesture { | ||||||
device_id: DeviceId, | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,8 @@ use sctk::reexports::protocols::wp::pointer_constraints::zv1::client::zwp_locked | |
use sctk::reexports::protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::WpCursorShapeDeviceV1; | ||
use sctk::reexports::protocols::wp::cursor_shape::v1::client::wp_cursor_shape_manager_v1::WpCursorShapeManagerV1; | ||
use sctk::reexports::protocols::wp::pointer_constraints::zv1::client::zwp_pointer_constraints_v1::{Lifetime, ZwpPointerConstraintsV1}; | ||
use sctk::reexports::protocols::wp::pointer_gestures::zv1::client::zwp_pointer_gestures_v1::ZwpPointerGesturesV1; | ||
use sctk::reexports::protocols::wp::pointer_gestures::zv1::client::zwp_pointer_gesture_pinch_v1::{ZwpPointerGesturePinchV1, Event}; | ||
use sctk::reexports::client::globals::{BindError, GlobalList}; | ||
use sctk::reexports::csd_frame::FrameClick; | ||
|
||
|
@@ -467,9 +469,107 @@ impl Dispatch<WpCursorShapeManagerV1, GlobalData, WinitState> for SeatState { | |
} | ||
} | ||
|
||
pub struct PointerGesturesState { | ||
pointer_gestures: ZwpPointerGesturesV1, | ||
} | ||
|
||
impl PointerGesturesState { | ||
pub fn new( | ||
globals: &GlobalList, | ||
queue_handle: &QueueHandle<WinitState>, | ||
) -> Result<Self, BindError> { | ||
let pointer_gestures = globals.bind(queue_handle, 1..=1, GlobalData)?; | ||
Ok(Self { pointer_gestures }) | ||
} | ||
} | ||
|
||
impl Deref for PointerGesturesState { | ||
type Target = ZwpPointerGesturesV1; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.pointer_gestures | ||
} | ||
} | ||
|
||
impl Dispatch<ZwpPointerGesturesV1, GlobalData, WinitState> for PointerGesturesState { | ||
fn event( | ||
_state: &mut WinitState, | ||
_proxy: &ZwpPointerGesturesV1, | ||
_event: <ZwpPointerGesturesV1 as wayland_client::Proxy>::Event, | ||
_data: &GlobalData, | ||
_conn: &Connection, | ||
_qhandle: &QueueHandle<WinitState>, | ||
) { | ||
unreachable!("zwp_pointer_gestures_v1 has no events") | ||
} | ||
} | ||
|
||
impl Dispatch<ZwpPointerGesturePinchV1, GlobalData, WinitState> for PointerGesturesState { | ||
fn event( | ||
state: &mut WinitState, | ||
_proxy: &ZwpPointerGesturePinchV1, | ||
event: <ZwpPointerGesturePinchV1 as wayland_client::Proxy>::Event, | ||
_data: &GlobalData, | ||
_conn: &Connection, | ||
_qhandle: &QueueHandle<WinitState>, | ||
) { | ||
let device_id = crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(DeviceId)); | ||
let (phase, pan_delta, scale_delta, rotation_delta) = match event { | ||
Event::Begin { time: _, serial: _, surface, fingers } => { | ||
if fingers != 2 { | ||
// We only support two fingers for now. | ||
return; | ||
} | ||
// The parent surface. | ||
let parent_surface = match surface.data::<SurfaceData>() { | ||
Some(data) => data.parent_surface().unwrap_or(&surface), | ||
None => return, | ||
}; | ||
|
||
let pan_delta = PhysicalPosition::new(0., 0.); | ||
state.window_id = wayland::make_wid(parent_surface); | ||
state.previous_scale = 1.; | ||
|
||
(TouchPhase::Started, pan_delta, 0., 0.) | ||
}, | ||
Event::Update { time: _, dx, dy, scale, rotation } => { | ||
let pan_delta = PhysicalPosition::new(dx as f32, dy as f32); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's in |
||
let scale_delta = scale - state.previous_scale; | ||
state.previous_scale = scale; | ||
(TouchPhase::Moved, pan_delta, scale_delta, -rotation as f32) | ||
}, | ||
Event::End { time: _, serial: _, cancelled } => { | ||
let pan_delta = PhysicalPosition::new(0., 0.); | ||
state.previous_scale = 1.; | ||
( | ||
if cancelled == 0 { TouchPhase::Ended } else { TouchPhase::Cancelled }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Define it on a separate line, so it'll end up more compact. |
||
pan_delta, | ||
0., | ||
0., | ||
) | ||
}, | ||
_ => unreachable!("Unknown event {event:?}"), | ||
}; | ||
state.events_sink.push_window_event( | ||
WindowEvent::PanGesture { device_id, delta: pan_delta, phase }, | ||
state.window_id, | ||
); | ||
Comment on lines
+553
to
+556
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't @madsmtm do you know about it? Also, it's strange that we don't have amount of fingers in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The terminology is probably different elsewhere, but I think a pan gesture (docs) is similar, but distinct from a swipe gesture (docs); the pan is more general (e.g. moving a map around), a swipe is usually short and only in one direction (e.g. dismissing a pop-up). It would make sense to have the number of fingers in the event. |
||
state.events_sink.push_window_event( | ||
WindowEvent::PinchGesture { device_id, delta: scale_delta, phase }, | ||
state.window_id, | ||
); | ||
state.events_sink.push_window_event( | ||
WindowEvent::RotationGesture { device_id, delta: rotation_delta, phase }, | ||
state.window_id, | ||
); | ||
Comment on lines
+557
to
+564
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should only send updates if there was a change compared to previous state, so if there was not pinch, but just rotation, only rotation should be send. |
||
} | ||
} | ||
|
||
delegate_dispatch!(WinitState: [ WlPointer: WinitPointerData] => SeatState); | ||
delegate_dispatch!(WinitState: [ WpCursorShapeManagerV1: GlobalData] => SeatState); | ||
delegate_dispatch!(WinitState: [ WpCursorShapeDeviceV1: GlobalData] => SeatState); | ||
delegate_dispatch!(WinitState: [ZwpPointerConstraintsV1: GlobalData] => PointerConstraintsState); | ||
delegate_dispatch!(WinitState: [ZwpLockedPointerV1: GlobalData] => PointerConstraintsState); | ||
delegate_dispatch!(WinitState: [ZwpConfinedPointerV1: GlobalData] => PointerConstraintsState); | ||
delegate_dispatch!(WinitState: [ZwpPointerGesturesV1: GlobalData] => PointerGesturesState); | ||
delegate_dispatch!(WinitState: [ZwpPointerGesturePinchV1: GlobalData] => PointerGesturesState); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,8 +26,8 @@ use sctk::subcompositor::SubcompositorState; | |
use crate::platform_impl::wayland::event_loop::sink::EventSink; | ||
use crate::platform_impl::wayland::output::MonitorHandle; | ||
use crate::platform_impl::wayland::seat::{ | ||
PointerConstraintsState, RelativePointerState, TextInputState, WinitPointerData, | ||
WinitPointerDataExt, WinitSeatState, | ||
PointerConstraintsState, PointerGesturesState, RelativePointerState, TextInputState, | ||
WinitPointerData, WinitPointerDataExt, WinitSeatState, | ||
}; | ||
use crate::platform_impl::wayland::types::kwin_blur::KWinBlurManager; | ||
use crate::platform_impl::wayland::types::wp_fractional_scaling::FractionalScalingManager; | ||
|
@@ -100,6 +100,15 @@ pub struct WinitState { | |
/// Pointer constraints to handle pointer locking and confining. | ||
pub pointer_constraints: Option<Arc<PointerConstraintsState>>, | ||
|
||
/// Pointer gestures to handle swipe, pinch and hold. | ||
pub pointer_gestures: Option<PointerGesturesState>, | ||
|
||
/// XXX: Is this really meant to stay here? | ||
pub window_id: WindowId, | ||
Comment on lines
+106
to
+107
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it should be like with keyboard focus, on user data. |
||
|
||
/// XXX: Is this really meant to stay here? | ||
pub previous_scale: f64, | ||
Comment on lines
+109
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, should be on user data as well. |
||
|
||
/// Viewporter state on the given window. | ||
pub viewporter_state: Option<ViewporterState>, | ||
|
||
|
@@ -185,8 +194,12 @@ impl WinitState { | |
pointer_constraints: PointerConstraintsState::new(globals, queue_handle) | ||
.map(Arc::new) | ||
.ok(), | ||
pointer_gestures: PointerGesturesState::new(globals, queue_handle).ok(), | ||
pointer_surfaces: Default::default(), | ||
|
||
window_id: WindowId(0), | ||
previous_scale: 1., | ||
|
||
monitors: Arc::new(Mutex::new(monitors)), | ||
events_sink: EventSink::new(), | ||
loop_handle, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.grammarbook.com/blog/commas/oxford-comma/