fix(wayland): properly destroy panel items

This commit is contained in:
Nova
2022-09-02 08:36:02 -04:00
parent a43b30da41
commit d92cbf01d1
5 changed files with 81 additions and 39 deletions

View File

@@ -92,7 +92,7 @@ pub struct Item {
pub specialization: ItemType, pub specialization: ItemType,
} }
impl Item { impl Item {
pub fn new( pub fn add_to(
node: &Arc<Node>, node: &Arc<Node>,
type_info: &'static TypeInfo, type_info: &'static TypeInfo,
specialization: ItemType, specialization: ItemType,
@@ -109,6 +109,7 @@ impl Item {
if let Some(ui) = type_info.ui.lock().upgrade() { if let Some(ui) = type_info.ui.lock().upgrade() {
ui.handle_create_item(&item); ui.handle_create_item(&item);
} }
let _ = node.item.set(item.clone());
item item
} }
fn make_alias(&self, client: &Arc<Client>, parent: &str) -> (Arc<Node>, Arc<Alias>) { fn make_alias(&self, client: &Arc<Client>, parent: &str) -> (Arc<Node>, Arc<Alias>) {
@@ -173,9 +174,11 @@ pub struct EnvironmentItem {
} }
impl EnvironmentItem { impl EnvironmentItem {
pub fn add_to(node: &Arc<Node>, path: String) { pub fn add_to(node: &Arc<Node>, path: String) {
let specialization = ItemType::Environment(EnvironmentItem { path }); Item::add_to(
let item = Item::new(node, &ITEM_TYPE_INFO_ENVIRONMENT, specialization); node,
let _ = node.item.set(item); &ITEM_TYPE_INFO_ENVIRONMENT,
ItemType::Environment(EnvironmentItem { path }),
);
node.add_local_method("getPath", EnvironmentItem::get_path_flex); node.add_local_method("getPath", EnvironmentItem::get_path_flex);
} }

View File

@@ -19,7 +19,10 @@ impl CompositorHandler for WaylandState {
} }
fn commit(&mut self, dh: &DisplayHandle, surface: &WlSurface) { fn commit(&mut self, dh: &DisplayHandle, surface: &WlSurface) {
// Let Smithay handle all the buffer maintenance
on_commit_buffer_handler(surface); on_commit_buffer_handler(surface);
// Create/update textures from all buffers
import_surface_tree(&mut self.renderer, surface, &self.log).unwrap(); import_surface_tree(&mut self.renderer, surface, &self.log).unwrap();
compositor::with_states(surface, |data| { compositor::with_states(surface, |data| {
@@ -27,7 +30,7 @@ impl CompositorHandler for WaylandState {
.data_map .data_map
.get::<RendererSurfaceStateUserData>() .get::<RendererSurfaceStateUserData>()
.map(|surface_states| surface_states.borrow().wl_buffer().is_some()) .map(|surface_states| surface_states.borrow().wl_buffer().is_some())
.unwrap_or_default(); .unwrap_or(false);
if !mapped { if !mapped {
return; return;
@@ -46,15 +49,9 @@ impl CompositorHandler for WaylandState {
.cloned() .cloned()
.map(SendWrapper::new); .map(SendWrapper::new);
if let ItemType::Panel(panel_item) = &data let panel_node = data.data_map.get::<Arc<Node>>().unwrap();
.data_map let item = panel_node.item.get().unwrap();
.get::<Arc<Node>>() if let ItemType::Panel(panel_item) = &item.specialization {
.unwrap()
.item
.get()
.unwrap()
.specialization
{
panel_item.resize(&data.data_map); panel_item.resize(&data.data_map);
} }
}); });

View File

@@ -5,17 +5,20 @@ pub mod shaders;
pub mod surface; pub mod surface;
pub mod xdg_decoration; pub mod xdg_decoration;
pub mod xdg_shell; 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 anyhow::{ensure, Result};
use once_cell::sync::OnceCell;
use parking_lot::Mutex; use parking_lot::Mutex;
use send_wrapper::SendWrapper;
use slog::Logger; use slog::Logger;
use smithay::{ use smithay::{
backend::{egl::EGLContext, renderer::gles2::Gles2Renderer}, backend::{egl::EGLContext, renderer::gles2::Gles2Renderer},
delegate_output, delegate_shm, delegate_output, delegate_shm,
desktop::utils::send_frames_surface_tree, desktop::utils::send_frames_surface_tree,
reexports::wayland_server::{ reexports::wayland_server::{
backend::{ClientData, ClientId, DisconnectReason}, backend::{ClientData, ClientId, DisconnectReason, GlobalId},
protocol::wl_output::Subpixel, protocol::wl_output::Subpixel,
Display, DisplayHandle, ListeningSocket, Display, DisplayHandle, ListeningSocket,
}, },
@@ -28,14 +31,12 @@ use smithay::{
shm::{ShmHandler, ShmState}, shm::{ShmHandler, ShmState},
}, },
}; };
use std::sync::mpsc::{channel, Receiver, Sender};
use std::{ffi::c_void, sync::Arc};
use stereokit as sk; use stereokit as sk;
use stereokit::StereoKit; use stereokit::StereoKit;
use surface::CoreSurface; use surface::CoreSurface;
use crate::nodes::core::Node;
use self::{panel_item::PanelItem, seat::SeatDelegate};
struct EGLRawHandles { struct EGLRawHandles {
display: *const c_void, display: *const c_void,
config: *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<SendWrapper<Sender<GlobalId>>> = OnceCell::new();
}
pub struct WaylandState { pub struct WaylandState {
pub log: slog::Logger, pub log: slog::Logger,
global_destroy_queue: Receiver<GlobalId>,
pub display: Arc<Mutex<Display<WaylandState>>>, pub display: Arc<Mutex<Display<WaylandState>>>,
pub display_handle: DisplayHandle, pub display_handle: DisplayHandle,
pub socket: ListeningSocket, pub socket: ListeningSocket,
@@ -129,9 +135,16 @@ impl WaylandState {
output.change_current_state(None, None, Some(Integer(2)), None); output.change_current_state(None, None, Some(Integer(2)), None);
// let data_device_state = DataDeviceState::new(&dh, log.clone()); // 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"); println!("Init Wayland compositor");
Ok(WaylandState { Ok(WaylandState {
log, log,
global_destroy_queue,
display: Arc::new(Mutex::new(display)), display: Arc::new(Mutex::new(display)),
display_handle, display_handle,
socket, socket,
@@ -161,6 +174,11 @@ impl WaylandState {
drop(display); drop(display);
drop(display_clone); drop(display_clone);
while let Ok(global_to_destroy) = self.global_destroy_queue.try_recv() {
self.display_handle
.remove_global::<WaylandState>(global_to_destroy);
}
let time_ms = (sk.time_getf() * 1000.) as u32; let time_ms = (sk.time_getf() * 1000.) as u32;
self.xdg_shell_state.toplevel_surfaces(|surfs| { self.xdg_shell_state.toplevel_surfaces(|surfs| {
for surf in surfs.iter() { for surf in surfs.iter() {

View File

@@ -19,6 +19,7 @@ use parking_lot::Mutex;
use smithay::{ use smithay::{
backend::renderer::utils::RendererSurfaceStateUserData, backend::renderer::utils::RendererSurfaceStateUserData,
reexports::wayland_server::{ reexports::wayland_server::{
backend::ObjectId,
protocol::{ protocol::{
wl_keyboard::KeyState, wl_keyboard::KeyState,
wl_pointer::{Axis, ButtonState}, wl_pointer::{Axis, ButtonState},
@@ -33,7 +34,7 @@ use std::{
sync::{Arc, Weak}, sync::{Arc, Weak},
}; };
use super::{seat::SeatData, surface::CoreSurface, WaylandState}; use super::{seat::SeatData, surface::CoreSurface, WaylandState, GLOBAL_DESTROY_QUEUE_IN};
lazy_static! { lazy_static! {
static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo { static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
@@ -62,7 +63,8 @@ lazy_static! {
pub struct PanelItem { pub struct PanelItem {
node: Weak<Node>, node: Weak<Node>,
pending_material_applications: Mutex<Vec<(Arc<Model>, u32)>>, pending_material_applications: Mutex<Vec<(Arc<Model>, u32)>>,
pub toplevel_surface: WlSurface, dh: DisplayHandle,
pub toplevel_surface_id: ObjectId,
seat_data: SeatData, seat_data: SeatData,
size: Mutex<Size<i32, Logical>>, size: Mutex<Size<i32, Logical>>,
} }
@@ -80,8 +82,7 @@ impl PanelItem {
)); ));
Spatial::add_to(&node, None, Mat4::IDENTITY).unwrap(); Spatial::add_to(&node, None, Mat4::IDENTITY).unwrap();
let seat_data = SeatData::new(toplevel_surface.client_id().unwrap()); let seat_data = SeatData::new(dh, toplevel_surface.client_id().unwrap());
dh.create_global::<WaylandState, _, _>(7, seat_data.clone());
let size = data let size = data
.get::<RendererSurfaceStateUserData>() .get::<RendererSurfaceStateUserData>()
@@ -94,12 +95,12 @@ impl PanelItem {
let specialization = ItemType::Panel(PanelItem { let specialization = ItemType::Panel(PanelItem {
node: Arc::downgrade(&node), node: Arc::downgrade(&node),
pending_material_applications: Mutex::new(Vec::new()), pending_material_applications: Mutex::new(Vec::new()),
toplevel_surface, dh: dh.clone(),
toplevel_surface_id: toplevel_surface.id(),
seat_data, seat_data,
size, size,
}); });
let item = Item::new(&node, &ITEM_TYPE_INFO_PANEL, specialization); Item::add_to(&node, &ITEM_TYPE_INFO_PANEL, specialization);
let _ = node.item.set(item);
node.add_local_signal( node.add_local_signal(
"applySurfaceMaterial", "applySurfaceMaterial",
PanelItem::apply_surface_material_flex, PanelItem::apply_surface_material_flex,
@@ -120,14 +121,19 @@ impl PanelItem {
node node
} }
fn toplevel_surface(&self) -> WlSurface {
WlSurface::from_id(&self.dh, self.toplevel_surface_id.clone()).unwrap()
}
pub fn resize(&self, data: &UserDataMap) { pub fn resize(&self, data: &UserDataMap) {
if let Some(surface_states) = data.get::<RendererSurfaceStateUserData>() { if let Some(surface_states) = data.get::<RendererSurfaceStateUserData>() {
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( let _ = self.node.upgrade().unwrap().send_remote_signal(
"resize", "resize",
&flexbuffer_from_vector_arguments(|vec| { &flexbuffer_from_vector_arguments(|vec| {
vec.push(size.w as u64); vec.push(size.w);
vec.push(size.h as u64); vec.push(size.h);
}), }),
); );
} }
@@ -140,7 +146,6 @@ impl PanelItem {
data: &[u8], data: &[u8],
) -> Result<()> { ) -> Result<()> {
let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?;
let material_idx = flex_vec.idx(1).get_u64()?;
let model_node = calling_client let model_node = calling_client
.scenegraph .scenegraph
.get_node(flex_vec.idx(0).as_str()) .get_node(flex_vec.idx(0).as_str())
@@ -149,6 +154,7 @@ impl PanelItem {
.model .model
.get() .get()
.ok_or_else(|| anyhow!("Node is not a model"))?; .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 { if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization {
panel_item panel_item
@@ -182,7 +188,7 @@ impl PanelItem {
if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization {
if *panel_item.seat_data.pointer_active.lock() { if *panel_item.seat_data.pointer_active.lock() {
if let Some(pointer) = panel_item.seat_data.pointer() { 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; *panel_item.seat_data.pointer_active.lock() = false;
} }
} }
@@ -201,7 +207,7 @@ impl PanelItem {
if *pointer_active { if *pointer_active {
pointer.motion(0, x, y); pointer.motion(0, x, y);
} else { } else {
pointer.enter(0, &panel_item.toplevel_surface, x, y); pointer.enter(0, &panel_item.toplevel_surface(), x, y);
*pointer_active = true; *pointer_active = true;
} }
pointer.frame(); pointer.frame();
@@ -275,9 +281,9 @@ impl PanelItem {
let active = flexbuffers::Reader::get_root(data)?.get_bool()?; let active = flexbuffers::Reader::get_root(data)?.get_bool()?;
if *keyboard_active != active { if *keyboard_active != active {
if active { if active {
keyboard.enter(0, &panel_item.toplevel_surface, vec![]); keyboard.enter(0, &panel_item.toplevel_surface(), vec![]);
} else { } else {
keyboard.leave(0, &panel_item.toplevel_surface); keyboard.leave(0, &panel_item.toplevel_surface());
} }
*keyboard_active = active; *keyboard_active = active;
} }
@@ -341,6 +347,15 @@ impl ItemSpecialization for PanelItem {
size_vec.push(size.h as u32); 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( pub fn register_panel_item_ui_flex(
_node: &Node, _node: &Node,

View File

@@ -3,7 +3,7 @@ use nanoid::nanoid;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use parking_lot::Mutex; use parking_lot::Mutex;
use smithay::reexports::wayland_server::{ use smithay::reexports::wayland_server::{
backend::ClientId, backend::{ClientId, GlobalId},
delegate_dispatch, delegate_global_dispatch, delegate_dispatch, delegate_global_dispatch,
protocol::{ protocol::{
wl_keyboard::{self, WlKeyboard}, wl_keyboard::{self, WlKeyboard},
@@ -21,15 +21,23 @@ pub struct SeatDelegate;
#[derive(Clone)] #[derive(Clone)]
pub struct SeatData(Arc<SeatDataInner>); pub struct SeatData(Arc<SeatDataInner>);
impl SeatData { impl SeatData {
pub fn new(client: ClientId) -> Self { pub fn new(dh: &DisplayHandle, client: ClientId) -> Self {
SeatData(Arc::new(SeatDataInner { let seat_data = SeatData(Arc::new(SeatDataInner {
client, client,
global_id: OnceCell::new(),
pointer: OnceCell::new(), pointer: OnceCell::new(),
pointer_active: Mutex::new(false), pointer_active: Mutex::new(false),
keyboard: OnceCell::new(), keyboard: OnceCell::new(),
keyboard_active: Mutex::new(false), keyboard_active: Mutex::new(false),
touch: OnceCell::new(), touch: OnceCell::new(),
})) }));
seat_data
.global_id
.set(dh.create_global::<WaylandState, _, _>(7, seat_data.clone()))
.unwrap();
seat_data
} }
} }
impl Deref for SeatData { impl Deref for SeatData {
@@ -42,6 +50,7 @@ impl Deref for SeatData {
pub struct SeatDataInner { pub struct SeatDataInner {
client: ClientId, client: ClientId,
pub global_id: OnceCell<GlobalId>,
pointer: OnceCell<WlPointer>, pointer: OnceCell<WlPointer>,
pub pointer_active: Mutex<bool>, pub pointer_active: Mutex<bool>,
keyboard: OnceCell<WlKeyboard>, keyboard: OnceCell<WlKeyboard>,