feat: subsurface support
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -2357,7 +2357,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d"
|
||||
[[package]]
|
||||
name = "stardust-xr"
|
||||
version = "0.45.0"
|
||||
source = "git+https://github.com/StardustXR/core.git?branch=dev#060e3a91772b4a41178ad73f35a81eb22442641e"
|
||||
source = "git+https://github.com/StardustXR/core.git?branch=dev#52f75945be534b42006455395d89c91babbb1029"
|
||||
dependencies = [
|
||||
"cluFlock",
|
||||
"dirs",
|
||||
@@ -2377,7 +2377,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "stardust-xr-schemas"
|
||||
version = "1.5.3"
|
||||
source = "git+https://github.com/StardustXR/core.git?branch=dev#060e3a91772b4a41178ad73f35a81eb22442641e"
|
||||
source = "git+https://github.com/StardustXR/core.git?branch=dev#52f75945be534b42006455395d89c91babbb1029"
|
||||
dependencies = [
|
||||
"flatbuffers",
|
||||
"flexbuffers",
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
use super::state::{ClientState, WaylandState};
|
||||
use crate::wayland::surface::CoreSurface;
|
||||
use super::{
|
||||
state::{ClientState, WaylandState},
|
||||
utils::WlSurfaceExt,
|
||||
xdg_shell::{surface_panel_item, ChildInfoExt},
|
||||
};
|
||||
use crate::{
|
||||
nodes::items::panel::{ChildInfo, Geometry, SurfaceId},
|
||||
wayland::surface::CoreSurface,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use portable_atomic::{AtomicU32, Ordering};
|
||||
use rand::Rng;
|
||||
use smithay::{
|
||||
backend::renderer::utils::on_commit_buffer_handler,
|
||||
backend::renderer::utils::{on_commit_buffer_handler, RendererSurfaceStateUserData},
|
||||
delegate_compositor,
|
||||
reexports::wayland_server::{protocol::wl_surface::WlSurface, Client},
|
||||
wayland::compositor::{self, CompositorClientState, CompositorHandler, CompositorState},
|
||||
wayland::compositor::{
|
||||
self, add_post_commit_hook, CompositorClientState, CompositorHandler, CompositorState,
|
||||
},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use tracing::debug;
|
||||
@@ -38,33 +49,79 @@ impl CompositorHandler for WaylandState {
|
||||
&client.get_data::<ClientState>().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 new_subsurface(&mut self, surface: &WlSurface, parent: &WlSurface) {
|
||||
let id = rand::thread_rng().gen_range(0..u64::MAX);
|
||||
surface.insert_data(SurfaceId::Child(id));
|
||||
CoreSurface::add_to(surface);
|
||||
let Some(parent_surface_id) = parent.get_data::<SurfaceId>() else {
|
||||
return;
|
||||
};
|
||||
surface.insert_data(Mutex::new(ChildInfo {
|
||||
id,
|
||||
parent: parent_surface_id,
|
||||
geometry: Geometry {
|
||||
origin: [0; 2].into(),
|
||||
size: [256; 2].into(),
|
||||
},
|
||||
z_order: 1,
|
||||
}));
|
||||
|
||||
// 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);
|
||||
let Some(panel_item) = surface_panel_item(parent) else {
|
||||
return;
|
||||
};
|
||||
let panel_item_weak = Arc::downgrade(&panel_item);
|
||||
add_post_commit_hook(surface, move |_: &mut WaylandState, _dh, surf| {
|
||||
if surface_panel_item(surf).is_some() {
|
||||
return;
|
||||
}
|
||||
surf.insert_data(panel_item_weak.clone());
|
||||
|
||||
// // self..lock().insert(id, (popup, positioner));
|
||||
let Some(panel_item) = surface_panel_item(surf) else {
|
||||
return;
|
||||
};
|
||||
panel_item.backend.new_child(surf);
|
||||
});
|
||||
|
||||
// let child_data = self.child_data(id).unwrap();
|
||||
// panel_item.create_child(id, &child_data);
|
||||
// }
|
||||
add_post_commit_hook(surface, move |_: &mut WaylandState, _dh, surf| {
|
||||
let Some(view) = surf
|
||||
.get_data_raw::<RendererSurfaceStateUserData, _, _>(|s| s.lock().ok()?.view())
|
||||
.flatten()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let mut changed = false;
|
||||
surf.get_data_raw::<Mutex<ChildInfo>, _, _>(|c| {
|
||||
let mut info = c.lock();
|
||||
if info.geometry.origin.x != view.offset.x
|
||||
&& info.geometry.origin.y != view.offset.y
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
if info.geometry.size.x != view.dst.w as u32
|
||||
&& info.geometry.size.y != view.dst.h as u32
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
info.geometry.size = [view.dst.w as u32, view.dst.h as u32].into();
|
||||
});
|
||||
|
||||
let Some(panel_item) = surface_panel_item(surf) else {
|
||||
return;
|
||||
};
|
||||
if changed {
|
||||
panel_item.backend.reposition_child(surf);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn destroyed(&mut self, surface: &WlSurface) {
|
||||
let Some(panel_item) = surface_panel_item(surface) else {
|
||||
return;
|
||||
};
|
||||
if surface.get_child_info().is_some() {
|
||||
panel_item.backend.drop_child(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate_compositor!(WaylandState);
|
||||
|
||||
@@ -146,7 +146,7 @@ impl XdgShellHandler for WaylandState {
|
||||
};
|
||||
panel_item.backend.seat.unfocus(toplevel.wl_surface(), self);
|
||||
panel_item.backend.toplevel.lock().take();
|
||||
panel_item.backend.popups.lock().clear();
|
||||
panel_item.backend.children.lock().clear();
|
||||
}
|
||||
fn app_id_changed(&mut self, toplevel: ToplevelSurface) {
|
||||
let Some(panel_item) = surface_panel_item(toplevel.wl_surface()) else {
|
||||
@@ -178,21 +178,33 @@ impl XdgShellHandler for WaylandState {
|
||||
}
|
||||
|
||||
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 id = rand::thread_rng().gen_range(0..u64::MAX);
|
||||
popup.wl_surface().insert_data(SurfaceId::Child(id));
|
||||
let Some(parent) = popup.get_parent_surface() else {
|
||||
return;
|
||||
};
|
||||
let _ = popup.send_configure();
|
||||
CoreSurface::add_to(popup.wl_surface());
|
||||
|
||||
popup.wl_surface().insert_data(Mutex::new(ChildInfo {
|
||||
id,
|
||||
parent: parent.get_data::<SurfaceId>().unwrap(),
|
||||
geometry: positioner
|
||||
.get_unconstrained_geometry(Rectangle {
|
||||
loc: (-100000, -100000).into(),
|
||||
size: (200000, 200000).into(),
|
||||
})
|
||||
.into(),
|
||||
z_order: 1,
|
||||
}));
|
||||
|
||||
let Some(panel_item) = surface_panel_item(&parent) else {
|
||||
return;
|
||||
};
|
||||
let panel_item_weak = Arc::downgrade(&panel_item);
|
||||
add_post_commit_hook(
|
||||
popup.wl_surface(),
|
||||
move |state: &mut WaylandState, _dh, surf| {
|
||||
move |_: &mut WaylandState, _dh, surf| {
|
||||
if surface_panel_item(surf).is_some() {
|
||||
return;
|
||||
}
|
||||
@@ -200,15 +212,7 @@ impl XdgShellHandler for WaylandState {
|
||||
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);
|
||||
panel.backend.new_child(surf);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -221,21 +225,26 @@ impl XdgShellHandler for WaylandState {
|
||||
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
||||
return;
|
||||
};
|
||||
let Some(SurfaceId::Child(uid)) = popup.wl_surface().get_data::<SurfaceId>() else {
|
||||
return;
|
||||
};
|
||||
|
||||
panel_item.backend.reposition_popup(uid, popup, positioner)
|
||||
popup
|
||||
.wl_surface()
|
||||
.get_data_raw::<Mutex<ChildInfo>, _, _>(|ci| {
|
||||
ci.lock().geometry = positioner
|
||||
.get_unconstrained_geometry(Rectangle {
|
||||
loc: (-100000, -100000).into(),
|
||||
size: (200000, 200000).into(),
|
||||
})
|
||||
.into()
|
||||
});
|
||||
|
||||
panel_item.backend.reposition_child(popup.wl_surface());
|
||||
}
|
||||
fn popup_destroyed(&mut self, popup: PopupSurface) {
|
||||
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
||||
return;
|
||||
};
|
||||
let Some(SurfaceId::Child(uid)) = popup.wl_surface().get_data::<SurfaceId>() else {
|
||||
return;
|
||||
};
|
||||
panel_item.backend.seat.unfocus(popup.wl_surface(), self);
|
||||
panel_item.backend.drop_popup(uid);
|
||||
panel_item.backend.drop_child(popup.wl_surface());
|
||||
}
|
||||
|
||||
fn grab(&mut self, _popup: PopupSurface, _seat: WlSeat, _serial: Serial) {}
|
||||
@@ -298,97 +307,74 @@ impl XdgShellHandler for WaylandState {
|
||||
}
|
||||
delegate_xdg_shell!(WaylandState);
|
||||
|
||||
pub trait ChildInfoExt {
|
||||
fn get_child_info(&self) -> Option<ChildInfo>;
|
||||
}
|
||||
impl ChildInfoExt for WlSurface {
|
||||
fn get_child_info(&self) -> Option<ChildInfo> {
|
||||
self.get_data_raw::<Mutex<ChildInfo>, _, _>(|c| c.lock().clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct XdgBackend {
|
||||
toplevel: Mutex<Option<ToplevelSurface>>,
|
||||
pub subsurfaces: Mutex<FxHashMap<u64, WlSurface>>,
|
||||
popups: Mutex<FxHashMap<u64, (PopupSurface, PositionerState)>>,
|
||||
pub children: Mutex<FxHashMap<u64, WlSurface>>,
|
||||
// popups: Mutex<FxHashMap<u64, (PopupSurface, PositionerState)>>,
|
||||
seat: Arc<SeatWrapper>,
|
||||
}
|
||||
impl XdgBackend {
|
||||
pub fn create(toplevel: ToplevelSurface, seat: Arc<SeatWrapper>) -> Self {
|
||||
XdgBackend {
|
||||
toplevel: Mutex::new(Some(toplevel)),
|
||||
subsurfaces: Mutex::new(FxHashMap::default()),
|
||||
popups: Mutex::new(FxHashMap::default()),
|
||||
children: Mutex::new(FxHashMap::default()),
|
||||
// popups: Mutex::new(FxHashMap::default()),
|
||||
seat,
|
||||
}
|
||||
}
|
||||
fn wl_surface_from_id(&self, id: &SurfaceId) -> Option<WlSurface> {
|
||||
match id {
|
||||
SurfaceId::Toplevel(_) => Some(self.toplevel.lock().clone()?.wl_surface().clone()),
|
||||
SurfaceId::Child(popup) => {
|
||||
let popups = self.popups.lock();
|
||||
Some(popups.get(popup)?.0.wl_surface().clone())
|
||||
}
|
||||
SurfaceId::Child(id) => self.children.lock().get(id).cloned(),
|
||||
}
|
||||
}
|
||||
fn panel_item(&self) -> Option<Arc<PanelItem<XdgBackend>>> {
|
||||
surface_panel_item(self.toplevel.lock().clone()?.wl_surface())
|
||||
}
|
||||
|
||||
pub fn new_subsurface(&self, id: u64, surface: WlSurface) {
|
||||
pub fn new_child(&self, surface: &WlSurface) {
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
return;
|
||||
};
|
||||
let Some(child_info) = surface.get_child_info() else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.subsurfaces.lock().insert(id, surface);
|
||||
|
||||
let child_data = self.child_data(id).unwrap();
|
||||
panel_item.create_child(id, &child_data);
|
||||
self.children.lock().insert(child_info.id, surface.clone());
|
||||
panel_item.create_child(child_info.id, &child_info);
|
||||
}
|
||||
pub fn drop_subsurface(&self, id: u64) {
|
||||
pub fn reposition_child(&self, surface: &WlSurface) {
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
return;
|
||||
};
|
||||
panel_item.destroy_child(id);
|
||||
self.subsurfaces.lock().remove(&id);
|
||||
}
|
||||
let Some(child_info) = surface.get_child_info() else {
|
||||
return;
|
||||
};
|
||||
|
||||
pub fn new_popup(&self, id: u64, popup: PopupSurface, positioner: PositionerState) {
|
||||
panel_item.reposition_child(child_info.id, &child_info.geometry);
|
||||
}
|
||||
pub fn drop_child(&self, surface: &WlSurface) {
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.popups.lock().insert(id, (popup, positioner));
|
||||
|
||||
let child_data = self.child_data(id).unwrap();
|
||||
panel_item.create_child(id, &child_data);
|
||||
}
|
||||
pub fn reposition_popup(&self, id: u64, _popup: PopupSurface, positioner: PositionerState) {
|
||||
let mut popups = self.popups.lock();
|
||||
let Some((_, old_positioner)) = popups.get_mut(&id) else {
|
||||
let Some(child_info) = surface.get_child_info() else {
|
||||
return;
|
||||
};
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
return;
|
||||
};
|
||||
let geometry = positioner.get_geometry();
|
||||
|
||||
*old_positioner = positioner;
|
||||
panel_item.reposition_child(id, &geometry.into());
|
||||
}
|
||||
pub fn drop_popup(&self, id: u64) {
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
return;
|
||||
};
|
||||
panel_item.destroy_child(id);
|
||||
self.popups.lock().remove(&id);
|
||||
panel_item.destroy_child(child_info.id);
|
||||
self.children.lock().remove(&child_info.id);
|
||||
}
|
||||
|
||||
fn child_data(&self, id: u64) -> Option<ChildInfo> {
|
||||
let (popup, positioner) = self.popups.lock().get(&id).unwrap().clone();
|
||||
let parent = popup.get_parent_surface().unwrap();
|
||||
let parent = parent.get_data::<SurfaceId>().unwrap();
|
||||
Some(ChildInfo {
|
||||
id,
|
||||
parent,
|
||||
geometry: positioner
|
||||
.get_unconstrained_geometry(Rectangle {
|
||||
loc: (-100000, -100000).into(),
|
||||
size: (200000, 200000).into(),
|
||||
})
|
||||
.into(),
|
||||
})
|
||||
fn child_info(&self, id: u64) -> Option<ChildInfo> {
|
||||
self.children.lock().get(&id).unwrap().get_child_info()
|
||||
}
|
||||
}
|
||||
impl Backend for XdgBackend {
|
||||
@@ -487,10 +473,10 @@ impl Backend for XdgBackend {
|
||||
};
|
||||
|
||||
let children = self
|
||||
.popups
|
||||
.children
|
||||
.lock()
|
||||
.keys()
|
||||
.map(|k| self.child_data(*k).unwrap())
|
||||
.map(|k| self.child_info(*k).unwrap())
|
||||
.collect();
|
||||
|
||||
Ok(PanelItemInitData {
|
||||
|
||||
Reference in New Issue
Block a user