Skip to content

Commit

Permalink
Wayland: Fix panic when calling set_cursor_grab from a different thre…
Browse files Browse the repository at this point in the history
…ad than evlp's one. (#1206)

This commit also start following X11 behavior on cursor icon update when
cursor is invisible.

Fixes regression introdced in 5ced36e
  • Loading branch information
kchibisov authored and Osspial committed Oct 16, 2019
1 parent 34dce80 commit 765225d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 11 deletions.
32 changes: 27 additions & 5 deletions src/platform_impl/linux/wayland/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,11 @@ impl CursorManager {
}

pub fn set_cursor_icon(&mut self, cursor: CursorIcon) {
if self.cursor_visible && cursor != self.current_cursor {
if cursor != self.current_cursor {
self.current_cursor = cursor;

self.set_cursor_icon_impl(cursor);
if self.cursor_visible {
self.set_cursor_icon_impl(cursor);
}
}
}

Expand Down Expand Up @@ -191,7 +192,11 @@ impl CursorManager {
}
}

pub fn grab_pointer(&mut self, surface: Option<&WlSurface>) {
// This function can only be called from a thread on which `pointer_constraints_proxy` event
// queue is located, so calling it directly from a Window doesn't work well, in case
// you've sent your window to another thread, so we need to pass cursor grab updates to
// the event loop and call this function from there.
fn grab_pointer(&mut self, surface: Option<&WlSurface>) {
for locked_pointer in self.locked_pointers.drain(..) {
locked_pointer.destroy();
}
Expand Down Expand Up @@ -230,6 +235,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>>>,
// The cursor manager
cursor_manager: Arc<Mutex<CursorManager>>,
// Utility for grabbing the cursor and changing visibility
_user_source: ::calloop::Source<::calloop::channel::Channel<T>>,
user_sender: ::calloop::channel::Sender<T>,
Expand Down Expand Up @@ -416,6 +423,7 @@ impl<T: 'static> EventLoop<T> {
outputs: env.outputs.clone(),
_user_source: user_source,
user_sender,
cursor_manager,
_kbd_source: kbd_source,
window_target: RootELW {
p: crate::platform_impl::EventLoopWindowTarget::Wayland(EventLoopWindowTarget {
Expand Down Expand Up @@ -654,7 +662,16 @@ 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,
grab_cursor,
surface,
wid,
frame| {
if let Some(frame) = frame {
if let Some((w, h)) = newsize {
frame.resize(w, h);
Expand Down Expand Up @@ -684,6 +701,11 @@ impl<T> EventLoop<T> {
if closed {
sink.send_window_event(crate::event::WindowEvent::CloseRequested, wid);
}

if let Some(grab_cursor) = grab_cursor {
let surface = if grab_cursor { Some(surface) } else { None };
self.cursor_manager.lock().unwrap().grab_pointer(surface);
}
},
)
}
Expand Down
16 changes: 10 additions & 6 deletions src/platform_impl/linux/wayland/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ 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>>>, // Update grab state
}

impl Window {
Expand Down Expand Up @@ -143,13 +144,15 @@ 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));

evlp.store.lock().unwrap().windows.push(InternalWindow {
closed: false,
newsize: None,
size: size.clone(),
need_refresh: need_refresh.clone(),
fullscreen: fullscreen.clone(),
cursor_grab_changed: cursor_grab_changed.clone(),
need_frame_refresh: need_frame_refresh.clone(),
surface: surface.clone(),
kill_switch: kill_switch.clone(),
Expand All @@ -170,6 +173,7 @@ impl Window {
need_refresh,
cursor_manager,
fullscreen,
cursor_grab_changed,
})
}

Expand Down Expand Up @@ -309,12 +313,7 @@ impl Window {

#[inline]
pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
let mut cursor_manager = self.cursor_manager.lock().unwrap();
if grab {
cursor_manager.grab_pointer(Some(&self.surface));
} else {
cursor_manager.grab_pointer(None);
}
*self.cursor_grab_changed.lock().unwrap() = Some(grab);
Ok(())
}

Expand Down Expand Up @@ -374,6 +373,7 @@ struct InternalWindow {
need_refresh: Arc<Mutex<bool>>,
fullscreen: Arc<Mutex<bool>>,
need_frame_refresh: Arc<Mutex<bool>>,
cursor_grab_changed: Arc<Mutex<Option<bool>>>,
closed: bool,
kill_switch: Arc<Mutex<bool>>,
frame: Weak<Mutex<SWindow<ConceptFrame>>>,
Expand Down Expand Up @@ -441,6 +441,8 @@ impl WindowStore {
bool,
bool,
bool,
Option<bool>,
&wl_surface::WlSurface,
WindowId,
Option<&mut SWindow<ConceptFrame>>,
),
Expand All @@ -455,6 +457,8 @@ impl WindowStore {
replace(&mut *window.need_refresh.lock().unwrap(), false),
replace(&mut *window.need_frame_refresh.lock().unwrap(), false),
window.closed,
window.cursor_grab_changed.lock().unwrap().take(),
&window.surface,
make_wid(&window.surface),
opt_mutex_lock.as_mut().map(|m| &mut **m),
);
Expand Down

0 comments on commit 765225d

Please sign in to comment.