Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions anvil/src/shell/xdg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ impl<BackendData: Backend> XdgShellHandler for AnvilState<BackendData> {
}
pointer.set_grab(self, PopupPointerGrab::new(&grab), serial, Focus::Keep);
}
// TODO touch grab
}
}
}
Expand Down
155 changes: 154 additions & 1 deletion src/desktop/wayland/popup/grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
use wayland_server::{protocol::wl_surface::WlSurface, Resource};

use crate::{
backend::input::{ButtonState, KeyState, Keycode},
backend::input::{ButtonState, KeyState, Keycode, TouchSlot},
input::{
keyboard::{
GrabStartData as KeyboardGrabStartData, KeyboardGrab, KeyboardHandle, KeyboardInnerHandle,
Expand All @@ -18,6 +18,7 @@ use crate::{
GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab,
PointerInnerHandle, RelativeMotionEvent,
},
touch::{self, DownEvent, OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent},
SeatHandler,
},
utils::{DeadResource, IsAlive, Logical, Point, Serial, SERIAL_COUNTER},
Expand Down Expand Up @@ -227,6 +228,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
root: <D as SeatHandler>::KeyboardFocus,
serial: Serial,
Expand All @@ -235,13 +237,15 @@ where
keyboard_handle: Option<KeyboardHandle<D>>,
keyboard_grab_start_data: KeyboardGrabStartData<D>,
pointer_grab_start_data: PointerGrabStartData<D>,
touch_grab_start_data: touch::GrabStartData<D>,
}

impl<D> fmt::Debug for PopupGrab<D>
where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PopupGrab")
Expand All @@ -251,6 +255,7 @@ where
.field("keyboard_handle", &self.keyboard_handle)
.field("keyboard_grab_start_data", &self.keyboard_grab_start_data)
.field("pointer_grab_start_data", &self.pointer_grab_start_data)
.field("touch_grab_start_data", &self.touch_grab_start_data)
.finish()
}
}
Expand All @@ -260,6 +265,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
fn clone(&self) -> Self {
PopupGrab {
Expand All @@ -270,6 +276,7 @@ where
keyboard_handle: self.keyboard_handle.clone(),
keyboard_grab_start_data: self.keyboard_grab_start_data.clone(),
pointer_grab_start_data: self.pointer_grab_start_data.clone(),
touch_grab_start_data: self.touch_grab_start_data.clone(),
}
}
}
Expand All @@ -279,6 +286,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus + From<PopupKind>,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
pub(super) fn new(
toplevel_popups: PopupGrabInner,
Expand All @@ -304,7 +312,12 @@ where
// We set the focus to root as this will make
// sure the grab will stay alive until the
// toplevel is destroyed or the grab is unset
focus: Some((root.clone().into(), (0f64, 0f64).into())),
location: (0f64, 0f64).into(),
},
touch_grab_start_data: touch::GrabStartData {
focus: Some((root.into(), (0f64, 0f64).into())),
slot: TouchSlot::from(None),
location: (0f64, 0f64).into(),
},
}
Expand Down Expand Up @@ -377,6 +390,15 @@ where
&self.pointer_grab_start_data
}

/// Convenience method for getting a [`touch::GrabStartData`] for this grab.
///
/// The focus of the [`touch::GrabStartData`] will always be the root
/// of the popup grab, e.g. the surface of the toplevel, to make sure
/// the grab is not automatically unset.
pub fn touch_grab_start_data(&self) -> &touch::GrabStartData<D> {
&self.touch_grab_start_data
}

