From 56afecca74530d2d8b6bfc4884de92fa5d81db93 Mon Sep 17 00:00:00 2001 From: Nova Date: Tue, 20 Sep 2022 19:01:09 -0400 Subject: [PATCH] feat(wayland): resize --- src/wayland/compositor.rs | 7 +++- src/wayland/data_device.rs | 12 +++---- src/wayland/mod.rs | 6 +--- src/wayland/panel_item.rs | 69 +++++++++++++++++++++++++++----------- src/wayland/seat.rs | 7 +++- src/wayland/state.rs | 32 ++++++++++-------- src/wayland/surface.rs | 9 +++-- src/wayland/xdg_shell.rs | 42 ++++++++++++++++++++--- 8 files changed, 131 insertions(+), 53 deletions(-) diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs index b310081..66bc543 100644 --- a/src/wayland/compositor.rs +++ b/src/wayland/compositor.rs @@ -13,7 +13,12 @@ impl CompositorHandler for WaylandState { fn commit(&mut self, surface: &WlSurface) { compositor::with_states(surface, |data| { data.data_map.insert_if_missing_threadsafe(|| { - CoreSurface::new(&self.display, self.display_handle.clone(), surface) + CoreSurface::new( + &self.weak_ref.upgrade().unwrap(), + &self.display, + self.display_handle.clone(), + surface, + ) }) }); } diff --git a/src/wayland/data_device.rs b/src/wayland/data_device.rs index cd83f90..f10840e 100644 --- a/src/wayland/data_device.rs +++ b/src/wayland/data_device.rs @@ -64,9 +64,9 @@ impl Dispatch for WaylandState { _data_init: &mut DataInit<'_, WaylandState>, ) { match request { - Offer { mime_type: _ } => todo!(), - Destroy => todo!(), - SetActions { dnd_actions: _ } => todo!(), + Offer { mime_type: _ } => {} + Destroy => {} + SetActions { dnd_actions: _ } => {} _ => unreachable!(), } } @@ -88,12 +88,12 @@ impl Dispatch for WaylandState { origin: _, icon: _, serial: _, - } => todo!(), + } => {} SetSelection { source: _, serial: _, - } => todo!(), - Release => todo!(), + } => {} + Release => {} _ => unreachable!(), } } diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 278c6af..ed64df1 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -83,11 +83,7 @@ impl Wayland { let display_handle = display.handle(); let display = Arc::new(Mutex::new(display)); - let state = Arc::new(Mutex::new(WaylandState::new( - log.clone(), - display.clone(), - display_handle, - ))); + let state = WaylandState::new(log.clone(), display.clone(), display_handle); let (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8); GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap(); diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index e236cc3..7c359dd 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -19,6 +19,7 @@ use lazy_static::lazy_static; use nanoid::nanoid; use smithay::{ reexports::wayland_server::protocol::wl_pointer::{Axis, ButtonState}, + utils::Size, wayland::{compositor::SurfaceData, shell::xdg::XdgToplevelSurfaceData}, }; use stardust_xr::{ @@ -97,10 +98,11 @@ impl PanelItem { ); node.add_local_signal("keyboardDeactivate", PanelItem::keyboard_deactivate_flex); node.add_local_signal("keyboardKeyState", PanelItem::keyboard_key_state_flex); + node.add_local_signal("resize", PanelItem::resize_flex); node } - fn from_node(node: &Node) -> &PanelItem { + pub fn from_node(node: &Node) -> &PanelItem { match &node.item.get().unwrap().specialization { ItemType::Panel(panel_item) => panel_item, _ => unreachable!(), @@ -179,29 +181,23 @@ impl PanelItem { if let Some(panel_node) = surface_data.data_map.get::>() { let panel_item = PanelItem::from_node(panel_node); - core_surface.with_data(|core_surface_data| { - if core_surface_data.resized { - panel_item.resize(core_surface); - core_surface_data.resized = false; - } - }); + // core_surface.with_data(|core_surface_data| { + // panel_item.resize(); + // }); panel_item.set_cursor(); } } - pub fn resize(&self, core_surface: &CoreSurface) { - core_surface.with_data(|data| { - if data.resized { - let _ = self.node.upgrade().unwrap().send_remote_signal( - "resize", - &flexbuffer_from_vector_arguments(|vec| { - vec.push(data.size.x); - vec.push(data.size.y); - }), - ); - data.resized = false; - } + pub fn resize(&self) { + self.core_surface.upgrade().unwrap().with_data(|data| { + let _ = self.node.upgrade().unwrap().send_remote_signal( + "resize", + &flexbuffer_from_vector_arguments(|vec| { + vec.push(data.size.x); + vec.push(data.size.y); + }), + ); }); } @@ -461,6 +457,41 @@ impl PanelItem { Ok(()) } + + fn resize_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { + if let Some(core_surface) = panel_item.core_surface.upgrade() { + let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; + let w = flex_vec.index(0)?.get_u64()? as u32; + let h = flex_vec.index(1)?.get_u64()? as u32; + + let toplevel_surface = core_surface + .wayland_state() + .lock() + .xdg_shell_state + .toplevel_surfaces(|surfaces| { + surfaces + .iter() + .find(|surf| surf.wl_surface().clone() == core_surface.wl_surface()) + .map(|surf| surf.clone()) + }); + + if let Some(toplevel_surface) = toplevel_surface { + let mut size_set = false; + toplevel_surface.with_pending_state(|state| { + state.size = Some(Size::default()); + state.size.as_mut().unwrap().w = w as i32; + state.size.as_mut().unwrap().h = h as i32; + size_set = true; + }); + if size_set { + toplevel_surface.send_configure(); + } + } + } + } + Ok(()) + } } impl ItemSpecialization for PanelItem { fn serialize_start_data(&self, vec: &mut flexbuffers::VectorBuilder) { diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index 428e5ff..9206b44 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -213,7 +213,12 @@ impl Dispatch for SeatDelegate { if let Some(surface) = surface.as_ref() { compositor::with_states(surface, |data| { data.data_map.insert_if_missing_threadsafe(|| { - CoreSurface::new(&state.display, dh.clone(), surface) + CoreSurface::new( + &state.weak_ref.upgrade().unwrap(), + &state.display, + dh.clone(), + surface, + ) }); if !data.data_map.insert_if_missing_threadsafe(|| { Arc::new(Mutex::new(Cursor { diff --git a/src/wayland/state.rs b/src/wayland/state.rs index 6937548..4471cc9 100644 --- a/src/wayland/state.rs +++ b/src/wayland/state.rs @@ -25,7 +25,7 @@ use smithay::{ shm::{ShmHandler, ShmState}, }, }; -use std::sync::Arc; +use std::sync::{Arc, Weak}; pub struct ClientState; impl ClientData for ClientState { @@ -42,6 +42,7 @@ impl ClientData for ClientState { } pub struct WaylandState { + pub weak_ref: Weak>, pub display: Arc>>, pub display_handle: DisplayHandle, @@ -60,7 +61,7 @@ impl WaylandState { log: Logger, display: Arc>>, display_handle: DisplayHandle, - ) -> Self { + ) -> Arc> { let compositor_state = CompositorState::new::(&display_handle, log.clone()); let xdg_shell_state = XdgShellState::new::(&display_handle, log.clone()); let xdg_decoration_state = XdgDecorationState::new::(&display_handle, log.clone()); @@ -84,19 +85,22 @@ impl WaylandState { println!("Init Wayland compositor"); - WaylandState { - display, - display_handle, + Arc::new_cyclic(|weak| { + Mutex::new(WaylandState { + weak_ref: weak.clone(), + display, + display_handle, - compositor_state, - xdg_shell_state, - xdg_decoration_state, - kde_decoration_state, - shm_state, - output_manager_state, - output, - seats: FxHashMap::default(), - } + compositor_state, + xdg_shell_state, + xdg_decoration_state, + kde_decoration_state, + shm_state, + output_manager_state, + output, + seats: FxHashMap::default(), + }) + }) } pub fn new_client(&mut self, client: ClientId, dh: &DisplayHandle) { diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index 8b26e44..e668895 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -34,7 +34,6 @@ pub struct CoreSurfaceData { sk_tex: Option>, sk_mat: Option>>, pub size: Vector2, - pub resized: bool, } impl CoreSurfaceData { fn new(sk: &StereoKit) -> Self { @@ -53,7 +52,6 @@ impl CoreSurfaceData { sk_tex: Some(sk_tex), sk_mat: Some(sk_mat), size: Vector2::from([0, 0]), - resized: false, } } fn update_tex(&mut self, data: &RendererSurfaceStateUserData, renderer: &Gles2Renderer) { @@ -92,6 +90,7 @@ impl Drop for CoreSurfaceData { pub struct CoreSurface { display: Weak>>, + pub state: Weak>, pub dh: DisplayHandle, pub surface_id: ObjectId, pub mapped_data: Mutex>, @@ -100,12 +99,14 @@ pub struct CoreSurface { impl CoreSurface { pub fn new( + state: &Arc>, display: &Arc>>, dh: DisplayHandle, surface: &WlSurface, ) -> Arc { CORE_SURFACES.add(CoreSurface { display: Arc::downgrade(display), + state: Arc::downgrade(state), dh, surface_id: surface.id(), mapped_data: Mutex::new(None), @@ -181,6 +182,10 @@ impl CoreSurface { }); } + pub fn wayland_state(&self) -> Arc> { + self.state.upgrade().unwrap() + } + pub fn wl_surface(&self) -> WlSurface { WlSurface::from_id(&self.dh, self.surface_id.clone()).unwrap() } diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 1d914fc..45a1c21 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -1,4 +1,8 @@ -use super::state::WaylandState; +use std::sync::Arc; + +use crate::nodes::Node; + +use super::{panel_item::PanelItem, state::WaylandState, surface::CoreSurface}; use smithay::{ delegate_xdg_shell, reexports::{ @@ -6,11 +10,15 @@ use smithay::{ decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode, shell::server::xdg_toplevel::State, }, - wayland_server::protocol::wl_seat::WlSeat, + wayland_server::protocol::{wl_seat::WlSeat, wl_surface::WlSurface}, }, utils::Serial, - wayland::shell::xdg::{ - PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState, + wayland::{ + compositor, + shell::xdg::{ + Configure, PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, + XdgShellState, + }, }, }; @@ -29,9 +37,33 @@ impl XdgShellHandler for WaylandState { }); surface.send_configure(); } + fn ack_configure(&mut self, surface: WlSurface, configure: Configure) { + match configure { + Configure::Toplevel(config) => { + if let Some(size) = config.state.size { + compositor::with_states(&surface, |data| { + if let Some(panel_node) = data.data_map.get::>() { + if let Some(core_surface) = data.data_map.get::>() { + let panel_item = PanelItem::from_node(panel_node); + if core_surface + .with_data(|data| { + data.size.x = size.w as u32; + data.size.y = size.h as u32; + }) + .is_some() + { + panel_item.resize(); + } + } + } + }) + } + } + Configure::Popup(_) => (), + } + } fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {} - fn grab(&mut self, _surface: PopupSurface, _seat: WlSeat, _serial: Serial) {} } delegate_xdg_shell!(WaylandState);