seat: Make render-related state thread-safe

This commit is contained in:
Victoria Brekenfeld 2024-06-07 19:26:23 +02:00 committed by Victoria Brekenfeld
parent bd58481d19
commit c7d50e7c5b
11 changed files with 137 additions and 112 deletions

View file

@ -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<CursorShape>,
pub type CursorState = Mutex<CursorStateInner>;
pub struct CursorStateInner {
current_cursor: CursorShape,
pub cursors: HashMap<CursorShape, Cursor>,
current_image: RefCell<Option<Image>>,
image_cache: RefCell<Vec<(Image, MemoryRenderBuffer)>>,
current_image: Option<Image>,
//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::<RefCell<CursorImageStatus>>()
.map(|cell| {
let mut cursor_status = cell.borrow_mut();
.get::<Mutex<CursorImageStatus>>()
.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::<CursorState>().unwrap();
let frame = state
.cursors
.get(&*state.current_cursor.borrow())
.unwrap()
.get_image(
integer_scale,
Into::<Duration>::into(time).as_millis() as u32,
);
let mut state = seat_userdata.get::<CursorState>().unwrap().lock().unwrap();
let frame = state.cursors.get(&state.current_cursor).unwrap().get_image(
integer_scale,
Into::<Duration>::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::<i32, BufferCoords>::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,

View file

@ -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<Item = &'a Seat<State>>,
theme: &Theme,
now: Time<Monotonic>,
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::<SeatMoveGrabState>()
.unwrap()
.borrow()
.lock()
.unwrap()
.as_ref()
.map(|state| state.render::<CosmicElement<R>, R>(renderer, output, theme))
{
@ -459,7 +461,8 @@ where
.user_data()
.get::<SeatMenuGrabState>()
.unwrap()
.borrow()
.lock()
.unwrap()
.as_ref()
.map(|state| state.render::<CosmicMappedRenderElement<R>, R>(renderer, output))
{
@ -492,9 +495,15 @@ where
CosmicMappedRenderElement<R>: RenderElement<R>,
WorkspaceRenderElement<R>: RenderElement<R>,
{
let seats = shell
.seats
.iter()
.cloned()
.collect::<Vec<_>>();
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::<SeatMoveGrabState>()
.unwrap()
.borrow()
.lock()
.unwrap()
.is_some();
let active_output = last_active_seat.active_output();
let output_size = output.geometry().size;