diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs index a141ecc..8b8deec 100644 --- a/src/wayland/compositor.rs +++ b/src/wayland/compositor.rs @@ -1,6 +1,5 @@ -use crate::wayland::surface::CoreSurface; - use super::state::{ClientState, WaylandState}; +use crate::wayland::surface::CoreSurface; use portable_atomic::{AtomicU32, Ordering}; use smithay::{ backend::renderer::utils::on_commit_buffer_handler, @@ -38,6 +37,34 @@ impl CompositorHandler for WaylandState { fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState { &client.get_data::().unwrap().compositor_state } + + // fn new_subsurface(&mut self, surface: &WlSurface, parent: &WlSurface) { + // let Some(panel_item) = surface_panel_item(parent) else { + // return; + // }; + // let uid = surface.insert_data(Arc::downgrade(&panel_item)); + // } + + // fn destroyed(&mut self, surface: &WlSurface) { + // let Some(panel_item) = surface_panel_item(surface) else { + // return; + // }; + // let Some((id, _)) = panel_item + // .backend + // .subsurfaces + // .lock() + // .iter() + // .find(|(_, d)| *d == surface) + // else { + // return; + // }; + // panel_item.backend.drop_subsurface(*id); + + // // self..lock().insert(id, (popup, positioner)); + + // let child_data = self.child_data(id).unwrap(); + // panel_item.create_child(id, &child_data); + // } } delegate_compositor!(WaylandState); diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index 825b93e..250538b 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -22,7 +22,6 @@ use smithay::{ desktop::utils::send_frames_surface_tree, output::Output, reexports::wayland_server::{self, protocol::wl_surface::WlSurface, Resource}, - wayland::compositor::{self, SurfaceData}, }; use std::{ffi::c_void, sync::Arc, time::Duration}; use stereokit_rust::{ @@ -99,70 +98,77 @@ impl CoreSurface { return; } - let mapped = compositor::with_states(&wl_surface, |data| { - data.data_map - .get::() - .map(|surface_states| surface_states.lock().unwrap().buffer().is_some()) - .unwrap_or(false) - }); + self.update_textures(renderer); + self.apply_surface_materials(); + } + + pub fn update_textures(&self, renderer: &mut GlesRenderer) { + let Some(wl_surface) = self.wl_surface() else { + return; + }; + let mapped = wl_surface + .get_data_raw::(|surface_states| { + surface_states.lock().unwrap().buffer().is_some() + }) + .unwrap_or(false); if !mapped { return; } let mut mapped_data = self.mapped_data.lock(); - self.with_states(|data| { - let Some(renderer_surface_state) = data - .data_map - .get::() - .map(std::sync::Mutex::lock) - .and_then(Result::ok) - else { - return; - }; - let Some(smithay_tex) = renderer_surface_state - .texture::(renderer.id()) - .cloned() - else { - return; - }; - let Some(sk_tex) = self.sk_tex.get() else { - return; - }; - let Some(sk_mat) = self.sk_mat.get() else { - return; - }; - sk_tex - .lock() - .0 - .set_native_surface( - smithay_tex.tex_id() as usize as *mut c_void, - TexType::ImageNomips, - smithay::backend::renderer::gles::ffi::RGBA8.into(), - smithay_tex.width() as i32, - smithay_tex.height() as i32, - 1, - false, - ) - .sample_mode(TexSample::Point) - .address_mode(TexAddress::Clamp); + let Some(smithay_tex) = wl_surface + .get_data_raw::(|surface_states| { + surface_states + .lock() + .unwrap() + .texture::(renderer.id()) + .cloned() + }) + .flatten() + else { + return; + }; - if let Some(material_offset) = self.material_offset.lock().delta() { - sk_mat.lock().0.queue_offset(*material_offset as i32); - } + let Some(sk_tex) = self.sk_tex.get() else { + return; + }; + let Some(sk_mat) = self.sk_mat.get() else { + return; + }; + sk_tex + .lock() + .0 + .set_native_surface( + smithay_tex.tex_id() as usize as *mut c_void, + TexType::ImageNomips, + smithay::backend::renderer::gles::ffi::RGBA8.into(), + smithay_tex.width() as i32, + smithay_tex.height() as i32, + 1, + false, + ) + .sample_mode(TexSample::Point) + .address_mode(TexAddress::Clamp); - let Some(surface_size) = renderer_surface_state.surface_size() else { - return; - }; - let new_mapped_data = CoreSurfaceData { - size: Vector2::from([surface_size.w as u32, surface_size.h as u32]), - wl_tex: Some(SendWrapper::new(smithay_tex)), - }; - *mapped_data = Some(new_mapped_data); - }); - drop(mapped_data); - self.apply_surface_materials(); + if let Some(material_offset) = self.material_offset.lock().delta() { + sk_mat.lock().0.queue_offset(*material_offset as i32); + } + + let Some(surface_size) = wl_surface + .get_data_raw::(|surface_states| { + surface_states.lock().unwrap().surface_size() + }) + .flatten() + else { + return; + }; + let new_mapped_data = CoreSurfaceData { + size: Vector2::from([surface_size.w as u32, surface_size.h as u32]), + wl_tex: Some(SendWrapper::new(smithay_tex)), + }; + *mapped_data = Some(new_mapped_data); } pub fn frame(&self, output: Output) { @@ -201,11 +207,6 @@ impl CoreSurface { self.weak_surface.upgrade().ok() } - pub fn with_states T>(&self, f: F) -> Option { - self.wl_surface() - .map(|wl_surface| compositor::with_states(&wl_surface, f)) - } - pub fn size(&self) -> Option> { self.mapped_data.lock().as_ref().map(|d| d.size) } diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 43fc36b..b0e1ff2 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -16,6 +16,7 @@ use parking_lot::Mutex; use rand::Rng; use rustc_hash::FxHashMap; use smithay::{ + backend::renderer::utils::RendererSurfaceStateUserData, delegate_xdg_shell, reexports::{ wayland_protocols::xdg::{ @@ -48,7 +49,7 @@ impl From> for Geometry { } } -fn surface_panel_item(wl_surface: &WlSurface) -> Option>> { +pub fn surface_panel_item(wl_surface: &WlSurface) -> Option>> { let panel_item = wl_surface .get_data::>>() .as_ref() @@ -119,14 +120,18 @@ impl XdgShellHandler for WaylandState { let Some(panel_item) = surface_panel_item(surf) else { return; }; - let Some(core_surface) = CoreSurface::from_wl_surface(surf) else { + let Some(size) = surf + .get_data_raw::(|surface_states| { + surface_states.lock().unwrap().surface_size() + }) + .flatten() + else { return; }; + let size = [size.w as u32, size.h as u32].into(); surf.get_data_raw::>, _, _>(|old_size| { let mut old_size = old_size.lock(); - let Some(size) = core_surface.size() else { - return; - }; + if *old_size != size { panel_item.toplevel_size_changed(size); *old_size = size; @@ -295,13 +300,15 @@ delegate_xdg_shell!(WaylandState); pub struct XdgBackend { toplevel: Mutex>, + pub subsurfaces: Mutex>, popups: Mutex>, - pub seat: Arc, + seat: Arc, } impl XdgBackend { pub fn create(toplevel: ToplevelSurface, seat: Arc) -> Self { XdgBackend { toplevel: Mutex::new(Some(toplevel)), + subsurfaces: Mutex::new(FxHashMap::default()), popups: Mutex::new(FxHashMap::default()), seat, } @@ -319,6 +326,24 @@ impl XdgBackend { surface_panel_item(self.toplevel.lock().clone()?.wl_surface()) } + pub fn new_subsurface(&self, id: u64, surface: WlSurface) { + let Some(panel_item) = self.panel_item() else { + return; + }; + + self.subsurfaces.lock().insert(id, surface); + + let child_data = self.child_data(id).unwrap(); + panel_item.create_child(id, &child_data); + } + pub fn drop_subsurface(&self, id: u64) { + let Some(panel_item) = self.panel_item() else { + return; + }; + panel_item.destroy_child(id); + self.subsurfaces.lock().remove(&id); + } + pub fn new_popup(&self, id: u64, popup: PopupSurface, positioner: PositionerState) { let Some(panel_item) = self.panel_item() else { return; @@ -347,6 +372,7 @@ impl XdgBackend { return; }; panel_item.destroy_child(id); + self.popups.lock().remove(&id); } fn child_data(&self, id: u64) -> Option {