diff --git a/src/backend/render/cursor.rs b/src/backend/render/cursor.rs index c11af140..126e6717 100644 --- a/src/backend/render/cursor.rs +++ b/src/backend/render/cursor.rs @@ -24,7 +24,7 @@ use smithay::{ }, wayland::compositor::{get_role, with_states}, }; -use std::{cell::RefCell, collections::HashMap, io::Read, sync::Mutex, time::Duration}; +use std::{collections::HashMap, io::Read, sync::Mutex, time::Duration}; use tracing::warn; use xcursor::{ parser::{parse_xcursor, Image}, @@ -221,16 +221,17 @@ where ) } -pub struct CursorState { - current_cursor: RefCell, +pub type CursorState = Mutex; +pub struct CursorStateInner { + current_cursor: CursorShape, pub cursors: HashMap, - current_image: RefCell>, - image_cache: RefCell>, + current_image: Option, + //image_cache: Vec<(Image, MemoryRenderBuffer)>, } -impl CursorState { - pub fn set_shape(&self, shape: CursorShape) { - *self.current_cursor.borrow_mut() = shape; +impl CursorStateInner { + pub fn set_shape(&mut self, shape: CursorShape) { + self.current_cursor = shape; } } @@ -245,11 +246,11 @@ pub fn load_cursor_theme() -> (CursorTheme, u32) { (CursorTheme::load(&name), size) } -impl Default for CursorState { - fn default() -> CursorState { +impl Default for CursorStateInner { + fn default() -> CursorStateInner { let (theme, size) = load_cursor_theme(); - CursorState { - current_cursor: RefCell::new(CursorShape::Default), + CursorStateInner { + current_cursor: CursorShape::Default, cursors: { let mut map = HashMap::new(); map.insert( @@ -302,8 +303,7 @@ impl Default for CursorState { ); map }, - current_image: RefCell::new(None), - image_cache: RefCell::new(Vec::new()), + current_image: None, } } } @@ -325,9 +325,9 @@ where // reset the cursor if the surface is no longer alive let cursor_status = seat .user_data() - .get::>() - .map(|cell| { - let mut cursor_status = cell.borrow_mut(); + .get::>() + .map(|lock| { + let mut cursor_status = lock.lock().unwrap(); if let CursorImageStatus::Surface(ref surface) = *cursor_status { if !surface.alive() { *cursor_status = CursorImageStatus::default_named(); @@ -344,26 +344,24 @@ where let integer_scale = scale.x.max(scale.y).ceil() as u32; let seat_userdata = seat.user_data(); - let state = seat_userdata.get::().unwrap(); - let frame = state - .cursors - .get(&*state.current_cursor.borrow()) - .unwrap() - .get_image( - integer_scale, - Into::::into(time).as_millis() as u32, - ); + let mut state = seat_userdata.get::().unwrap().lock().unwrap(); + let frame = state.cursors.get(&state.current_cursor).unwrap().get_image( + integer_scale, + Into::::into(time).as_millis() as u32, + ); - let mut pointer_images = state.image_cache.borrow_mut(); + /* + let mut pointer_images = &mut state.image_cache; let maybe_image = pointer_images .iter() .find_map(|(image, texture)| if image == &frame { Some(texture) } else { None }); - let pointer_image = match maybe_image { + */ + let pointer_image = /*match maybe_image { Some(image) => image, None => { - let buffer = MemoryRenderBuffer::from_slice( + let buffer =*/ MemoryRenderBuffer::from_slice( &frame.pixels_rgba, Fourcc::Argb8888, (frame.width as i32, frame.height as i32), @@ -371,20 +369,21 @@ where Transform::Normal, None, ); + /* pointer_images.push((frame.clone(), buffer)); pointer_images.last().map(|(_, i)| i).unwrap() } - }; + };*/ let hotspot = Point::::from((frame.xhot as i32, frame.yhot as i32)); - *state.current_image.borrow_mut() = Some(frame); + state.current_image = Some(frame); return vec![( CursorRenderElement::Static( MemoryRenderBufferRenderElement::from_buffer( renderer, location.to_physical(scale), - pointer_image, + &pointer_image, None, None, None, diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index e7cdf873..266dde8e 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -58,6 +58,7 @@ use smithay::{ }, }, desktop::{layer_map_for_output, PopupManager}, + input::Seat, output::{Output, OutputNoMode}, utils::{IsAlive, Logical, Monotonic, Point, Rectangle, Scale, Time, Transform}, wayland::{ @@ -388,9 +389,9 @@ pub enum CursorMode { } #[profiling::function] -pub fn cursor_elements<'frame, R>( +pub fn cursor_elements<'a, 'frame, R>( renderer: &mut R, - shell: &Shell, + seats: impl Iterator>, theme: &Theme, now: Time, output: &Output, @@ -405,7 +406,7 @@ where let scale = output.current_scale().fractional_scale(); let mut elements = Vec::new(); - for seat in shell.seats.iter() { + for seat in seats { let pointer = match seat.get_pointer() { Some(ptr) => ptr, None => continue, @@ -416,7 +417,7 @@ where elements.extend( cursor::draw_cursor( renderer, - seat, + &seat, location, scale.into(), now, @@ -434,7 +435,7 @@ where } if !exclude_dnd_icon { - if let Some(wl_surface) = get_dnd_icon(seat) { + if let Some(wl_surface) = get_dnd_icon(&seat) { elements.extend( cursor::draw_dnd_icon(renderer, &wl_surface, location.to_i32_round(), scale) .into_iter() @@ -448,7 +449,8 @@ where .user_data() .get::() .unwrap() - .borrow() + .lock() + .unwrap() .as_ref() .map(|state| state.render::, R>(renderer, output, theme)) { @@ -459,7 +461,8 @@ where .user_data() .get::() .unwrap() - .borrow() + .lock() + .unwrap() .as_ref() .map(|state| state.render::, R>(renderer, output)) { @@ -492,9 +495,15 @@ where CosmicMappedRenderElement: RenderElement, WorkspaceRenderElement: RenderElement, { + let seats = shell + .seats + .iter() + .cloned() + .collect::>(); + let mut elements = cursor_elements( renderer, - shell, + seats.iter(), theme, now, output, @@ -556,13 +565,13 @@ where overview.0, overview.1.map(|indicator| (indicator, swap_tree)), ); - let last_active_seat = shell.seats.last_active(); let move_active = last_active_seat .user_data() .get::() .unwrap() - .borrow() + .lock() + .unwrap() .is_some(); let active_output = last_active_seat.active_output(); let output_size = output.geometry().size; diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index dba91f62..8a61873d 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -1197,13 +1197,15 @@ impl PointerTarget for CosmicStack { }; let _old_focus = p.swap_focus(Some(next)); - let cursor_state = seat.user_data().get::().unwrap(); - cursor_state.set_shape(next.cursor_shape()); - let cursor_status = seat + let mut cursor_state = seat .user_data() - .get::>() + .get::() + .unwrap() + .lock() .unwrap(); - *cursor_status.borrow_mut() = CursorImageStatus::default_named(); + cursor_state.set_shape(next.cursor_shape()); + let cursor_status = seat.user_data().get::>().unwrap(); + *cursor_status.lock().unwrap() = CursorImageStatus::default_named(); }); event.location -= self.0.with_program(|p| { @@ -1225,13 +1227,15 @@ impl PointerTarget for CosmicStack { }; let _previous = p.swap_focus(Some(next)); - let cursor_state = seat.user_data().get::().unwrap(); - cursor_state.set_shape(next.cursor_shape()); - let cursor_status = seat + let mut cursor_state = seat .user_data() - .get::>() + .get::() + .unwrap() + .lock() .unwrap(); - *cursor_status.borrow_mut() = CursorImageStatus::default_named(); + cursor_state.set_shape(next.cursor_shape()); + let cursor_status = seat.user_data().get::>().unwrap(); + *cursor_status.lock().unwrap() = CursorImageStatus::default_named(); }); let active_window_geo = self.0.with_program(|p| { @@ -1322,7 +1326,12 @@ impl PointerTarget for CosmicStack { fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { self.0.with_program(|p| { - let cursor_state = seat.user_data().get::().unwrap(); + let mut cursor_state = seat + .user_data() + .get::() + .unwrap() + .lock() + .unwrap(); cursor_state.set_shape(CursorShape::Default); let _previous = p.swap_focus(None); }); diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index e8b42010..66346cee 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -46,7 +46,6 @@ use smithay::{ }; use std::{ borrow::Cow, - cell::RefCell, fmt, hash::Hash, sync::{ @@ -686,12 +685,9 @@ impl PointerTarget for CosmicWindow { assert_eq!(old_focus, None); let cursor_state = seat.user_data().get::().unwrap(); - cursor_state.set_shape(next.cursor_shape()); - let cursor_status = seat - .user_data() - .get::>() - .unwrap(); - *cursor_status.borrow_mut() = CursorImageStatus::default_named(); + cursor_state.lock().unwrap().set_shape(next.cursor_shape()); + let cursor_status = seat.user_data().get::>().unwrap(); + *cursor_status.lock().unwrap() = CursorImageStatus::default_named(); } }); @@ -709,12 +705,9 @@ impl PointerTarget for CosmicWindow { let _previous = p.swap_focus(Some(next)); let cursor_state = seat.user_data().get::().unwrap(); - cursor_state.set_shape(next.cursor_shape()); - let cursor_status = seat - .user_data() - .get::>() - .unwrap(); - *cursor_status.borrow_mut() = CursorImageStatus::default_named(); + cursor_state.lock().unwrap().set_shape(next.cursor_shape()); + let cursor_status = seat.user_data().get::>().unwrap(); + *cursor_status.lock().unwrap() = CursorImageStatus::default_named(); } }); @@ -794,7 +787,7 @@ impl PointerTarget for CosmicWindow { fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { self.0.with_program(|p| { let cursor_state = seat.user_data().get::().unwrap(); - cursor_state.set_shape(CursorShape::Default); + cursor_state.lock().unwrap().set_shape(CursorShape::Default); let _previous = p.swap_focus(None); }); PointerTarget::leave(&self.0, seat, data, serial, time) diff --git a/src/shell/focus/mod.rs b/src/shell/focus/mod.rs index 2752e3cb..275c5a66 100644 --- a/src/shell/focus/mod.rs +++ b/src/shell/focus/mod.rs @@ -18,7 +18,7 @@ use smithay::{ shell::wlr_layer::{KeyboardInteractivity, Layer}, }, }; -use std::{borrow::Cow, cell::RefCell}; +use std::{borrow::Cow, sync::Mutex}; use tracing::{debug, trace}; use self::target::{KeyboardFocusTarget, WindowGroup}; @@ -77,27 +77,28 @@ impl<'a> FocusStackMut<'a> { } } -pub struct ActiveFocus(RefCell>); +pub struct ActiveFocus(Mutex>); impl ActiveFocus { fn set(seat: &Seat, target: Option) { if !seat .user_data() - .insert_if_missing(|| ActiveFocus(RefCell::new(target.clone()))) + .insert_if_missing_threadsafe(|| ActiveFocus(Mutex::new(target.clone()))) { *seat .user_data() .get::() .unwrap() .0 - .borrow_mut() = target; + .lock() + .unwrap() = target; } } fn get(seat: &Seat) -> Option { seat.user_data() .get::() - .and_then(|a| a.0.borrow().clone()) + .and_then(|a| a.0.lock().unwrap().clone()) } } diff --git a/src/shell/grabs/menu/mod.rs b/src/shell/grabs/menu/mod.rs index 73fd9442..0ced2bb8 100644 --- a/src/shell/grabs/menu/mod.rs +++ b/src/shell/grabs/menu/mod.rs @@ -1,9 +1,6 @@ -use std::{ - cell::RefCell, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, Mutex, - }, +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, }; use calloop::LoopHandle; @@ -57,7 +54,7 @@ pub use self::default::*; pub struct MenuGrabState { elements: Arc>>, } -pub type SeatMenuGrabState = RefCell>; +pub type SeatMenuGrabState = Mutex>; impl MenuGrabState { pub fn render(&self, renderer: &mut R, output: &Output) -> Vec @@ -228,7 +225,8 @@ impl Program for ContextMenu { .user_data() .get::() .unwrap() - .borrow_mut(); + .lock() + .unwrap(); if let Some(grab_state) = &*grab_state { let mut elements = grab_state.elements.lock().unwrap(); @@ -320,7 +318,8 @@ impl Program for ContextMenu { .user_data() .get::() .unwrap() - .borrow_mut(); + .lock() + .unwrap(); if let Some(grab_state) = &*grab_state { let mut elements = grab_state.elements.lock().unwrap(); @@ -713,7 +712,8 @@ impl MenuGrab { .user_data() .get::() .unwrap() - .borrow_mut() = Some(grab_state); + .lock() + .unwrap() = Some(grab_state); MenuGrab { elements, @@ -729,7 +729,8 @@ impl Drop for MenuGrab { .user_data() .get::() .unwrap() - .borrow_mut() + .lock() + .unwrap() .take(); } } diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index 7e2cd2cc..597c4b2f 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -44,11 +44,15 @@ use smithay::{ output::Output, utils::{IsAlive, Logical, Point, Rectangle, Scale, Serial, SERIAL_COUNTER}, }; -use std::{cell::RefCell, collections::HashSet, sync::atomic::Ordering, time::Instant}; +use std::{ + collections::HashSet, + sync::{atomic::Ordering, Mutex}, + time::Instant, +}; use super::{GrabStartData, ReleaseMode}; -pub type SeatMoveGrabState = RefCell>; +pub type SeatMoveGrabState = Mutex>; const RESCALE_ANIMATION_DURATION: f64 = 150.0; @@ -363,7 +367,7 @@ impl MoveGrab { .seat .user_data() .get::() - .map(|s| s.borrow_mut()); + .map(|s| s.lock().unwrap()); if let Some(grab_state) = borrow.as_mut().and_then(|s| s.as_mut()) { grab_state.location = location; grab_state.cursor_output = self.cursor_output.clone(); @@ -698,11 +702,12 @@ impl MoveGrab { .user_data() .get::() .unwrap() - .borrow_mut() = Some(grab_state); + .lock() + .unwrap() = Some(grab_state); { let cursor_state = seat.user_data().get::().unwrap(); - cursor_state.set_shape(CursorShape::Grab); + cursor_state.lock().unwrap().set_shape(CursorShape::Grab); } MoveGrab { @@ -743,7 +748,7 @@ impl Drop for MoveGrab { let position: Option<(CosmicMapped, Point)> = if let Some(grab_state) = seat.user_data() .get::() - .and_then(|s| s.borrow_mut().take()) + .and_then(|s| s.lock().unwrap().take()) { if grab_state.window.alive() { let window_location = @@ -842,7 +847,7 @@ impl Drop for MoveGrab { { let cursor_state = seat.user_data().get::().unwrap(); - cursor_state.set_shape(CursorShape::Default); + cursor_state.lock().unwrap().set_shape(CursorShape::Default); } if let Some((mapped, position)) = position { diff --git a/src/shell/layout/tiling/grabs/resize.rs b/src/shell/layout/tiling/grabs/resize.rs index 562b2d44..2f908941 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -50,10 +50,13 @@ impl PointerTarget for ResizeForkTarget { fn enter(&self, seat: &Seat, _data: &mut State, _event: &MotionEvent) { let user_data = seat.user_data(); let cursor_state = user_data.get::().unwrap(); - cursor_state.set_shape(match self.orientation { - Orientation::Horizontal => CursorShape::RowResize, - Orientation::Vertical => CursorShape::ColResize, - }); + cursor_state + .lock() + .unwrap() + .set_shape(match self.orientation { + Orientation::Horizontal => CursorShape::RowResize, + Orientation::Vertical => CursorShape::ColResize, + }); } fn leave( @@ -65,7 +68,7 @@ impl PointerTarget for ResizeForkTarget { ) { let user_data = seat.user_data(); let cursor_state = user_data.get::().unwrap(); - cursor_state.set_shape(CursorShape::Default) + cursor_state.lock().unwrap().set_shape(CursorShape::Default) } fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { diff --git a/src/shell/seats.rs b/src/shell/seats.rs index 1638b751..d42941df 100644 --- a/src/shell/seats.rs +++ b/src/shell/seats.rs @@ -155,7 +155,7 @@ impl Drop for SeatId { #[repr(transparent)] struct SeatId(pub usize); -struct ActiveOutput(pub RefCell); +struct ActiveOutput(pub Mutex); pub fn create_seat( dh: &DisplayHandle, @@ -166,15 +166,15 @@ pub fn create_seat( ) -> Seat { let mut seat = seat_state.new_wl_seat(dh, name); let userdata = seat.user_data(); - userdata.insert_if_missing(SeatId::default); + userdata.insert_if_missing_threadsafe(SeatId::default); userdata.insert_if_missing(Devices::default); userdata.insert_if_missing(SupressedKeys::default); userdata.insert_if_missing(ModifiersShortcutQueue::default); - userdata.insert_if_missing(SeatMoveGrabState::default); - userdata.insert_if_missing(SeatMenuGrabState::default); - userdata.insert_if_missing(CursorState::default); - userdata.insert_if_missing(|| ActiveOutput(RefCell::new(output.clone()))); - userdata.insert_if_missing(|| RefCell::new(CursorImageStatus::default_named())); + userdata.insert_if_missing_threadsafe(SeatMoveGrabState::default); + userdata.insert_if_missing_threadsafe(SeatMenuGrabState::default); + userdata.insert_if_missing_threadsafe(CursorState::default); + userdata.insert_if_missing_threadsafe(|| ActiveOutput(Mutex::new(output.clone()))); + userdata.insert_if_missing_threadsafe(|| Mutex::new(CursorImageStatus::default_named())); // A lot of clients bind keyboard and pointer unconditionally once on launch.. // Initial clients might race the compositor on adding periheral and @@ -232,7 +232,7 @@ impl SeatExt for Seat { fn active_output(&self) -> Output { self.user_data() .get::() - .map(|x| x.0.borrow().clone()) + .map(|x| x.0.lock().unwrap().clone()) .unwrap() } @@ -242,7 +242,8 @@ impl SeatExt for Seat { .get::() .unwrap() .0 - .borrow_mut() = output.clone(); + .lock() + .unwrap() = output.clone(); } fn devices(&self) -> &Devices { @@ -266,9 +267,9 @@ impl SeatExt for Seat { let cursor_status = self .user_data() - .get::>() - .map(|cell| { - let mut cursor_status = cell.borrow_mut(); + .get::>() + .map(|lock| { + let mut cursor_status = lock.lock().unwrap(); if let CursorImageStatus::Surface(ref surface) = *cursor_status { if !surface.alive() { *cursor_status = CursorImageStatus::default_named(); @@ -298,9 +299,11 @@ impl SeatExt for Seat { } CursorImageStatus::Named(CursorIcon::Default) => { let seat_userdata = self.user_data(); - seat_userdata.insert_if_missing(CursorState::default); + seat_userdata.insert_if_missing_threadsafe(CursorState::default); let state = seat_userdata.get::().unwrap(); let frame = state + .lock() + .unwrap() .cursors .get(&CursorShape::Default) .unwrap() diff --git a/src/wayland/handlers/compositor.rs b/src/wayland/handlers/compositor.rs index 5cfea8bc..b3c5f09c 100644 --- a/src/wayland/handlers/compositor.rs +++ b/src/wayland/handlers/compositor.rs @@ -172,7 +172,8 @@ impl CompositorHandler for State { .user_data() .get::() .unwrap() - .borrow() + .lock() + .unwrap() .as_ref() .and_then(|state| { state diff --git a/src/wayland/handlers/seat.rs b/src/wayland/handlers/seat.rs index c0eded05..6ded40be 100644 --- a/src/wayland/handlers/seat.rs +++ b/src/wayland/handlers/seat.rs @@ -9,7 +9,7 @@ use smithay::{ delegate_seat, input::{keyboard::LedState, pointer::CursorImageStatus, SeatHandler, SeatState}, }; -use std::cell::RefCell; +use std::sync::Mutex; impl SeatHandler for State { type KeyboardFocus = KeyboardFocusTarget; @@ -27,9 +27,10 @@ impl SeatHandler for State { ) { *seat .user_data() - .get::>() + .get::>() .unwrap() - .borrow_mut() = image; + .lock() + .unwrap() = image; } fn focus_changed(