fn unset_keyboard_grab(&self, data: &mut D, serial: Serial) {
if let Some(keyboard) = self.keyboard_handle.as_ref() {
if keyboard.is_grabbed()
Expand All @@ -401,6 +423,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
popup_grab: PopupGrab<D>,
}
Expand All @@ -410,6 +433,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PopupKeyboardGrab")
Expand All @@ -423,6 +447,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
/// Create a [`PopupKeyboardGrab`] for the provided [`PopupGrab`]
pub fn new(popup_grab: &PopupGrab<D>) -> Self {
Expand All @@ -437,6 +462,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus + From<PopupKind>,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
fn input(
&mut self,
Expand Down Expand Up @@ -509,6 +535,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
popup_grab: PopupGrab<D>,
}
Expand All @@ -518,6 +545,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PopupPointerGrab")
Expand All @@ -531,6 +559,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
/// Create a [`PopupPointerGrab`] for the provided [`PopupGrab`]
pub fn new(popup_grab: &PopupGrab<D>) -> Self {
Expand All @@ -545,6 +574,7 @@ where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus + From<PopupKind>,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
fn motion(
&mut self,
Expand Down Expand Up @@ -708,3 +738,126 @@ where
self.popup_grab.unset_keyboard_grab(data, serial);
}
}

/// Default implementation of a [`TouchGrab`] for [`PopupGrab`]
///
/// The [`PopupTouchGrab`] will make sure that touch events
/// stays on the same client as the grabbed popup (similar to an
/// "owner-events" grab in X11 parlance). If an input event happens
/// outside of the grabbed [`WlSurface`] the popup will be dismissed
/// and the grab ends. In case of a nested grab all parent grabs will
/// also be dismissed.
pub struct PopupTouchGrab<D>
where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
popup_grab: PopupGrab<D>,
}

impl<D> fmt::Debug for PopupTouchGrab<D>
where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PopupTouchGrab")
.field("popup_grab", &self.popup_grab)
.finish()
}
}

impl<D> PopupTouchGrab<D>
where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus + From<PopupKind>,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
{
/// Create a [`PopupTouchGrab`] for the provided [`PopupGrab`]
pub fn new(popup_grab: &PopupGrab<D>) -> Self {
PopupTouchGrab {
popup_grab: popup_grab.clone(),
}
}
}

impl<D> TouchGrab<D> for PopupTouchGrab<D>
where
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus + From<PopupKind>,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
{
fn down(
&mut self,
data: &mut D,
handle: &mut TouchInnerHandle<'_, D>,
focus: Option<(<D as SeatHandler>::TouchFocus, Point<f64, Logical>)>,
event: &DownEvent,
seq: Serial,
) {
if focus
.as_ref()
.and_then(|f1| {
self.popup_grab
.current_grab()
.as_ref()
.and_then(|f2| f2.wl_surface())
.map(|s| f1.0.same_client_as(&s.id()))
})
.unwrap_or(false)
{
handle.down(data, focus, event, seq);
} else {
handle.down(data, None, event, seq);
}
}

fn up(&mut self, data: &mut D, handle: &mut TouchInnerHandle<'_, D>, event: &UpEvent, seq: Serial) {
handle.up(data, event, seq)
}

fn motion(
&mut self,
data: &mut D,
handle: &mut TouchInnerHandle<'_, D>,
focus: Option<(<D as SeatHandler>::TouchFocus, Point<f64, Logical>)>,
event: &touch::MotionEvent,
seq: Serial,
) {
handle.motion(data, focus, event, seq)
}

fn frame(&mut self, data: &mut D, handle: &mut TouchInnerHandle<'_, D>, seq: Serial) {
handle.frame(data, seq)
}

fn cancel(&mut self, data: &mut D, handle: &mut TouchInnerHandle<'_, D>, seq: Serial) {
handle.cancel(data, seq)
}

fn shape(&mut self, data: &mut D, handle: &mut TouchInnerHandle<'_, D>, event: &ShapeEvent, seq: Serial) {
handle.shape(data, event, seq)
}

fn orientation(
&mut self,
data: &mut D,
handle: &mut TouchInnerHandle<'_, D>,
event: &OrientationEvent,
seq: Serial,
) {
handle.orientation(data, event, seq)
}

fn start_data(&self) -> &touch::GrabStartData<D> {
self.popup_grab.touch_grab_start_data()
}

fn unset(&mut self, _data: &mut D) {}
}
1 change: 1 addition & 0 deletions src/desktop/wayland/popup/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ impl PopupManager {
D: SeatHandler + 'static,
<D as SeatHandler>::KeyboardFocus: WaylandFocus + From<PopupKind>,
<D as SeatHandler>::PointerFocus: From<<D as SeatHandler>::KeyboardFocus> + WaylandFocus,
<D as SeatHandler>::TouchFocus: From<<D as SeatHandler>::KeyboardFocus>,
{
let surface = popup.wl_surface();
assert_eq!(
Expand Down
Loading