mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
Wayland: Fix panic when calling set_cursor_grab from a different thread than evlp's one. (#1206)
This commit also start following X11 behavior on cursor icon update when
cursor is invisible.
Fixes regression introdced in 5ced36e319
This commit is contained in:
parent
34dce8069f
commit
765225d918
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -143,6 +144,7 @@ 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,
|
||||
|
@ -150,6 +152,7 @@ impl Window {
|
|||
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(),
|
||||
|
@ -170,6 +173,7 @@ impl Window {
|
|||
need_refresh,
|
||||
cursor_manager,
|
||||
fullscreen,
|
||||
cursor_grab_changed,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -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>>>,
|
||||
|
@ -441,6 +441,8 @@ impl WindowStore {
|
|||
bool,
|
||||
bool,
|
||||
bool,
|
||||
Option<bool>,
|
||||
&wl_surface::WlSurface,
|
||||
WindowId,
|
||||
Option<&mut SWindow<ConceptFrame>>,
|
||||
),
|
||||
|
@ -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),
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue