From 088e8e2c9cce7983f34e036931bab19909168cdc Mon Sep 17 00:00:00 2001 From: Nova Date: Fri, 11 Nov 2022 12:52:51 -0500 Subject: [PATCH] fix(wayland): remove unwraps --- src/wayland/compositor.rs | 2 - src/wayland/mod.rs | 14 +- src/wayland/panel_item.rs | 339 +++++++++++++++++++------------------- src/wayland/seat.rs | 3 + src/wayland/surface.rs | 26 +-- src/wayland/xdg_shell.rs | 49 +++--- 6 files changed, 217 insertions(+), 216 deletions(-) diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs index 7a7d304..66bc543 100644 --- a/src/wayland/compositor.rs +++ b/src/wayland/compositor.rs @@ -1,6 +1,5 @@ use super::{state::WaylandState, surface::CoreSurface}; use smithay::{ - backend::renderer::utils::on_commit_buffer_handler, delegate_compositor, reexports::wayland_server::protocol::wl_surface::WlSurface, wayland::compositor::{self, CompositorHandler, CompositorState}, @@ -12,7 +11,6 @@ impl CompositorHandler for WaylandState { } fn commit(&mut self, surface: &WlSurface) { - on_commit_buffer_handler(surface); compositor::with_states(surface, |data| { data.data_map.insert_if_missing_threadsafe(|| { CoreSurface::new( diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 9621782..9c9e4a9 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -149,15 +149,13 @@ impl Wayland { let time_ms = (sk.time_getf() * 1000.) as u64; for core_surface in CORE_SURFACES.get_valid_contents() { - let client_id = match core_surface.wl_surface().client() { - Some(client) => client.id(), - None => continue, - }; + let Some(client_id) = + core_surface + .wl_surface() + .and_then(|surf| surf.client()) + .map(|c| c.id()) else { continue }; let state = self.state.lock(); - let seat_data = match state.seats.get(&client_id) { - Some(seat_data) => seat_data.clone(), - None => continue, - }; + let Some(seat_data) = state.seats.get(&client_id).cloned() else { continue }; let output = state.output.clone(); core_surface.process( sk, diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index d441e8e..504e726 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -22,7 +22,10 @@ use serde::Deserialize; use smithay::{ reexports::wayland_server::protocol::wl_pointer::{Axis, ButtonState}, utils::Size, - wayland::{compositor::SurfaceData, shell::xdg::XdgToplevelSurfaceData}, + wayland::{ + compositor::SurfaceData, + shell::xdg::{Configure, XdgToplevelSurfaceData}, + }, }; use stardust_xr::schemas::flex::{deserialize, serialize}; use std::sync::{Arc, Weak}; @@ -103,11 +106,11 @@ impl PanelItem { node } - pub fn from_node(node: &Node) -> &PanelItem { - match &node.item.get().unwrap().specialization { - ItemType::Panel(panel_item) => panel_item, - _ => unreachable!(), - } + pub fn from_node(node: &Node) -> Option<&PanelItem> { + node.item.get().and_then(|item| match &item.specialization { + ItemType::Panel(panel_item) => Some(panel_item), + _ => None, + }) } fn apply_surface_material_flex( @@ -144,6 +147,20 @@ impl PanelItem { calling_client: Arc, data: &[u8], ) -> Result<()> { + let panel_item = match PanelItem::from_node(node) { + Some(panel_item) => panel_item, + None => return Ok(()), + }; + let cursor = panel_item.seat_data.cursor.lock(); + let cursor = match &*cursor { + Some(core_surface) => core_surface, + None => return Ok(()), + }; + let core_surface = match cursor.lock().core_surface.upgrade() { + Some(core_surface) => core_surface, + None => return Ok(()), + }; + #[derive(Deserialize)] struct SurfaceMaterialInfo<'a> { model_path: &'a str, @@ -159,13 +176,7 @@ impl PanelItem { .get() .ok_or_else(|| anyhow!("Node is not a model"))?; - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(cursor) = &*panel_item.seat_data.cursor.lock() { - if let Some(core_surface) = cursor.lock().core_surface.upgrade() { - core_surface.apply_material(model.clone(), info.idx); - } - } - } + core_surface.apply_material(model.clone(), info.idx); Ok(()) } @@ -187,25 +198,22 @@ impl PanelItem { } pub fn if_mapped(_core_surface: &Arc, surface_data: &SurfaceData) { - if let Some(panel_node) = surface_data.data_map.get::>() { - let panel_item = PanelItem::from_node(panel_node); + let Some(panel_node) = surface_data.data_map.get::>() else { return }; + let Some(panel_item) = PanelItem::from_node(panel_node) else { return }; - // core_surface.with_data(|core_surface_data| { - // panel_item.resize(); - // }); - - panel_item.set_cursor(); - } + panel_item.set_cursor(); } - pub fn resize(&self) { - self.core_surface.upgrade().unwrap().with_data(|data| { - let _ = self - .node - .upgrade() - .unwrap() - .send_remote_signal("resize", &serialize(data.size).unwrap()); - }); + pub fn ack_resize(&self, xdg_config: Configure) { + let Configure::Toplevel(config) = xdg_config else { return }; + let Some(size) = config.state.size else { return }; + let Some(core_surface) = self.core_surface.upgrade() else { return }; + core_surface.with_data(|data| data.size = Vector2::from([size.w as u32, size.h as u32])); + let _ = self + .node + .upgrade() + .unwrap() + .send_remote_signal("resize", &serialize((size.w, size.h)).unwrap()); } pub fn set_cursor(&self) { @@ -215,16 +223,12 @@ impl PanelItem { } let mut data = serialize(()).unwrap(); - if let Some(cursor) = &*self.seat_data.cursor.lock() { - let cursor = cursor.lock(); + let cursor = self.seat_data.cursor.lock(); + if let Some(cursor) = cursor.as_ref().map(|cursor| cursor.lock()) { if let Some(core_surface) = cursor.core_surface.upgrade() { if let Some(mapped_data) = &*core_surface.mapped_data.lock() { data = serialize((mapped_data.size, cursor.hotspot)).unwrap(); - } else { - return; - }; - } else { - return; + } } } @@ -241,109 +245,109 @@ impl PanelItem { _calling_client: Arc, _data: &[u8], ) -> Result<()> { - let panel_item = PanelItem::from_node(node); - if *panel_item.seat_data.pointer_active.lock() { - if let Some(core_surface) = panel_item.core_surface.upgrade() { - if let Some(pointer) = panel_item.seat_data.pointer() { - pointer.leave(0, &core_surface.wl_surface()); - *panel_item.seat_data.pointer_active.lock() = false; - pointer.frame(); - core_surface.flush_clients(); - } - } + let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; + if !panel_item.seat_data.pointer_active() { + return Ok(()); } + let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) }; + let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) }; + let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) }; + + pointer.leave(0, &wl_surface); + *panel_item.seat_data.pointer_active.lock() = false; + pointer.frame(); + core_surface.flush_clients(); Ok(()) } fn pointer_motion_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(pointer) = panel_item.seat_data.pointer() { - if let Some(core_surface) = panel_item.core_surface.upgrade() { - if let Some(size) = core_surface.with_data(|data| data.size) { - let mut position: Vector2 = deserialize(data)?; - position.x = position.x.clamp(0.0, size.x as f64); - position.y = position.y.clamp(0.0, size.y as f64); - let mut pointer_active = panel_item.seat_data.pointer_active.lock(); - if *pointer_active { - pointer.motion(0, position.x, position.y); - } else { - pointer.enter(0, &core_surface.wl_surface(), position.x, position.y); - *pointer_active = true; - } - pointer.frame(); - core_surface.flush_clients(); - } - } - } + let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; + if !panel_item.seat_data.pointer_active() { + return Ok(()); } + let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) }; + let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) }; + let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) }; + + let Some(pointer_surface_size) = + core_surface.with_data(|data| data.size) else { return Ok(()) }; + + let mut position: Vector2 = deserialize(data)?; + position.x = position.x.clamp(0.0, pointer_surface_size.x as f64); + position.y = position.y.clamp(0.0, pointer_surface_size.y as f64); + let mut pointer_active = panel_item.seat_data.pointer_active.lock(); + if *pointer_active { + pointer.motion(0, position.x, position.y); + } else { + pointer.enter(0, &wl_surface, position.x, position.y); + *pointer_active = true; + } + pointer.frame(); + core_surface.flush_clients(); Ok(()) } fn pointer_button_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(pointer) = panel_item.seat_data.pointer() { - if *panel_item.seat_data.pointer_active.lock() { - if let Some(core_surface) = panel_item.core_surface.upgrade() { - let (button, state): (u32, u32) = deserialize(data)?; - pointer.button( - 0, - 0, - button, - match state { - 0 => ButtonState::Released, - 1 => ButtonState::Pressed, - _ => { - bail!("Button state is out of bounds") - } - }, - ); - pointer.frame(); - core_surface.flush_clients(); - } - } - } + let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; + if !panel_item.seat_data.pointer_active() { + return Ok(()); } + let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) }; + let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) }; + + let (button, state): (u32, u32) = deserialize(data)?; + pointer.button( + 0, + 0, + button, + match state { + 0 => ButtonState::Released, + 1 => ButtonState::Pressed, + _ => { + bail!("Button state is out of bounds") + } + }, + ); + pointer.frame(); + core_surface.flush_clients(); Ok(()) } fn pointer_scroll_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; + if !panel_item.seat_data.pointer_active() { + return Ok(()); + } + let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) }; + let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) }; + #[derive(Deserialize)] struct PointerScrollArgs { axis_continuous: Vector2, axis_discrete: Option>, } - let args: PointerScrollArgs = deserialize(data)?; - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(pointer) = panel_item.seat_data.pointer() { - if *panel_item.seat_data.pointer_active.lock() { - if let Some(core_surface) = panel_item.core_surface.upgrade() { - let flex = flexbuffers::Reader::get_root(data)?; - if flex.flexbuffer_type().is_null() { - pointer.axis_stop(0, Axis::HorizontalScroll); - pointer.axis_stop(0, Axis::VerticalScroll); - } else { - pointer.axis(0, Axis::HorizontalScroll, args.axis_continuous.x as f64); - pointer.axis(0, Axis::VerticalScroll, args.axis_continuous.y as f64); - if let Some(axis_discrete_vec) = args.axis_discrete { - pointer.axis_discrete( - Axis::HorizontalScroll, - axis_discrete_vec.x as i32, - ); - pointer.axis_discrete( - Axis::VerticalScroll, - axis_discrete_vec.y as i32, - ); - } - } - pointer.frame(); - core_surface.flush_clients(); - } + let args: Option = deserialize(data)?; + + match args { + Some(args) => { + pointer.axis(0, Axis::HorizontalScroll, args.axis_continuous.x as f64); + pointer.axis(0, Axis::VerticalScroll, args.axis_continuous.y as f64); + if let Some(axis_discrete_vec) = args.axis_discrete { + pointer.axis_discrete(Axis::HorizontalScroll, axis_discrete_vec.x as i32); + pointer.axis_discrete(Axis::VerticalScroll, axis_discrete_vec.y as i32); } } - } + None => { + pointer.axis_stop(0, Axis::HorizontalScroll); + pointer.axis_stop(0, Axis::VerticalScroll); + } + }; + + pointer.frame(); + core_surface.flush_clients(); Ok(()) } @@ -391,19 +395,18 @@ impl PanelItem { } fn keyboard_activate_flex(node: &Node, keymap: &Keymap) -> Result<()> { - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(keyboard) = panel_item.seat_data.keyboard() { - if let Some(core_surface) = panel_item.core_surface.upgrade() { - let mut keyboard_info = panel_item.seat_data.keyboard_info.lock(); - if keyboard_info.is_none() { - keyboard.enter(0, &core_surface.wl_surface(), vec![]); - keyboard.repeat_info(0, 0); - } - keyboard_info.replace(KeyboardInfo::new(keymap)); - keyboard_info.as_ref().unwrap().keymap.send(keyboard)?; - } - } + let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; + let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) }; + let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) }; + let Some(keyboard) = panel_item.seat_data.keyboard() else { return Ok(()) }; + + let mut keyboard_info = panel_item.seat_data.keyboard_info.lock(); + if keyboard_info.is_none() { + keyboard.enter(0, &wl_surface, vec![]); + keyboard.repeat_info(0, 0); } + keyboard_info.replace(KeyboardInfo::new(keymap)); + keyboard_info.as_ref().unwrap().keymap.send(keyboard)?; Ok(()) } @@ -413,16 +416,15 @@ impl PanelItem { _calling_client: Arc, _data: &[u8], ) -> Result<()> { - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(keyboard) = panel_item.seat_data.keyboard() { - if let Some(core_surface) = panel_item.core_surface.upgrade() { - let mut keyboard_info = panel_item.seat_data.keyboard_info.lock(); - if keyboard_info.is_some() { - keyboard.leave(0, &core_surface.wl_surface()); - *keyboard_info = None; - } - } - } + let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; + let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) }; + let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) }; + let Some(keyboard) = panel_item.seat_data.keyboard() else { return Ok(()) }; + + let mut keyboard_info = panel_item.seat_data.keyboard_info.lock(); + if keyboard_info.is_some() { + keyboard.leave(0, &wl_surface); + *keyboard_info = None; } Ok(()) @@ -433,49 +435,48 @@ impl PanelItem { _calling_client: Arc, data: &[u8], ) -> Result<()> { - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(keyboard) = panel_item.seat_data.keyboard() { - let mut keyboard_info = panel_item.seat_data.keyboard_info.lock(); - if let Some(keyboard_info) = &mut *keyboard_info { - let (key, state): (u32, u32) = deserialize(data)?; - keyboard_info.process(key, state, keyboard)?; - } - } + let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; + let Some(keyboard) = panel_item.seat_data.keyboard() else { return Ok(()) }; + + let mut keyboard_info = panel_item.seat_data.keyboard_info.lock(); + if let Some(keyboard_info) = &mut *keyboard_info { + let (key, state): (u32, u32) = deserialize(data)?; + keyboard_info.process(key, state, keyboard)?; } Ok(()) } fn resize_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(core_surface) = panel_item.core_surface.upgrade() { - let size: Vector2 = deserialize(data)?; + let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; + let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) }; + let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) }; + let size: Vector2 = deserialize(data)?; - let toplevel_surface = core_surface - .wayland_state() - .lock() - .xdg_shell_state - .toplevel_surfaces(|surfaces| { - surfaces - .iter() - .find(|surf| surf.wl_surface().clone() == core_surface.wl_surface()) - .cloned() - }); + let toplevel_surface = core_surface + .wayland_state() + .lock() + .xdg_shell_state + .toplevel_surfaces(|surfaces| { + surfaces + .iter() + .find(|surf| surf.wl_surface().clone() == wl_surface) + .cloned() + }); - if let Some(toplevel_surface) = toplevel_surface { - let mut size_set = false; - toplevel_surface.with_pending_state(|state| { - state.size = Some(Size::default()); - state.size.as_mut().unwrap().w = size.x as i32; - state.size.as_mut().unwrap().h = size.y as i32; - size_set = true; - }); - if size_set { - toplevel_surface.send_configure(); - } - } + if let Some(toplevel_surface) = toplevel_surface { + let mut size_set = false; + toplevel_surface.with_pending_state(|state| { + state.size = Some(Size::default()); + state.size.as_mut().unwrap().w = size.x as i32; + state.size.as_mut().unwrap().h = size.y as i32; + size_set = true; + }); + if size_set { + toplevel_surface.send_configure(); } } + Ok(()) } } diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index 526d3f0..740c7d7 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -121,6 +121,9 @@ impl SeatDataInner { pub fn pointer(&self) -> Option<&WlPointer> { self.pointer.get() } + pub fn pointer_active(&self) -> bool { + *self.pointer_active.lock() + } pub fn keyboard(&self) -> Option<&WlKeyboard> { self.keyboard.get() } diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index b323dee..a40e580 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -10,7 +10,7 @@ use slog::Logger; use smithay::{ backend::renderer::{ gles2::{Gles2Renderer, Gles2Texture}, - utils::{import_surface_tree, RendererSurfaceStateUserData}, + utils::{import_surface_tree, on_commit_buffer_handler, RendererSurfaceStateUserData}, Texture, }, desktop::utils::send_frames_surface_tree, @@ -18,7 +18,7 @@ use smithay::{ reexports::wayland_server::{ self, protocol::wl_surface::WlSurface, Display, DisplayHandle, Resource, }, - wayland::compositor::{self, SurfaceData, SurfaceUserData}, + wayland::compositor::{self, SurfaceData}, }; use std::{ sync::{Arc, Weak}, @@ -128,17 +128,16 @@ impl CoreSurface { on_mapped: F, if_mapped: M, ) { - // Avoid a panic in rare cases - if self.wl_surface().data::().is_none() { - return; - } + let Some(wl_surface) = self.wl_surface() else { return }; + // Let smithay handle buffer management (has to be done here as RendererSurfaceStates is not thread safe) + on_commit_buffer_handler(&wl_surface); // Import all surface buffers into textures - if import_surface_tree(renderer, &self.wl_surface(), log).is_err() { + if import_surface_tree(renderer, &wl_surface, log).is_err() { return; } - let mapped = compositor::with_states(&self.wl_surface(), |data| { + let mapped = compositor::with_states(&wl_surface, |data| { data.data_map .get::() .map(|surface_states| surface_states.borrow().wl_buffer().is_some()) @@ -170,7 +169,7 @@ impl CoreSurface { if_mapped(data); }); - send_frames_surface_tree(&self.wl_surface(), &output, time, None, |_, _| { + send_frames_surface_tree(&wl_surface, &output, time, None, |_, _| { Some(output.clone()) }); } @@ -198,15 +197,16 @@ impl CoreSurface { self.state.upgrade().unwrap() } - pub fn wl_surface(&self) -> WlSurface { - self.weak_surface.upgrade().unwrap() + pub fn wl_surface(&self) -> Option { + self.weak_surface.upgrade().ok() } - pub fn with_states(&self, f: F) -> T + pub fn with_states(&self, f: F) -> Option where F: FnOnce(&SurfaceData) -> T, { - compositor::with_states(&self.wl_surface(), f) + self.wl_surface() + .map(|wl_surface| compositor::with_states(&wl_surface, f)) } pub fn with_data(&self, f: F) -> Option diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index d5abff2..858e983 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use crate::nodes::Node; -use super::{panel_item::PanelItem, state::WaylandState, surface::CoreSurface}; +use super::{panel_item::PanelItem, state::WaylandState}; use smithay::{ delegate_xdg_shell, reexports::{ @@ -37,29 +37,30 @@ impl XdgShellHandler for WaylandState { surface.send_configure(); } fn ack_configure(&mut self, surface: WlSurface, configure: Configure) { - match configure { - Configure::Toplevel(config) => { - if let Some(size) = config.state.size { - compositor::with_states(&surface, |data| { - if let Some(panel_node) = data.data_map.get::>() { - if let Some(core_surface) = data.data_map.get::>() { - let panel_item = PanelItem::from_node(panel_node); - let has_data = core_surface - .with_data(|data| { - data.size.x = size.w as u32; - data.size.y = size.h as u32; - }) - .is_some(); - if has_data { - panel_item.resize(); - } - } - } - }) - } - } - Configure::Popup(_) => (), - } + // let size = match configure { + // Configure::Toplevel(config) => config.state.size, + // Configure::Popup(_) => return, + // }; + // let core_surface = match configure { + // Configure::Toplevel(config) => { + // .and_then(|panel| panel.core_surface()) + // } + // Configure::Popup(_) => return, + // }; + let Some(panel_item_node) = compositor::with_states(&surface, |data| { + data.data_map.get::>().cloned() + }) else { return }; + let Some(panel_item) = PanelItem::from_node(&panel_item_node) else { return }; + panel_item.ack_resize(configure); + + // let has_data = core_surface + // .with_data(|data| { + // data.size.x = size.w as u32; + // data.size.y = size.h as u32; + // }) + // .is_some(); + // if has_data { + // } } fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {}