diff --git a/Cargo.lock b/Cargo.lock index a847c43..ececf87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1339,7 +1339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2285,7 +2285,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/smithay/smithay.git#f208cd758416e4495e9eb8b27a96c523e92817a6" +source = "git+https://github.com/smithay/smithay.git#c6aab182a3c9f106d9c7a0ea34187f90403e59e7" dependencies = [ "appendlist", "bitflags 2.6.0", diff --git a/src/nodes/items/panel.rs b/src/nodes/items/panel.rs index be0ae91..5b2ebbb 100644 --- a/src/nodes/items/panel.rs +++ b/src/nodes/items/panel.rs @@ -110,12 +110,6 @@ impl PanelItem { (node, panel_item) } - pub fn drop_toplevel(&self) { - let Some(node) = self.node.upgrade() else { - return; - }; - node.destroy(); - } } // Remote signals diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs index adebfa6..a141ecc 100644 --- a/src/wayland/compositor.rs +++ b/src/wayland/compositor.rs @@ -33,9 +33,6 @@ impl CompositorHandler for WaylandState { data.data_map.get::>().cloned() }); - if let Some(core_surface) = CoreSurface::from_wl_surface(surface) { - core_surface.commit(count); - } } fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState { diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index 4daa839..5049c0e 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -39,7 +39,7 @@ impl SeatHandler for WaylandState { self.seat.cursor_info_tx.send_modify(|c| match image { CursorImageStatus::Hidden => c.surface = None, CursorImageStatus::Surface(surface) => { - CoreSurface::add_to(&surface, || (), |_| ()); + CoreSurface::add_to(&surface); compositor::with_states(&surface, |data| { if let Some(core_surface) = data.data_map.get::>() { core_surface.set_material_offset(1); diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index fcea11f..825b93e 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -1,4 +1,4 @@ -use super::utils; +use super::utils::WlSurfaceExt; use crate::{ core::{delta::Delta, destroy_queue, registry::Registry}, nodes::{ @@ -50,41 +50,24 @@ pub struct CoreSurface { sk_tex: OnceCell>, sk_mat: OnceCell>, material_offset: Mutex>, - on_mapped: Mutex>, - on_commit: Mutex>, pub pending_material_applications: Registry, } impl CoreSurface { - pub fn add_to( - surface: &WlSurface, - on_mapped: impl Fn() + Send + Sync + 'static, - on_commit: impl Fn(u32) + Send + Sync + 'static, - ) { + pub fn add_to(surface: &WlSurface) { let core_surface = CORE_SURFACES.add(CoreSurface { weak_surface: surface.downgrade(), mapped_data: Mutex::new(None), sk_tex: OnceCell::new(), sk_mat: OnceCell::new(), material_offset: Mutex::new(Delta::new(0)), - on_mapped: Mutex::new(Box::new(on_mapped) as Box), - on_commit: Mutex::new(Box::new(on_commit) as Box), pending_material_applications: Registry::new(), }); - utils::insert_data_raw(surface, core_surface); - } - - pub fn commit(&self, count: u32) { - (*self.on_commit.lock())(count); + surface.insert_data(core_surface); } pub fn from_wl_surface(surf: &WlSurface) -> Option> { - utils::get_data(surf) - } - - pub fn decycle(&self) { - *self.on_mapped.lock() = Box::new(|| {}); - *self.on_commit.lock() = Box::new(|_| {}); + surf.get_data() } pub fn process(&self, renderer: &mut GlesRenderer) { @@ -128,14 +111,12 @@ impl CoreSurface { } let mut mapped_data = self.mapped_data.lock(); - let just_mapped = mapped_data.is_none(); self.with_states(|data| { let Some(renderer_surface_state) = data .data_map .get::() .map(std::sync::Mutex::lock) - .map(Result::ok) - .flatten() + .and_then(Result::ok) else { return; }; @@ -181,9 +162,6 @@ impl CoreSurface { *mapped_data = Some(new_mapped_data); }); drop(mapped_data); - if just_mapped { - (*self.on_mapped.lock())(); - } self.apply_surface_materials(); } diff --git a/src/wayland/utils.rs b/src/wayland/utils.rs index dbb5f1e..70711ce 100644 --- a/src/wayland/utils.rs +++ b/src/wayland/utils.rs @@ -1,14 +1,20 @@ use smithay::{reexports::wayland_server::protocol::wl_surface::WlSurface, wayland::compositor}; -use std::sync::Arc; -pub fn insert_data(wl_surface: &WlSurface, data: T) { - insert_data_raw(wl_surface, Arc::new(data)) +pub trait WlSurfaceExt { + fn insert_data(&self, data: T) -> bool; + fn get_data(&self) -> Option; + fn get_data_raw O>(&self, f: F) -> Option; } -pub fn insert_data_raw(wl_surface: &WlSurface, data: Arc) { - compositor::with_states(wl_surface, |d| { - d.data_map.insert_if_missing_threadsafe(move || data) - }); -} -pub fn get_data(wl_surface: &WlSurface) -> Option> { - compositor::with_states(wl_surface, |d| d.data_map.get::>().cloned()) +impl WlSurfaceExt for WlSurface { + fn insert_data(&self, data: T) -> bool { + compositor::with_states(self, |d| { + d.data_map.insert_if_missing_threadsafe(move || data) + }) + } + fn get_data(&self) -> Option { + compositor::with_states(self, |d| d.data_map.get::().cloned()) + } + fn get_data_raw O>(&self, f: F) -> Option { + compositor::with_states(self, |d| Some((f)(d.data_map.get::()?))) + } } diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 27e8cb7..213ff7a 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -2,7 +2,7 @@ use super::{ seat::{handle_cursor, SeatWrapper}, state::{ClientState, WaylandState}, surface::CoreSurface, - utils, + utils::WlSurfaceExt, }; use crate::nodes::{ drawable::model::ModelPart, @@ -29,7 +29,7 @@ use smithay::{ }, utils::{Logical, Rectangle, Serial}, wayland::{ - compositor, + compositor::{self, add_post_commit_hook}, shell::xdg::{ PopupSurface, PositionerState, ShellClient, SurfaceCachedState, ToplevelSurface, XdgShellHandler, XdgShellState, XdgToplevelSurfaceData, @@ -49,20 +49,12 @@ impl From> for Geometry { } fn surface_panel_item(wl_surface: &WlSurface) -> Option>> { - let panel_item = utils::get_data::>>(wl_surface) - .as_deref() + let panel_item = wl_surface + .get_data::>>() + .as_ref() .and_then(Weak::upgrade); if panel_item.is_none() { warn!("Couldn't get panel item"); - // println!("panel item not found at \n{}\n\n", { - // let backtrace = Backtrace::force_capture().to_string(); - // let mut split_backtrace = backtrace - // .split('\n') - // .map(|s| s.to_string()) - // .collect::>(); - // split_backtrace.resize(4, "".to_string()); - // split_backtrace.join("\n") - // }); } panel_item } @@ -76,6 +68,7 @@ impl XdgShellHandler for WaylandState { fn client_destroyed(&mut self, _client: ShellClient) {} fn new_toplevel(&mut self, toplevel: ToplevelSurface) { + toplevel.wl_surface().insert_data(SurfaceId::Toplevel(())); toplevel.with_pending_state(|s| { s.decoration_mode = Some(Mode::ServerSide); s.states.set(State::TiledTop); @@ -86,44 +79,50 @@ impl XdgShellHandler for WaylandState { s.states.unset(State::Fullscreen); }); toplevel.send_configure(); - utils::insert_data(toplevel.wl_surface(), SurfaceId::Toplevel); - utils::insert_data(toplevel.wl_surface(), Mutex::new(Vector2::from([0_u32; 2]))); - CoreSurface::add_to( + toplevel + .wl_surface() + .insert_data(Mutex::new(Vector2::from([0_u32; 2]))); + + CoreSurface::add_to(toplevel.wl_surface()); + add_post_commit_hook( toplevel.wl_surface(), - { - let toplevel = toplevel.clone(); - move || { - let wl_surface = toplevel.wl_surface().client().unwrap(); - let client_state = wl_surface.get_data::().unwrap(); - let (node, panel_item) = PanelItem::create( - Box::new(XdgBackend::create( - toplevel.clone(), - client_state.seat.clone(), - )), - client_state.pid, - ); - handle_cursor(&panel_item, panel_item.backend.seat.cursor_info_rx.clone()); - utils::insert_data(toplevel.wl_surface(), Arc::downgrade(&panel_item)); - utils::insert_data_raw(toplevel.wl_surface(), node); + |state: &mut WaylandState, _dh, surf| { + if surface_panel_item(surf).is_some() { + return; } + let client = surf.client().unwrap(); + let client_state = client.get_data::().unwrap(); + let Some(toplevel) = state + .xdg_shell + .toplevel_surfaces() + .iter() + .find(|s| s.wl_surface() == surf) + else { + return; + }; + let (node, panel_item) = PanelItem::create( + Box::new(XdgBackend::create( + toplevel.clone(), + client_state.seat.clone(), + )), + client_state.pid, + ); + handle_cursor(&panel_item, panel_item.backend.seat.cursor_info_rx.clone()); + surf.insert_data(Arc::downgrade(&panel_item)); + surf.insert_data(node); }, - { - let toplevel = toplevel.clone(); - move |_c| { - let Some(panel_item) = surface_panel_item(toplevel.wl_surface()) else { - // if the wayland toplevel isn't mapped, hammer it again with a configure until it cooperates - toplevel.send_configure(); - return; - }; - let Some(core_surface) = CoreSurface::from_wl_surface(toplevel.wl_surface()) - else { - return; - }; - let Some(old_size) = - utils::get_data::>>(toplevel.wl_surface()) - else { - return; - }; + ); + + add_post_commit_hook( + toplevel.wl_surface(), + |_state: &mut WaylandState, _dh, surf| { + let Some(panel_item) = surface_panel_item(surf) else { + return; + }; + let Some(core_surface) = CoreSurface::from_wl_surface(surf) else { + return; + }; + surf.get_data_raw::>, _, _>(|old_size| { let mut old_size = old_size.lock(); let Some(size) = core_surface.size() else { return; @@ -132,94 +131,79 @@ impl XdgShellHandler for WaylandState { panel_item.toplevel_size_changed(size); *old_size = size; } - } + }); }, ); } fn toplevel_destroyed(&mut self, toplevel: ToplevelSurface) { - if let Some(core_surface) = CoreSurface::from_wl_surface(toplevel.wl_surface()) { - core_surface.decycle(); - } let Some(panel_item) = surface_panel_item(toplevel.wl_surface()) else { return; }; panel_item.backend.seat.unfocus(toplevel.wl_surface(), self); panel_item.backend.toplevel.lock().take(); panel_item.backend.popups.lock().clear(); - panel_item.drop_toplevel(); - // println!( - // "Dropping toplevel resulted in {} references", - // Arc::strong_count(&panel_item) - // ); } fn app_id_changed(&mut self, toplevel: ToplevelSurface) { let Some(panel_item) = surface_panel_item(toplevel.wl_surface()) else { return; }; - panel_item.toplevel_app_id_changed(&compositor::with_states( - toplevel.wl_surface(), - |states| { - states - .data_map - .get::() - .unwrap() - .lock() - .unwrap() - .app_id - .clone() - .unwrap() - }, - )) + panel_item.toplevel_app_id_changed( + &toplevel + .wl_surface() + .get_data_raw::(|d| { + d.lock().unwrap().app_id.clone().unwrap() + }) + .unwrap_or_default(), + ) } fn title_changed(&mut self, toplevel: ToplevelSurface) { let Some(panel_item) = surface_panel_item(toplevel.wl_surface()) else { return; }; - panel_item.toplevel_title_changed(&compositor::with_states( - toplevel.wl_surface(), - |states| { - states - .data_map - .get::() - .unwrap() - .lock() - .unwrap() - .title - .clone() - .unwrap() - }, - )) + panel_item.toplevel_title_changed( + &toplevel + .wl_surface() + .get_data_raw::(|d| { + d.lock().unwrap().title.clone().unwrap() + }) + .unwrap_or_default(), + ) } fn new_popup(&mut self, popup: PopupSurface, positioner: PositionerState) { let uid = rand::thread_rng().gen_range(0..u64::MAX); + popup.wl_surface().insert_data(SurfaceId::Child(uid)); let Some(parent) = popup.get_parent_surface() else { return; }; + let _ = popup.send_configure(); + CoreSurface::add_to(popup.wl_surface()); + let Some(panel_item) = surface_panel_item(&parent) else { return; }; - let _ = popup.send_configure(); - utils::insert_data(popup.wl_surface(), SurfaceId::Child(uid)); - utils::insert_data(popup.wl_surface(), Arc::downgrade(&panel_item)); - CoreSurface::add_to( + let panel_item_weak = Arc::downgrade(&panel_item); + add_post_commit_hook( popup.wl_surface(), - { - let popup = popup.clone(); - move || { - panel_item.backend.new_popup(uid, popup.clone(), positioner); - } - }, - { - let popup = popup.clone(); - move |_c| { - if surface_panel_item(popup.wl_surface()).is_none() { - // if the popup toplevel isn't mapped, hammer it again with a configure until it cooperates - let _ = popup.send_configure(); - }; + move |state: &mut WaylandState, _dh, surf| { + if surface_panel_item(surf).is_some() { + return; } + surf.insert_data(panel_item_weak.clone()); + let Some(panel) = surface_panel_item(surf) else { + return; + }; + let Some(popup) = state + .xdg_shell + .popup_surfaces() + .iter() + .find(|p| p.wl_surface() == surf) + else { + return; + }; + panel.backend.new_popup(uid, popup.clone(), positioner); }, ); } @@ -232,26 +216,17 @@ impl XdgShellHandler for WaylandState { let Some(panel_item) = surface_panel_item(popup.wl_surface()) else { return; }; - let Some(SurfaceId::Child(uid)) = utils::get_data::(popup.wl_surface()) - .as_deref() - .cloned() - else { + let Some(SurfaceId::Child(uid)) = popup.wl_surface().get_data::() else { return; }; panel_item.backend.reposition_popup(uid, popup, positioner) } fn popup_destroyed(&mut self, popup: PopupSurface) { - if let Some(core_surface) = CoreSurface::from_wl_surface(popup.wl_surface()) { - core_surface.decycle(); - } let Some(panel_item) = surface_panel_item(popup.wl_surface()) else { return; }; - let Some(SurfaceId::Child(uid)) = utils::get_data::(popup.wl_surface()) - .as_deref() - .cloned() - else { + let Some(SurfaceId::Child(uid)) = popup.wl_surface().get_data::() else { return; }; panel_item.backend.seat.unfocus(popup.wl_surface(), self); @@ -375,11 +350,9 @@ impl XdgBackend { } fn child_data(&self, id: u64) -> Option { - let (popup, positioner) = self.popups.lock().get(&id)?.clone(); - let parent_surface = popup.get_parent_surface()?; - let parent = utils::get_data::(&parent_surface)? - .as_ref() - .clone(); + let (popup, positioner) = self.popups.lock().get(&id).unwrap().clone(); + let parent = popup.get_parent_surface().unwrap(); + let parent = parent.get_data::().unwrap(); Some(ChildInfo { id, parent, @@ -426,11 +399,7 @@ impl Backend for XdgBackend { .clone() }); let toplevel_cached_state = compositor::with_states(toplevel.wl_surface(), |states| { - states - .cached_state - .get::() - .current() - .clone() + *states.cached_state.get::().current() }); let toplevel_core_surface = CoreSurface::from_wl_surface(toplevel.wl_surface()).unwrap();