fix(wayland): properly destroy panel items
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
Reference in New Issue
Block a user