feat: subsurface support
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -2357,7 +2357,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stardust-xr"
|
name = "stardust-xr"
|
||||||
version = "0.45.0"
|
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 = [
|
dependencies = [
|
||||||
"cluFlock",
|
"cluFlock",
|
||||||
"dirs",
|
"dirs",
|
||||||
@@ -2377,7 +2377,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stardust-xr-schemas"
|
name = "stardust-xr-schemas"
|
||||||
version = "1.5.3"
|
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 = [
|
dependencies = [
|
||||||
"flatbuffers",
|
"flatbuffers",
|
||||||
"flexbuffers",
|
"flexbuffers",
|
||||||
|
|||||||
@@ -1,11 +1,22 @@
|
|||||||
use super::state::{ClientState, WaylandState};
|
use super::{
|
||||||
use crate::wayland::surface::CoreSurface;
|
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 portable_atomic::{AtomicU32, Ordering};
|
||||||
|
use rand::Rng;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::utils::on_commit_buffer_handler,
|
backend::renderer::utils::{on_commit_buffer_handler, RendererSurfaceStateUserData},
|
||||||
delegate_compositor,
|
delegate_compositor,
|
||||||
reexports::wayland_server::{protocol::wl_surface::WlSurface, Client},
|
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 std::sync::Arc;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
@@ -38,33 +49,79 @@ impl CompositorHandler for WaylandState {
|
|||||||
&client.get_data::<ClientState>().unwrap().compositor_state
|
&client.get_data::<ClientState>().unwrap().compositor_state
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn new_subsurface(&mut self, surface: &WlSurface, parent: &WlSurface) {
|
fn new_subsurface(&mut self, surface: &WlSurface, parent: &WlSurface) {
|
||||||
// let Some(panel_item) = surface_panel_item(parent) else {
|
let id = rand::thread_rng().gen_range(0..u64::MAX);
|
||||||
// return;
|
surface.insert_data(SurfaceId::Child(id));
|
||||||
// };
|
CoreSurface::add_to(surface);
|
||||||
// let uid = surface.insert_data(Arc::downgrade(&panel_item));
|
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(parent) else {
|
||||||
// let Some(panel_item) = surface_panel_item(surface) else {
|
return;
|
||||||
// return;
|
};
|
||||||
// };
|
let panel_item_weak = Arc::downgrade(&panel_item);
|
||||||
// let Some((id, _)) = panel_item
|
add_post_commit_hook(surface, move |_: &mut WaylandState, _dh, surf| {
|
||||||
// .backend
|
if surface_panel_item(surf).is_some() {
|
||||||
// .subsurfaces
|
return;
|
||||||
// .lock()
|
}
|
||||||
// .iter()
|
surf.insert_data(panel_item_weak.clone());
|
||||||
// .find(|(_, d)| *d == surface)
|
|
||||||
// else {
|
|
||||||
// return;
|
|
||||||
// };
|
|
||||||
// panel_item.backend.drop_subsurface(*id);
|
|
||||||
|
|
||||||
// // 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();
|
add_post_commit_hook(surface, move |_: &mut WaylandState, _dh, surf| {
|
||||||
// panel_item.create_child(id, &child_data);
|
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);
|
delegate_compositor!(WaylandState);
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ impl XdgShellHandler for WaylandState {
|
|||||||
};
|
};
|
||||||
panel_item.backend.seat.unfocus(toplevel.wl_surface(), self);
|
panel_item.backend.seat.unfocus(toplevel.wl_surface(), self);
|
||||||
panel_item.backend.toplevel.lock().take();
|
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) {
|
fn app_id_changed(&mut self, toplevel: ToplevelSurface) {
|
||||||
let Some(panel_item) = surface_panel_item(toplevel.wl_surface()) else {
|
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) {
|
fn new_popup(&mut self, popup: PopupSurface, positioner: PositionerState) {
|
||||||
let uid = rand::thread_rng().gen_range(0..u64::MAX);
|
let id = rand::thread_rng().gen_range(0..u64::MAX);
|
||||||
popup.wl_surface().insert_data(SurfaceId::Child(uid));
|
popup.wl_surface().insert_data(SurfaceId::Child(id));
|
||||||
let Some(parent) = popup.get_parent_surface() else {
|
let Some(parent) = popup.get_parent_surface() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let _ = popup.send_configure();
|
let _ = popup.send_configure();
|
||||||
CoreSurface::add_to(popup.wl_surface());
|
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 {
|
let Some(panel_item) = surface_panel_item(&parent) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let panel_item_weak = Arc::downgrade(&panel_item);
|
let panel_item_weak = Arc::downgrade(&panel_item);
|
||||||
add_post_commit_hook(
|
add_post_commit_hook(
|
||||||
popup.wl_surface(),
|
popup.wl_surface(),
|
||||||
move |state: &mut WaylandState, _dh, surf| {
|
move |_: &mut WaylandState, _dh, surf| {
|
||||||
if surface_panel_item(surf).is_some() {
|
if surface_panel_item(surf).is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -200,15 +212,7 @@ impl XdgShellHandler for WaylandState {
|
|||||||
let Some(panel) = surface_panel_item(surf) else {
|
let Some(panel) = surface_panel_item(surf) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(popup) = state
|
panel.backend.new_child(surf);
|
||||||
.xdg_shell
|
|
||||||
.popup_surfaces()
|
|
||||||
.iter()
|
|
||||||
.find(|p| p.wl_surface() == surf)
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
panel.backend.new_popup(uid, popup.clone(), positioner);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -221,21 +225,26 @@ impl XdgShellHandler for WaylandState {
|
|||||||
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
||||||
return;
|
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) {
|
fn popup_destroyed(&mut self, popup: PopupSurface) {
|
||||||
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
||||||
return;
|
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.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) {}
|
fn grab(&mut self, _popup: PopupSurface, _seat: WlSeat, _serial: Serial) {}
|
||||||
@@ -298,97 +307,74 @@ impl XdgShellHandler for WaylandState {
|
|||||||
}
|
}
|
||||||
delegate_xdg_shell!(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 {
|
pub struct XdgBackend {
|
||||||
toplevel: Mutex<Option<ToplevelSurface>>,
|
toplevel: Mutex<Option<ToplevelSurface>>,
|
||||||
pub subsurfaces: Mutex<FxHashMap<u64, WlSurface>>,
|
pub children: Mutex<FxHashMap<u64, WlSurface>>,
|
||||||
popups: Mutex<FxHashMap<u64, (PopupSurface, PositionerState)>>,
|
// popups: Mutex<FxHashMap<u64, (PopupSurface, PositionerState)>>,
|
||||||
seat: Arc<SeatWrapper>,
|
seat: Arc<SeatWrapper>,
|
||||||
}
|
}
|
||||||
impl XdgBackend {
|
impl XdgBackend {
|
||||||
pub fn create(toplevel: ToplevelSurface, seat: Arc<SeatWrapper>) -> Self {
|
pub fn create(toplevel: ToplevelSurface, seat: Arc<SeatWrapper>) -> Self {
|
||||||
XdgBackend {
|
XdgBackend {
|
||||||
toplevel: Mutex::new(Some(toplevel)),
|
toplevel: Mutex::new(Some(toplevel)),
|
||||||
subsurfaces: Mutex::new(FxHashMap::default()),
|
children: Mutex::new(FxHashMap::default()),
|
||||||
popups: Mutex::new(FxHashMap::default()),
|
// popups: Mutex::new(FxHashMap::default()),
|
||||||
seat,
|
seat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn wl_surface_from_id(&self, id: &SurfaceId) -> Option<WlSurface> {
|
fn wl_surface_from_id(&self, id: &SurfaceId) -> Option<WlSurface> {
|
||||||
match id {
|
match id {
|
||||||
SurfaceId::Toplevel(_) => Some(self.toplevel.lock().clone()?.wl_surface().clone()),
|
SurfaceId::Toplevel(_) => Some(self.toplevel.lock().clone()?.wl_surface().clone()),
|
||||||
SurfaceId::Child(popup) => {
|
SurfaceId::Child(id) => self.children.lock().get(id).cloned(),
|
||||||
let popups = self.popups.lock();
|
|
||||||
Some(popups.get(popup)?.0.wl_surface().clone())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn panel_item(&self) -> Option<Arc<PanelItem<XdgBackend>>> {
|
fn panel_item(&self) -> Option<Arc<PanelItem<XdgBackend>>> {
|
||||||
surface_panel_item(self.toplevel.lock().clone()?.wl_surface())
|
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 {
|
let Some(panel_item) = self.panel_item() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let Some(child_info) = surface.get_child_info() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
self.subsurfaces.lock().insert(id, surface);
|
self.children.lock().insert(child_info.id, surface.clone());
|
||||||
|
panel_item.create_child(child_info.id, &child_info);
|
||||||
let child_data = self.child_data(id).unwrap();
|
|
||||||
panel_item.create_child(id, &child_data);
|
|
||||||
}
|
}
|
||||||
pub fn drop_subsurface(&self, id: u64) {
|
pub fn reposition_child(&self, surface: &WlSurface) {
|
||||||
let Some(panel_item) = self.panel_item() else {
|
let Some(panel_item) = self.panel_item() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
panel_item.destroy_child(id);
|
let Some(child_info) = surface.get_child_info() else {
|
||||||
self.subsurfaces.lock().remove(&id);
|
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 {
|
let Some(panel_item) = self.panel_item() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let Some(child_info) = surface.get_child_info() else {
|
||||||
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 {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(panel_item) = self.panel_item() else {
|
panel_item.destroy_child(child_info.id);
|
||||||
return;
|
self.children.lock().remove(&child_info.id);
|
||||||
};
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child_data(&self, id: u64) -> Option<ChildInfo> {
|
fn child_info(&self, id: u64) -> Option<ChildInfo> {
|
||||||
let (popup, positioner) = self.popups.lock().get(&id).unwrap().clone();
|
self.children.lock().get(&id).unwrap().get_child_info()
|
||||||
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(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Backend for XdgBackend {
|
impl Backend for XdgBackend {
|
||||||
@@ -487,10 +473,10 @@ impl Backend for XdgBackend {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let children = self
|
let children = self
|
||||||
.popups
|
.children
|
||||||
.lock()
|
.lock()
|
||||||
.keys()
|
.keys()
|
||||||
.map(|k| self.child_data(*k).unwrap())
|
.map(|k| self.child_info(*k).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(PanelItemInitData {
|
Ok(PanelItemInitData {
|
||||||
|
|||||||
Reference in New Issue
Block a user