Skip to content
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 support for set_cursor_grab and set_cursor_visible #1180

Merged
merged 23 commits into from
Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bbf56c5
Fixed relative_pointer not being set up when the "zwp_relative_pointe…
andersrein Sep 21, 2019
22cf11d
Ran cargo fmt
andersrein Sep 21, 2019
590957b
Updated changelog
andersrein Sep 21, 2019
d032d06
Added wayland support for set_grab_cursor and set_cursor_visible
andersrein Sep 21, 2019
7b87f91
Updated changelog
andersrein Sep 21, 2019
84befcc
Ran cargo fmt
andersrein Sep 21, 2019
c05da14
Fixed set_cursor_visible and set_cursor_grab so they can be called fr…
andersrein Sep 21, 2019
8259633
Ran cargo_fmt
andersrein Sep 21, 2019
5bda5a9
Improved CHANGELOG
andersrein Sep 21, 2019
4725dea
Added workaround so that when cursor is hidden it takes effect before…
andersrein Sep 21, 2019
fc4ae81
Switched to using Rc<RefCell> instead of Arc<Mutex> since all accesse…
andersrein Sep 22, 2019
fc46206
Forgot to run cargo fmt
andersrein Sep 22, 2019
529815a
Switched to using Rc and RefCell instead of Arc and Mutex where appli…
andersrein Sep 22, 2019
30d64d9
Improved comments and documentation relating to changing a hidden cur…
andersrein Sep 22, 2019
d36f0d0
Wayland: Fixed cursor not appearing immendiately when setting the cur…
andersrein Sep 22, 2019
54ed4c9
Forgot to run cargo fmt
andersrein Sep 22, 2019
065a247
Switched to only storing the pointers in CursorManager as AutoPointer.
andersrein Sep 22, 2019
7f4ef69
Fixed typo and removed println
andersrein Sep 22, 2019
24d9536
Merged from master
andersrein Sep 23, 2019
3da7a19
Merge branch 'master' into wayland_cursor
andersrein Sep 23, 2019
59d5d76
Merge branch 'master' of https://github.com/rust-windowing/winit
andersrein Sep 23, 2019
143cb4b
Merge branch 'master' into wayland_cursor
andersrein Sep 23, 2019
961835c
Update CHANGELOG.md
andersrein Oct 1, 2019
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- On Windows, fix hovering the mouse over the active window creating an endless stream of CursorMoved events.
- On X11, prevent stealing input focus when creating a new window.
Only steal input focus when entering fullscreen mode.
- Added support for set_cursor_visible and set_cursor_grab on wayland
andersrein marked this conversation as resolved.
Show resolved Hide resolved

# 0.20.0 Alpha 3 (2019-08-14)

Expand Down
122 changes: 121 additions & 1 deletion src/platform_impl/linux/wayland/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ use std::{
time::Instant,
};

use smithay_client_toolkit::reexports::protocols::unstable::pointer_constraints::v1::client::{
zwp_locked_pointer_v1::ZwpLockedPointerV1, zwp_pointer_constraints_v1::ZwpPointerConstraintsV1,
};
use smithay_client_toolkit::reexports::protocols::unstable::relative_pointer::v1::client::{
zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1,
zwp_relative_pointer_v1::ZwpRelativePointerV1,
};

use smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface;

use crate::{
dpi::{PhysicalPosition, PhysicalSize},
event::ModifiersState,
Expand Down Expand Up @@ -69,6 +74,68 @@ impl<T> WindowEventsSink<T> {
}
}

pub struct CursorManager {
pointer_constraints_proxy: Arc<Mutex<Option<ZwpPointerConstraintsV1>>>,
pointers: Vec<wl_pointer::WlPointer>,
locked_pointers: Vec<ZwpLockedPointerV1>,
cursor_visible: Arc<Mutex<bool>>,
}

impl CursorManager {
fn new(constraints: Arc<Mutex<Option<ZwpPointerConstraintsV1>>>) -> CursorManager {
CursorManager {
pointer_constraints_proxy: constraints,
pointers: Vec::new(),
locked_pointers: Vec::new(),
cursor_visible: Arc::new(Mutex::new(true)),
}
}

fn register_pointer(&mut self, pointer: wl_pointer::WlPointer) {
self.pointers.push(pointer);
}

pub fn set_cursor_visible(&mut self, visible: bool) {
// If we want to hide the cursor do it immediately. There is a known
// limitation that the cursor will not become visible again until it
// enters a new surface
andersrein marked this conversation as resolved.
Show resolved Hide resolved
if !visible {
for pointer in self.pointers.iter() {
pointer.set_cursor(0, None, 0, 0);
}
}
(*self.cursor_visible.lock().unwrap()) = visible;
}

pub fn grab_pointer(&mut self, surface: Option<&WlSurface>) {
for lp in self.locked_pointers.drain(..) {
lp.destroy();
}

if let Some(surface) = surface {
for pointer in self.pointers.iter() {
let locked_pointer = self
.pointer_constraints_proxy
.lock()
.unwrap()
.as_ref()
.and_then(|pointer_constraints| {
super::pointer::implement_locked_pointer(
surface,
pointer,
pointer_constraints,
)
.ok()
});

if let Some(locked_pointer) = locked_pointer {
self.locked_pointers.push(locked_pointer);
}
}
}
}
}

pub struct EventLoop<T: 'static> {
// The loop
inner_loop: ::calloop::EventLoop<()>,
Expand All @@ -79,6 +146,8 @@ pub struct EventLoop<T: 'static> {
// our sink, shared with some handlers, buffering the events
sink: Arc<Mutex<WindowEventsSink<T>>>,
pending_user_events: Rc<RefCell<VecDeque<T>>>,
// Utility for grabbing the cursor and changing visibility
cursor_manager: Arc<Mutex<CursorManager>>,
_user_source: ::calloop::Source<::calloop::channel::Channel<T>>,
user_sender: ::calloop::channel::Sender<T>,
_kbd_source: ::calloop::Source<
Expand Down Expand Up @@ -146,14 +215,20 @@ impl<T: 'static> EventLoop<T> {
})
.unwrap();

let pointer_constraints_proxy = Arc::new(Mutex::new(None));

let mut seat_manager = SeatManager {
sink: sink.clone(),
relative_pointer_manager_proxy: None,
pointer_constraints_proxy: pointer_constraints_proxy.clone(),
store: store.clone(),
seats: seats.clone(),
kbd_sender,
cursor_manager: Arc::new(Mutex::new(CursorManager::new(pointer_constraints_proxy))),
};

let cursor_manager = seat_manager.cursor_manager.clone();

