diff --git a/src/nodes/item.rs b/src/nodes/item.rs index f8ee6ca..dd6d526 100644 --- a/src/nodes/item.rs +++ b/src/nodes/item.rs @@ -92,7 +92,7 @@ pub struct Item { pub specialization: ItemType, } impl Item { - pub fn new( + pub fn add_to( node: &Arc, type_info: &'static TypeInfo, specialization: ItemType, @@ -109,6 +109,7 @@ impl Item { if let Some(ui) = type_info.ui.lock().upgrade() { ui.handle_create_item(&item); } + let _ = node.item.set(item.clone()); item } fn make_alias(&self, client: &Arc, parent: &str) -> (Arc, Arc) { @@ -173,9 +174,11 @@ pub struct EnvironmentItem { } impl EnvironmentItem { pub fn add_to(node: &Arc, path: String) { - let specialization = ItemType::Environment(EnvironmentItem { path }); - let item = Item::new(node, &ITEM_TYPE_INFO_ENVIRONMENT, specialization); - let _ = node.item.set(item); + Item::add_to( + node, + &ITEM_TYPE_INFO_ENVIRONMENT, + ItemType::Environment(EnvironmentItem { path }), + ); node.add_local_method("getPath", EnvironmentItem::get_path_flex); } diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs index e9546af..4b85cea 100644 --- a/src/wayland/compositor.rs +++ b/src/wayland/compositor.rs @@ -19,7 +19,10 @@ impl CompositorHandler for WaylandState { } fn commit(&mut self, dh: &DisplayHandle, surface: &WlSurface) { + // Let Smithay handle all the buffer maintenance on_commit_buffer_handler(surface); + + // Create/update textures from all buffers import_surface_tree(&mut self.renderer, surface, &self.log).unwrap(); compositor::with_states(surface, |data| { @@ -27,7 +30,7 @@ impl CompositorHandler for WaylandState { .data_map .get::() .map(|surface_states| surface_states.borrow().wl_buffer().is_some()) - .unwrap_or_default(); + .unwrap_or(false); if !mapped { return; @@ -46,15 +49,9 @@ impl CompositorHandler for WaylandState { .cloned() .map(SendWrapper::new); - if let ItemType::Panel(panel_item) = &data - .data_map - .get::>() - .unwrap() - .item - .get() - .unwrap() - .specialization - { + let panel_node = data.data_map.get::>().unwrap(); + let item = panel_node.item.get().unwrap(); + if let ItemType::Panel(panel_item) = &item.specialization { panel_item.resize(&data.data_map); } }); diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index e10e9be..39498ec 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -5,17 +5,20 @@ pub mod shaders; pub mod surface; pub mod xdg_decoration; pub mod xdg_shell; -use std::{ffi::c_void, sync::Arc}; +use self::{panel_item::PanelItem, seat::SeatDelegate}; +use crate::nodes::core::Node; use anyhow::{ensure, Result}; +use once_cell::sync::OnceCell; use parking_lot::Mutex; +use send_wrapper::SendWrapper; use slog::Logger; use smithay::{ backend::{egl::EGLContext, renderer::gles2::Gles2Renderer}, delegate_output, delegate_shm, desktop::utils::send_frames_surface_tree, reexports::wayland_server::{ - backend::{ClientData, ClientId, DisconnectReason}, + backend::{ClientData, ClientId, DisconnectReason, GlobalId}, protocol::wl_output::Subpixel, Display, DisplayHandle, ListeningSocket, }, @@ -28,14 +31,12 @@ use smithay::{ shm::{ShmHandler, ShmState}, }, }; +use std::sync::mpsc::{channel, Receiver, Sender}; +use std::{ffi::c_void, sync::Arc}; use stereokit as sk; use stereokit::StereoKit; use surface::CoreSurface; -use crate::nodes::core::Node; - -use self::{panel_item::PanelItem, seat::SeatDelegate}; - struct EGLRawHandles { display: *const c_void, config: *const c_void, @@ -71,9 +72,14 @@ impl ClientData for ClientState { } } +lazy_static::lazy_static! { + static ref GLOBAL_DESTROY_QUEUE_IN: OnceCell>> = OnceCell::new(); +} + pub struct WaylandState { pub log: slog::Logger, + global_destroy_queue: Receiver, pub display: Arc>>, pub display_handle: DisplayHandle, pub socket: ListeningSocket, @@ -129,9 +135,16 @@ impl WaylandState { output.change_current_state(None, None, Some(Integer(2)), None); // let data_device_state = DataDeviceState::new(&dh, log.clone()); + let (global_destroy_queue_in, global_destroy_queue) = channel(); + GLOBAL_DESTROY_QUEUE_IN + .set(SendWrapper::new(global_destroy_queue_in)) + .unwrap(); + println!("Init Wayland compositor"); Ok(WaylandState { log, + + global_destroy_queue, display: Arc::new(Mutex::new(display)), display_handle, socket, @@ -161,6 +174,11 @@ impl WaylandState { drop(display); drop(display_clone); + while let Ok(global_to_destroy) = self.global_destroy_queue.try_recv() { + self.display_handle + .remove_global::(global_to_destroy); + } + let time_ms = (sk.time_getf() * 1000.) as u32; self.xdg_shell_state.toplevel_surfaces(|surfs| { for surf in surfs.iter() { diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index d1ceb9e..d0d4b11 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -19,6 +19,7 @@ use parking_lot::Mutex; use smithay::{ backend::renderer::utils::RendererSurfaceStateUserData, reexports::wayland_server::{ + backend::ObjectId, protocol::{ wl_keyboard::KeyState, wl_pointer::{Axis, ButtonState}, @@ -33,7 +34,7 @@ use std::{ sync::{Arc, Weak}, }; -use super::{seat::SeatData, surface::CoreSurface, WaylandState}; +use super::{seat::SeatData, surface::CoreSurface, WaylandState, GLOBAL_DESTROY_QUEUE_IN}; lazy_static! { static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo { @@ -62,7 +63,8 @@ lazy_static! { pub struct PanelItem { node: Weak, pending_material_applications: Mutex, u32)>>, - pub toplevel_surface: WlSurface, + dh: DisplayHandle, + pub toplevel_surface_id: ObjectId, seat_data: SeatData, size: Mutex>, } @@ -80,8 +82,7 @@ impl PanelItem { )); Spatial::add_to(&node, None, Mat4::IDENTITY).unwrap(); - let seat_data = SeatData::new(toplevel_surface.client_id().unwrap()); - dh.create_global::(7, seat_data.clone()); + let seat_data = SeatData::new(dh, toplevel_surface.client_id().unwrap()); let size = data .get::() @@ -94,12 +95,12 @@ impl PanelItem { let specialization = ItemType::Panel(PanelItem { node: Arc::downgrade(&node), pending_material_applications: Mutex::new(Vec::new()), - toplevel_surface, + dh: dh.clone(), + toplevel_surface_id: toplevel_surface.id(), seat_data, size, }); - let item = Item::new(&node, &ITEM_TYPE_INFO_PANEL, specialization); - let _ = node.item.set(item); + Item::add_to(&node, &ITEM_TYPE_INFO_PANEL, specialization); node.add_local_signal( "applySurfaceMaterial", PanelItem::apply_surface_material_flex, @@ -120,14 +121,19 @@ impl PanelItem { node } + fn toplevel_surface(&self) -> WlSurface { + WlSurface::from_id(&self.dh, self.toplevel_surface_id.clone()).unwrap() + } + pub fn resize(&self, data: &UserDataMap) { if let Some(surface_states) = data.get::() { - if let Some(size) = surface_states.borrow().buffer_size() { + if let Some(size) = surface_states.borrow().surface_size() { + *self.size.lock() = size; let _ = self.node.upgrade().unwrap().send_remote_signal( "resize", &flexbuffer_from_vector_arguments(|vec| { - vec.push(size.w as u64); - vec.push(size.h as u64); + vec.push(size.w); + vec.push(size.h); }), ); } @@ -140,7 +146,6 @@ impl PanelItem { data: &[u8], ) -> Result<()> { let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; - let material_idx = flex_vec.idx(1).get_u64()?; let model_node = calling_client .scenegraph .get_node(flex_vec.idx(0).as_str()) @@ -149,6 +154,7 @@ impl PanelItem { .model .get() .ok_or_else(|| anyhow!("Node is not a model"))?; + let material_idx = flex_vec.idx(1).get_u64()?; if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { panel_item @@ -182,7 +188,7 @@ impl PanelItem { if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { if *panel_item.seat_data.pointer_active.lock() { if let Some(pointer) = panel_item.seat_data.pointer() { - pointer.leave(0, &panel_item.toplevel_surface); + pointer.leave(0, &panel_item.toplevel_surface()); *panel_item.seat_data.pointer_active.lock() = false; } } @@ -201,7 +207,7 @@ impl PanelItem { if *pointer_active { pointer.motion(0, x, y); } else { - pointer.enter(0, &panel_item.toplevel_surface, x, y); + pointer.enter(0, &panel_item.toplevel_surface(), x, y); *pointer_active = true; } pointer.frame(); @@ -275,9 +281,9 @@ impl PanelItem { let active = flexbuffers::Reader::get_root(data)?.get_bool()?; if *keyboard_active != active { if active { - keyboard.enter(0, &panel_item.toplevel_surface, vec![]); + keyboard.enter(0, &panel_item.toplevel_surface(), vec![]); } else { - keyboard.leave(0, &panel_item.toplevel_surface); + keyboard.leave(0, &panel_item.toplevel_surface()); } *keyboard_active = active; } @@ -341,6 +347,15 @@ impl ItemSpecialization for PanelItem { size_vec.push(size.h as u32); } } +impl Drop for PanelItem { + fn drop(&mut self) { + GLOBAL_DESTROY_QUEUE_IN + .get() + .unwrap() + .send(self.seat_data.global_id.get().cloned().unwrap()) + .unwrap(); + } +} pub fn register_panel_item_ui_flex( _node: &Node, diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index a3638c2..679954a 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -3,7 +3,7 @@ use nanoid::nanoid; use once_cell::sync::OnceCell; use parking_lot::Mutex; use smithay::reexports::wayland_server::{ - backend::ClientId, + backend::{ClientId, GlobalId}, delegate_dispatch, delegate_global_dispatch, protocol::{ wl_keyboard::{self, WlKeyboard}, @@ -21,15 +21,23 @@ pub struct SeatDelegate; #[derive(Clone)] pub struct SeatData(Arc); impl SeatData { - pub fn new(client: ClientId) -> Self { - SeatData(Arc::new(SeatDataInner { + pub fn new(dh: &DisplayHandle, client: ClientId) -> Self { + let seat_data = SeatData(Arc::new(SeatDataInner { client, + global_id: OnceCell::new(), pointer: OnceCell::new(), pointer_active: Mutex::new(false), keyboard: OnceCell::new(), keyboard_active: Mutex::new(false), touch: OnceCell::new(), - })) + })); + + seat_data + .global_id + .set(dh.create_global::(7, seat_data.clone())) + .unwrap(); + + seat_data } } impl Deref for SeatData { @@ -42,6 +50,7 @@ impl Deref for SeatData { pub struct SeatDataInner { client: ClientId, + pub global_id: OnceCell, pointer: OnceCell, pub pointer_active: Mutex, keyboard: OnceCell,