From dd6c9fee7cec294cc3b86a044c160dde9f110d8e Mon Sep 17 00:00:00 2001 From: Nova Date: Wed, 31 Aug 2022 17:22:13 -0400 Subject: [PATCH] feat(panel): seats --- src/nodes/item.rs | 32 +++++- src/wayland/compositor.rs | 58 +++++++--- src/wayland/mod.rs | 23 ++-- src/wayland/panel_item.rs | 234 ++++++++++++++++++++++++++++++++++++-- src/wayland/seat.rs | 172 ++++++++++++++++++++++++++++ src/wayland/xdg_shell.rs | 54 ++++----- 6 files changed, 502 insertions(+), 71 deletions(-) create mode 100644 src/wayland/seat.rs diff --git a/src/nodes/item.rs b/src/nodes/item.rs index 65c304b..d5a3cbd 100644 --- a/src/nodes/item.rs +++ b/src/nodes/item.rs @@ -7,8 +7,10 @@ use crate::core::registry::Registry; use crate::wayland::panel_item::{register_panel_item_ui_flex, PanelItem}; use anyhow::{anyhow, ensure, Result}; use lazy_static::lazy_static; +use libstardustxr::flex::flexbuffer_from_vector_arguments; use nanoid::nanoid; use parking_lot::Mutex; +use std::ops::Deref; use std::sync::{Arc, Weak}; lazy_static! { @@ -141,10 +143,24 @@ impl Drop for Item { } } +pub trait ItemSpecialization { + fn serialize_start_data(&self, vec: &mut flexbuffers::VectorBuilder); +} + pub enum ItemType { Environment(EnvironmentItem), Panel(PanelItem), } +impl Deref for ItemType { + type Target = dyn ItemSpecialization; + + fn deref(&self) -> &Self::Target { + match self { + ItemType::Environment(item) => item, + ItemType::Panel(item) => item, + } + } +} pub struct EnvironmentItem { path: String, @@ -169,6 +185,11 @@ impl EnvironmentItem { Ok(flexbuffers::singleton(path?.as_str())) } } +impl ItemSpecialization for EnvironmentItem { + fn serialize_start_data(&self, vec: &mut flexbuffers::VectorBuilder) { + vec.push(self.path.as_str()); + } +} pub struct ItemUI { node: Weak, @@ -208,7 +229,16 @@ impl ItemUI { let (alias_node, _) = item.make_alias(&node.get_client(), &(node.get_path().to_string() + "/item")); self.aliases.add(Arc::downgrade(&alias_node)); - self.send_state("create", item.uid.as_str()); + + let _ = node.send_remote_signal( + "create", + &flexbuffer_from_vector_arguments(|vec| { + vec.push(item.uid.as_str()); + let mut start_data_vec = vec.start_vector(); + item.specialization + .serialize_start_data(&mut start_data_vec); + }), + ); } fn handle_destroy_item(&self, item: &Item) { self.send_state("destroy", item.uid.as_str()); diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs index 90cde6f..e9546af 100644 --- a/src/wayland/compositor.rs +++ b/src/wayland/compositor.rs @@ -1,35 +1,61 @@ -use super::{surface::CoreSurface, WaylandState}; +use std::sync::Arc; + +use crate::nodes::{core::Node, item::ItemType}; + +use super::{panel_item::PanelItem, surface::CoreSurface, WaylandState}; use send_wrapper::SendWrapper; use smithay::{ backend::renderer::utils::{ import_surface_tree, on_commit_buffer_handler, RendererSurfaceStateUserData, }, delegate_compositor, - wayland::compositor::{self, CompositorHandler}, + reexports::wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle}, + wayland::compositor::{self, CompositorHandler, CompositorState}, }; impl CompositorHandler for WaylandState { - fn compositor_state(&mut self) -> &mut smithay::wayland::compositor::CompositorState { + fn compositor_state(&mut self) -> &mut CompositorState { &mut self.compositor_state } - fn commit( - &mut self, - _dh: &smithay::reexports::wayland_server::DisplayHandle, - surface: &smithay::reexports::wayland_server::protocol::wl_surface::WlSurface, - ) { + fn commit(&mut self, dh: &DisplayHandle, surface: &WlSurface) { on_commit_buffer_handler(surface); import_surface_tree(&mut self.renderer, surface, &self.log).unwrap(); compositor::with_states(surface, |data| { - if let Some(surface_states) = data.data_map.get::() { - if let Some(core_surface) = data.data_map.get::() { - *core_surface.wl_tex.lock() = surface_states - .borrow() - .texture(&self.renderer) - .cloned() - .map(SendWrapper::new); - } + let mapped = data + .data_map + .get::() + .map(|surface_states| surface_states.borrow().wl_buffer().is_some()) + .unwrap_or_default(); + + if !mapped { + return; + } + + data.data_map.insert_if_missing_threadsafe(CoreSurface::new); + data.data_map.insert_if_missing_threadsafe(|| { + PanelItem::create(dh, &data.data_map, surface.clone()) + }); + + let surface_states = data.data_map.get::().unwrap(); + let core_surface = data.data_map.get::().unwrap(); + *core_surface.wl_tex.lock() = surface_states + .borrow() + .texture(&self.renderer) + .cloned() + .map(SendWrapper::new); + + if let ItemType::Panel(panel_item) = &data + .data_map + .get::>() + .unwrap() + .item + .get() + .unwrap() + .specialization + { + panel_item.resize(&data.data_map); } }); } diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 0ab650c..cd016ac 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -1,5 +1,6 @@ pub mod compositor; pub mod panel_item; +pub mod seat; pub mod shaders; pub mod surface; pub mod xdg_decoration; @@ -23,7 +24,6 @@ use smithay::{ buffer::BufferHandler, compositor::{with_states, CompositorState}, output::{Output, OutputManagerState, Scale::Integer}, - seat::SeatState, shell::xdg::{decoration::XdgDecorationState, XdgShellState}, shm::{ShmHandler, ShmState}, }, @@ -32,6 +32,8 @@ use stereokit as sk; use stereokit::StereoKit; use surface::CoreSurface; +use self::seat::SeatDelegate; + struct EGLRawHandles { display: *const c_void, config: *const c_void, @@ -80,7 +82,7 @@ pub struct WaylandState { pub shm_state: ShmState, pub output_manager_state: OutputManagerState, pub output: Output, - pub seat_state: SeatState, + pub seat_state: SeatDelegate, // pub data_device_state: DataDeviceState, } @@ -123,7 +125,6 @@ impl WaylandState { ); let _global = output.create_global::(&display_handle); output.change_current_state(None, None, Some(Integer(2)), None); - let seat_state = SeatState::new(); // let data_device_state = DataDeviceState::new(&dh, log.clone()); println!("Init Wayland compositor"); @@ -139,7 +140,7 @@ impl WaylandState { shm_state, output_manager_state, output, - seat_state, + seat_state: SeatDelegate, // data_device_state, }) } @@ -162,17 +163,9 @@ impl WaylandState { self.xdg_shell_state.toplevel_surfaces(|surfs| { for surf in surfs.iter() { with_states(surf.wl_surface(), |data| { - let core_surface = data.data_map.get::().unwrap(); - core_surface.update_tex(sk); - }); - send_frames_surface_tree(surf.wl_surface(), time_ms); - } - }); - self.xdg_shell_state.popup_surfaces(|surfs| { - for surf in surfs.iter() { - with_states(surf.wl_surface(), |data| { - let core_surface = data.data_map.get::().unwrap(); - core_surface.update_tex(sk); + if let Some(core_surface) = data.data_map.get::() { + core_surface.update_tex(sk); + } }); send_frames_surface_tree(surf.wl_surface(), time_ms); } diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index 1f8d269..d05e5d3 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -5,18 +5,35 @@ use crate::{ }, nodes::{ core::Node, - item::{register_item_ui_flex, Item, ItemType, TypeInfo}, + item::{register_item_ui_flex, Item, ItemSpecialization, ItemType, TypeInfo}, spatial::Spatial, }, }; use anyhow::{anyhow, Result}; use glam::Mat4; use lazy_static::lazy_static; +use libstardustxr::{flex::flexbuffer_from_vector_arguments, flex_to_vec2}; use nanoid::nanoid; -use smithay::{reexports::wayland_server::protocol::wl_surface::WlSurface, wayland::compositor}; -use std::sync::Arc; +use parking_lot::Mutex; +use smithay::{ + backend::renderer::utils::RendererSurfaceStateUserData, + reexports::wayland_server::{ + protocol::{ + wl_keyboard::KeyState, + wl_pointer::{Axis, ButtonState}, + wl_surface::WlSurface, + }, + DisplayHandle, Resource, + }, + utils::{user_data::UserDataMap, Logical, Size}, + wayland::compositor, +}; +use std::{ + convert::TryInto, + sync::{Arc, Weak}, +}; -use super::surface::CoreSurface; +use super::{seat::SeatData, surface::CoreSurface, WaylandState}; lazy_static! { static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo { @@ -48,24 +65,68 @@ lazy_static! { } pub struct PanelItem { - toplevel_surface: WlSurface, + node: Weak, + pub toplevel_surface: WlSurface, + seat_data: SeatData, + size: Mutex>, } impl PanelItem { - pub fn create(toplevel_surface: WlSurface) -> Arc { + pub fn create( + dh: &DisplayHandle, + data: &UserDataMap, + toplevel_surface: WlSurface, + ) -> Arc { let node = Node::create(&INTERNAL_CLIENT, "/item/panel/item", &nanoid!(), true) .add_to_scenegraph(); Spatial::add_to(&node, None, Mat4::IDENTITY).unwrap(); - let specialization = ItemType::Panel(PanelItem { toplevel_surface }); + let seat_data = SeatData::new(toplevel_surface.client_id().unwrap()); + dh.create_global::(7, seat_data.clone()); + + let size = data + .get::() + .unwrap() + .borrow() + .surface_size() + .map(Mutex::new) + .unwrap(); + + let specialization = ItemType::Panel(PanelItem { + node: Arc::downgrade(&node), + toplevel_surface, + seat_data, + size, + }); let item = ITEM_TYPE_INFO_PANEL .items .add(Item::new(&node, &ITEM_TYPE_INFO_PANEL, specialization)); let _ = node.item.set(item); node.add_local_signal("applySurfaceMaterial", PanelItem::apply_surface_material); + node.add_local_signal("pointerDeactivate", PanelItem::pointer_deactivate); + node.add_local_signal("pointerScroll", PanelItem::pointer_scroll); + node.add_local_signal("pointerButton", PanelItem::pointer_button); + node.add_local_signal("pointerMotion", PanelItem::pointer_motion); + node.add_local_signal("keyboardSetActive", PanelItem::keyboard_set_active); + node.add_local_signal("keyboardSetKeyState", PanelItem::keyboard_set_key_state); + node.add_local_signal("keyboardSetModifiers", PanelItem::keyboard_set_modifiers); node } + pub fn resize(&self, data: &UserDataMap) { + if let Some(surface_states) = data.get::() { + if let Some(size) = surface_states.borrow().buffer_size() { + let _ = self.node.upgrade().unwrap().send_remote_signal( + "resize", + &flexbuffer_from_vector_arguments(|vec| { + vec.push(size.w as u64); + vec.push(size.h as u64); + }), + ); + } + } + } + fn apply_surface_material(node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; let material_idx = flex_vec.idx(1).get_u64()?; @@ -97,6 +158,165 @@ impl PanelItem { Ok(()) } + + fn pointer_deactivate(node: &Node, _calling_client: Arc, _data: &[u8]) -> Result<()> { + if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { + if *panel_item.seat_data.pointer_active.lock() { + if let Some(pointer) = panel_item.seat_data.pointer() { + pointer.leave(0, &panel_item.toplevel_surface); + *panel_item.seat_data.pointer_active.lock() = false; + } + } + } + + Ok(()) + } + + fn pointer_motion(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { + if let Some(pointer) = panel_item.seat_data.pointer() { + let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; + let x = flex_vec.index(0)?.get_f64()?; + let y = flex_vec.index(1)?.get_f64()?; + let mut pointer_active = panel_item.seat_data.pointer_active.lock(); + if *pointer_active { + pointer.motion(0, x, y); + } else { + pointer.enter(0, &panel_item.toplevel_surface, x, y); + *pointer_active = true; + } + pointer.frame(); + } + } + + Ok(()) + } + + fn pointer_button(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { + if let Some(pointer) = panel_item.seat_data.pointer() { + if *panel_item.seat_data.pointer_active.lock() { + let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; + let button = flex_vec.index(0)?.get_u64()? as u32; + let active = flex_vec.index(1)?.get_bool()?; + pointer.button( + 0, + 0, + button, + if active { + ButtonState::Pressed + } else { + ButtonState::Released + }, + ); + pointer.frame(); + } + } + } + + Ok(()) + } + + fn pointer_scroll(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { + if let Some(pointer) = panel_item.seat_data.pointer() { + if *panel_item.seat_data.pointer_active.lock() { + let flex = flexbuffers::Reader::get_root(data)?; + if flex.flexbuffer_type().is_null() { + pointer.axis_stop(0, Axis::HorizontalScroll); + pointer.axis_stop(0, Axis::VerticalScroll); + } else { + let flex_vec = flex.get_vector()?; + let axis_continuous_vec = flex_to_vec2!(flex_vec.idx(0)) + .ok_or_else(|| anyhow!("No continuous axis vector!"))?; + pointer.axis(0, Axis::HorizontalScroll, axis_continuous_vec.x as f64); + pointer.axis(0, Axis::VerticalScroll, axis_continuous_vec.y as f64); + if let Some(axis_discrete_vec) = flex_to_vec2!(flex_vec.idx(0)) { + pointer + .axis_discrete(Axis::HorizontalScroll, axis_discrete_vec.x as i32); + pointer.axis_discrete(Axis::VerticalScroll, axis_discrete_vec.y as i32); + } + } + pointer.frame(); + } + } + } + + Ok(()) + } + + fn keyboard_set_active(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { + if let Some(keyboard) = panel_item.seat_data.keyboard() { + let mut keyboard_active = panel_item.seat_data.keyboard_active.lock(); + let active = flexbuffers::Reader::get_root(data)?.get_bool()?; + if *keyboard_active != active { + if active { + keyboard.enter(0, &panel_item.toplevel_surface, vec![]); + } else { + keyboard.leave(0, &panel_item.toplevel_surface); + } + *keyboard_active = active; + } + } + } + + Ok(()) + } + + fn keyboard_set_key_state( + node: &Node, + _calling_client: Arc, + data: &[u8], + ) -> Result<()> { + if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { + if let Some(keyboard) = panel_item.seat_data.keyboard() { + let active = *panel_item.seat_data.keyboard_active.lock(); + if active { + let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; + let key = flex_vec.index(0)?.get_u64()? as u32; + let state: KeyState = (flex_vec.index(1)?.as_u64() as u32) + .try_into() + .map_err(|_| anyhow!("Invalid key state"))?; + keyboard.key(0, 0, key, state); + } + } + } + + Ok(()) + } + + fn keyboard_set_modifiers( + node: &Node, + _calling_client: Arc, + data: &[u8], + ) -> Result<()> { + if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { + if let Some(keyboard) = panel_item.seat_data.keyboard() { + let active = *panel_item.seat_data.keyboard_active.lock(); + if active { + let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; + keyboard.modifiers( + 0, + flex_vec.index(0)?.get_u64()? as u32, + flex_vec.index(1)?.get_u64()? as u32, + flex_vec.index(2)?.get_u64()? as u32, + flex_vec.index(3)?.get_u64()? as u32, + ); + } + } + } + + Ok(()) + } +} +impl ItemSpecialization for PanelItem { + fn serialize_start_data(&self, vec: &mut flexbuffers::VectorBuilder) { + let mut size_vec = vec.start_vector(); + let size = *self.size.lock(); + size_vec.push(size.w as u32); + size_vec.push(size.h as u32); + } } pub fn register_panel_item_ui_flex( diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs new file mode 100644 index 0000000..c3e2236 --- /dev/null +++ b/src/wayland/seat.rs @@ -0,0 +1,172 @@ +use super::WaylandState; +use nanoid::nanoid; +use once_cell::sync::OnceCell; +use parking_lot::Mutex; +use smithay::reexports::wayland_server::{ + backend::ClientId, + delegate_dispatch, delegate_global_dispatch, + protocol::{ + wl_keyboard::{self, WlKeyboard}, + wl_pointer::{self, WlPointer}, + wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE}, + wl_touch::{self, WlTouch}, + }, + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, +}; +use std::ops::Deref; +use std::sync::Arc; + +pub struct SeatDelegate; + +#[derive(Clone)] +pub struct SeatData(Arc); +impl SeatData { + pub fn new(client: ClientId) -> Self { + SeatData(Arc::new(SeatDataInner { + client, + pointer: OnceCell::new(), + pointer_active: Mutex::new(false), + keyboard: OnceCell::new(), + keyboard_active: Mutex::new(false), + touch: OnceCell::new(), + })) + } +} +impl Deref for SeatData { + type Target = SeatDataInner; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +pub struct SeatDataInner { + client: ClientId, + pointer: OnceCell, + pub pointer_active: Mutex, + keyboard: OnceCell, + pub keyboard_active: Mutex, + touch: OnceCell, +} +impl SeatDataInner { + pub fn pointer(&self) -> Option<&WlPointer> { + self.pointer.get() + } + pub fn keyboard(&self) -> Option<&WlKeyboard> { + self.keyboard.get() + } + pub fn touch(&self) -> Option<&WlTouch> { + self.touch.get() + } +} + +impl GlobalDispatch for SeatDelegate { + fn bind( + _state: &mut WaylandState, + _handle: &DisplayHandle, + _client: &Client, + resource: New, + data: &SeatData, + data_init: &mut DataInit<'_, WaylandState>, + ) { + let resource = data_init.init(resource, data.clone()); + + if resource.version() >= EVT_NAME_SINCE { + resource.name(nanoid!()); + } + + resource.capabilities(Capability::Pointer | Capability::Keyboard); + } + + fn can_view(client: Client, data: &SeatData) -> bool { + client.id() == data.0.client + } +} +delegate_global_dispatch!(WaylandState: [WlSeat: SeatData] => SeatDelegate); + +impl Dispatch for SeatDelegate { + fn request( + _state: &mut WaylandState, + _client: &Client, + _resource: &WlSeat, + request: ::Request, + data: &SeatData, + _dh: &DisplayHandle, + data_init: &mut DataInit<'_, WaylandState>, + ) { + match request { + wl_seat::Request::GetPointer { id } => { + let _ = data.0.pointer.set(data_init.init(id, data.clone())); + } + wl_seat::Request::GetKeyboard { id } => { + let _ = data.0.keyboard.set(data_init.init(id, data.clone())); + } + wl_seat::Request::GetTouch { id } => { + let _ = data.0.touch.set(data_init.init(id, data.clone())); + } + wl_seat::Request::Release => (), + _ => unreachable!(), + } + } +} +delegate_dispatch!(WaylandState: [WlSeat: SeatData] => SeatDelegate); + +impl Dispatch for SeatDelegate { + fn request( + _state: &mut WaylandState, + _client: &Client, + _resource: &WlPointer, + request: ::Request, + _data: &SeatData, + _dh: &DisplayHandle, + _data_init: &mut DataInit<'_, WaylandState>, + ) { + match request { + wl_pointer::Request::SetCursor { + serial: _, + surface: _, + hotspot_x: _, + hotspot_y: _, + } => todo!(), + wl_pointer::Request::Release => (), + _ => unreachable!(), + } + } +} +delegate_dispatch!(WaylandState: [WlPointer: SeatData] => SeatDelegate); + +impl Dispatch for SeatDelegate { + fn request( + _state: &mut WaylandState, + _client: &Client, + _resource: &WlKeyboard, + request: ::Request, + _data: &SeatData, + _dh: &DisplayHandle, + _data_init: &mut DataInit<'_, WaylandState>, + ) { + match request { + wl_keyboard::Request::Release => (), + _ => unreachable!(), + } + } +} +delegate_dispatch!(WaylandState: [WlKeyboard: SeatData] => SeatDelegate); + +impl Dispatch for SeatDelegate { + fn request( + _state: &mut WaylandState, + _client: &Client, + _resource: &WlTouch, + request: ::Request, + _data: &SeatData, + _dh: &DisplayHandle, + _data_init: &mut DataInit<'_, WaylandState>, + ) { + match request { + wl_touch::Request::Release => (), + _ => unreachable!(), + } + } +} +delegate_dispatch!(WaylandState: [WlTouch: SeatData] => SeatDelegate); diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index ee6f200..881f946 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -1,24 +1,27 @@ +use super::WaylandState; use smithay::{ delegate_xdg_shell, - reexports::wayland_protocols::xdg::{ - decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode, - shell::server::xdg_toplevel::State, + reexports::{ + wayland_protocols::xdg::{ + decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode, + shell::server::xdg_toplevel::State, + }, + wayland_server::{protocol::wl_seat::WlSeat, DisplayHandle}, + }, + wayland::{ + shell::xdg::{ + PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState, + }, + Serial, }, - wayland::{compositor, shell::xdg::XdgShellHandler}, }; -use super::{panel_item::PanelItem, surface::CoreSurface, WaylandState}; - impl XdgShellHandler for WaylandState { - fn xdg_shell_state(&mut self) -> &mut smithay::wayland::shell::xdg::XdgShellState { + fn xdg_shell_state(&mut self) -> &mut XdgShellState { &mut self.xdg_shell_state } - fn new_toplevel( - &mut self, - _dh: &smithay::reexports::wayland_server::DisplayHandle, - surface: smithay::wayland::shell::xdg::ToplevelSurface, - ) { + fn new_toplevel(&mut self, _dh: &DisplayHandle, surface: ToplevelSurface) { self.output .enter(&self.display_handle, surface.wl_surface()); surface.with_pending_state(|state| { @@ -26,35 +29,22 @@ impl XdgShellHandler for WaylandState { state.decoration_mode = Some(Mode::ServerSide); }); surface.send_configure(); - - compositor::with_states(surface.wl_surface(), |data| { - data.data_map.insert_if_missing_threadsafe(CoreSurface::new); - data.data_map - .insert_if_missing_threadsafe(|| PanelItem::create(surface.wl_surface().clone())); - }); } fn new_popup( &mut self, - _dh: &smithay::reexports::wayland_server::DisplayHandle, - surface: smithay::wayland::shell::xdg::PopupSurface, - _positioner: smithay::wayland::shell::xdg::PositionerState, + _dh: &DisplayHandle, + _surface: PopupSurface, + _positioner: PositionerState, ) { - self.output - .enter(&self.display_handle, surface.wl_surface()); - let _ = surface.send_configure(); - - compositor::with_states(surface.wl_surface(), |data| { - data.data_map.insert_if_missing(CoreSurface::new); - }); } fn grab( &mut self, - _dh: &smithay::reexports::wayland_server::DisplayHandle, - _surface: smithay::wayland::shell::xdg::PopupSurface, - _seat: smithay::reexports::wayland_server::protocol::wl_seat::WlSeat, - _serial: smithay::wayland::Serial, + _dh: &DisplayHandle, + _surface: PopupSurface, + _seat: WlSeat, + _serial: Serial, ) { todo!() }