let env = Environment::from_display_with_cb(
&display,
&mut event_queue,
Expand All @@ -172,6 +247,16 @@ impl<T: 'static> EventLoop<T> {
.unwrap(),
)
}
if interface == "zwp_pointer_constraints_v1" {
let pointer_constraints_proxy = registry
.bind(version, id, move |pointer_constraints| {
pointer_constraints.implement_closure(|_, _| (), ())
})
.unwrap();

*seat_manager.pointer_constraints_proxy.lock().unwrap() =
Some(pointer_constraints_proxy);
}
if interface == "wl_seat" {
seat_manager.add_seat(id, version, registry)
}
Expand Down Expand Up @@ -210,6 +295,7 @@ impl<T: 'static> EventLoop<T> {
pending_user_events,
display: display.clone(),
outputs: env.outputs.clone(),
cursor_manager,
_user_source: user_source,
user_sender,
_kbd_source: kbd_source,
Expand Down Expand Up @@ -449,7 +535,17 @@ impl<T> EventLoop<T> {
}
// process pending resize/refresh
window_target.store.lock().unwrap().for_each(
|newsize, size, new_dpi, refresh, frame_refresh, closed, wid, frame| {
|newsize,
size,
new_dpi,
refresh,
frame_refresh,
closed,
cursor_visible,
cursor_grab,
surface,
wid,
frame| {
if let Some(frame) = frame {
if let Some((w, h)) = newsize {
frame.resize(w, h);
Expand Down Expand Up @@ -479,6 +575,20 @@ impl<T> EventLoop<T> {
if closed {
sink.send_window_event(crate::event::WindowEvent::CloseRequested, wid);
}
if let Some(grab) = cursor_grab {
self.cursor_manager.lock().unwrap().grab_pointer(if grab {
Some(surface)
} else {
None
});
}

if let Some(visible) = cursor_visible {
self.cursor_manager
.lock()
.unwrap()
.set_cursor_visible(visible);
}
},
)
}
Expand All @@ -494,6 +604,8 @@ struct SeatManager<T: 'static> {
seats: Arc<Mutex<Vec<(u32, wl_seat::WlSeat)>>>,
kbd_sender: ::calloop::channel::Sender<(crate::event::WindowEvent, super::WindowId)>,
relative_pointer_manager_proxy: Option<ZwpRelativePointerManagerV1>,
pointer_constraints_proxy: Arc<Mutex<Option<ZwpPointerConstraintsV1>>>,
cursor_manager: Arc<Mutex<CursorManager>>,
}

impl<T: 'static> SeatManager<T> {
Expand All @@ -510,6 +622,7 @@ impl<T: 'static> SeatManager<T> {
touch: None,
kbd_sender: self.kbd_sender.clone(),
modifiers_tracker: Arc::new(Mutex::new(ModifiersState::default())),
cursor_manager: self.cursor_manager.clone(),
};
let seat = registry
.bind(min(version, 5), id, move |seat| {
Expand Down Expand Up @@ -541,6 +654,7 @@ struct SeatData<T> {
keyboard: Option<wl_keyboard::WlKeyboard>,
touch: Option<wl_touch::WlTouch>,
modifiers_tracker: Arc<Mutex<ModifiersState>>,
cursor_manager: Arc<Mutex<CursorManager>>,
}

impl<T: 'static> SeatData<T> {
Expand All @@ -555,8 +669,14 @@ impl<T: 'static> SeatData<T> {
self.sink.clone(),
self.store.clone(),
self.modifiers_tracker.clone(),
self.cursor_manager.lock().unwrap().cursor_visible.clone(),
));

self.cursor_manager
.lock()
.unwrap()
.register_pointer(self.pointer.as_ref().unwrap().clone());

self.relative_pointer =
self.relative_pointer_manager_proxy
.as_ref()
Expand Down
22 changes: 22 additions & 0 deletions src/platform_impl/linux/wayland/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ use smithay_client_toolkit::reexports::protocols::unstable::relative_pointer::v1
zwp_relative_pointer_v1::ZwpRelativePointerV1,
};

use smithay_client_toolkit::reexports::protocols::unstable::pointer_constraints::v1::client::{
zwp_locked_pointer_v1::ZwpLockedPointerV1, zwp_pointer_constraints_v1::Lifetime,
zwp_pointer_constraints_v1::ZwpPointerConstraintsV1,
};

use smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface;

pub fn implement_pointer<T: 'static>(
seat: &wl_seat::WlSeat,
sink: Arc<Mutex<WindowEventsSink<T>>>,
store: Arc<Mutex<WindowStore>>,
modifiers_tracker: Arc<Mutex<ModifiersState>>,
cursor_visible: Arc<Mutex<bool>>,
) -> WlPointer {
seat.get_pointer(|pointer| {
let mut mouse_focus = None;
Expand Down Expand Up @@ -62,6 +70,10 @@ pub fn implement_pointer<T: 'static>(
wid,
);
}

if *cursor_visible.lock().unwrap() == false {
pointer.set_cursor(0, None, 0, 0);
}
}
PtrEvent::Leave { surface, .. } => {
mouse_focus = None;
Expand Down Expand Up @@ -241,3 +253,13 @@ pub fn implement_relative_pointer<T: 'static>(
)
})
}

pub fn implement_locked_pointer(
surface: &WlSurface,
pointer: &WlPointer,
constraints: &ZwpPointerConstraintsV1,
) -> Result<ZwpLockedPointerV1, ()> {
constraints.lock_pointer(surface, pointer, None, Lifetime::Persistent.to_raw(), |c| {
andersrein marked this conversation as resolved.
Show resolved Hide resolved
c.implement_closure(|_, _| (), ())
})
}
25 changes: 21 additions & 4 deletions src/platform_impl/linux/wayland/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub struct Window {
need_frame_refresh: Arc<Mutex<bool>>,
need_refresh: Arc<Mutex<bool>>,
fullscreen: Arc<Mutex<bool>>,
cursor_grab_changed: Arc<Mutex<Option<bool>>>,
cursor_visible_changed: Arc<Mutex<Option<bool>>>,
}

impl Window {
Expand Down Expand Up @@ -140,6 +142,8 @@ impl Window {
let need_frame_refresh = Arc::new(Mutex::new(true));
let frame = Arc::new(Mutex::new(frame));
let need_refresh = Arc::new(Mutex::new(true));
let cursor_grab_changed = Arc::new(Mutex::new(None));
let cursor_visible_changed = Arc::new(Mutex::new(None));

evlp.store.lock().unwrap().windows.push(InternalWindow {
closed: false,
Expand All @@ -148,6 +152,8 @@ impl Window {
need_refresh: need_refresh.clone(),
fullscreen: fullscreen.clone(),
need_frame_refresh: need_frame_refresh.clone(),
cursor_grab_changed: cursor_grab_changed.clone(),
cursor_visible_changed: cursor_visible_changed.clone(),
surface: surface.clone(),
kill_switch: kill_switch.clone(),
frame: Arc::downgrade(&frame),
Expand All @@ -166,6 +172,8 @@ impl Window {
need_frame_refresh,
need_refresh,
fullscreen,
cursor_grab_changed,
cursor_visible_changed,
})
}

Expand Down Expand Up @@ -297,13 +305,14 @@ impl Window {
}

#[inline]
pub fn set_cursor_visible(&self, _visible: bool) {
// TODO: This isn't possible on Wayland yet
pub fn set_cursor_visible(&self, visible: bool) {
*self.cursor_visible_changed.lock().unwrap() = Some(visible);
}

#[inline]
pub fn set_cursor_grab(&self, _grab: bool) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
*self.cursor_grab_changed.lock().unwrap() = Some(grab);
Ok(())
}

#[inline]
Expand Down Expand Up @@ -362,6 +371,8 @@ struct InternalWindow {
need_refresh: Arc<Mutex<bool>>,
fullscreen: Arc<Mutex<bool>>,
need_frame_refresh: Arc<Mutex<bool>>,
cursor_grab_changed: Arc<Mutex<Option<bool>>>,
cursor_visible_changed: Arc<Mutex<Option<bool>>>,
closed: bool,
kill_switch: Arc<Mutex<bool>>,
frame: Weak<Mutex<SWindow<ConceptFrame>>>,
Expand Down Expand Up @@ -429,6 +440,9 @@ impl WindowStore {
bool,
bool,
bool,
Option<bool>,
Option<bool>,
&wl_surface::WlSurface,
WindowId,
Option<&mut SWindow<ConceptFrame>>,
),
Expand All @@ -443,6 +457,9 @@ impl WindowStore {
::std::mem::replace(&mut *window.need_refresh.lock().unwrap(), false),
::std::mem::replace(&mut *window.need_frame_refresh.lock().unwrap(), false),
window.closed,
window.cursor_visible_changed.lock().unwrap().take(),
window.cursor_grab_changed.lock().unwrap().take(),
&window.surface,
make_wid(&window.surface),
opt_mutex_lock.as_mut().map(|m| &mut **m),
);
Expand Down