feat(wayland): configure and commit for toplevel]
This commit is contained in:
@@ -175,7 +175,7 @@ pub trait ItemSpecialization {
|
||||
pub enum ItemType {
|
||||
Environment(EnvironmentItem),
|
||||
#[cfg(feature = "wayland")]
|
||||
Panel(PanelItem),
|
||||
Panel(Arc<PanelItem>),
|
||||
}
|
||||
impl Deref for ItemType {
|
||||
type Target = dyn ItemSpecialization;
|
||||
@@ -184,7 +184,7 @@ impl Deref for ItemType {
|
||||
match self {
|
||||
ItemType::Environment(item) => item,
|
||||
#[cfg(feature = "wayland")]
|
||||
ItemType::Panel(item) => item,
|
||||
ItemType::Panel(item) => &**item,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{state::WaylandState, surface::CoreSurface};
|
||||
use super::{panel_item::PanelItem, state::WaylandState, surface::CoreSurface};
|
||||
use smithay::{
|
||||
delegate_compositor,
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
wayland::compositor::{self, CompositorHandler, CompositorState},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
impl CompositorHandler for WaylandState {
|
||||
fn compositor_state(&mut self) -> &mut CompositorState {
|
||||
@@ -11,16 +12,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.weak_ref.upgrade().unwrap(),
|
||||
&self.display,
|
||||
self.display_handle.clone(),
|
||||
surface,
|
||||
)
|
||||
})
|
||||
});
|
||||
CoreSurface::add_to(&self.display, self.display_handle.clone(), surface);
|
||||
if let Some(panel_item) = compositor::with_states(surface, |data| {
|
||||
data.data_map.get::<Arc<PanelItem>>().cloned()
|
||||
}) {
|
||||
panel_item.commit_toplevel();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +1,110 @@
|
||||
use super::state::WaylandState;
|
||||
use super::{state::WaylandState, xdg_shell::XdgSurfaceData};
|
||||
use smithay::{
|
||||
delegate_kde_decoration, delegate_xdg_decoration,
|
||||
reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode,
|
||||
wayland::shell::{
|
||||
self, kde::decoration::KdeDecorationHandler, xdg::decoration::XdgDecorationHandler,
|
||||
delegate_kde_decoration,
|
||||
reexports::{
|
||||
wayland_protocols::xdg::{
|
||||
decoration::zv1::server::{
|
||||
zxdg_decoration_manager_v1::{self, ZxdgDecorationManagerV1},
|
||||
zxdg_toplevel_decoration_v1::{self, Mode, ZxdgToplevelDecorationV1},
|
||||
},
|
||||
shell::server::xdg_toplevel::XdgToplevel,
|
||||
},
|
||||
wayland_server::{
|
||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Weak,
|
||||
},
|
||||
},
|
||||
wayland::shell::{self, kde::decoration::KdeDecorationHandler},
|
||||
};
|
||||
|
||||
impl XdgDecorationHandler for WaylandState {
|
||||
fn new_decoration(&mut self, toplevel: smithay::wayland::shell::xdg::ToplevelSurface) {
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.decoration_mode = Some(Mode::ServerSide);
|
||||
});
|
||||
toplevel.send_configure();
|
||||
}
|
||||
// impl XdgDecorationHandler for WaylandState {
|
||||
// fn new_decoration(&mut self, toplevel: smithay::wayland::shell::xdg::ToplevelSurface) {
|
||||
// toplevel.with_pending_state(|state| {
|
||||
// state.decoration_mode = Some(Mode::ServerSide);
|
||||
// });
|
||||
// toplevel.send_configure();
|
||||
// }
|
||||
|
||||
fn request_mode(
|
||||
&mut self,
|
||||
_toplevel: smithay::wayland::shell::xdg::ToplevelSurface,
|
||||
_mode: smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode,
|
||||
// fn request_mode(
|
||||
// &mut self,
|
||||
// _toplevel: smithay::wayland::shell::xdg::ToplevelSurface,
|
||||
// _mode: smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode,
|
||||
// ) {
|
||||
// }
|
||||
|
||||
// fn unset_mode(&mut self, _toplevel: smithay::wayland::shell::xdg::ToplevelSurface) {}
|
||||
// }
|
||||
// delegate_xdg_decoration!(WaylandState);
|
||||
|
||||
impl GlobalDispatch<ZxdgDecorationManagerV1, (), WaylandState> for WaylandState {
|
||||
fn bind(
|
||||
_state: &mut WaylandState,
|
||||
_handle: &DisplayHandle,
|
||||
_client: &Client,
|
||||
resource: New<ZxdgDecorationManagerV1>,
|
||||
_global_data: &(),
|
||||
data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
data_init.init(resource, ());
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<ZxdgDecorationManagerV1, (), WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
_resource: &ZxdgDecorationManagerV1,
|
||||
request: zxdg_decoration_manager_v1::Request,
|
||||
_data: &(),
|
||||
_dhandle: &DisplayHandle,
|
||||
data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
zxdg_decoration_manager_v1::Request::Destroy => todo!(),
|
||||
zxdg_decoration_manager_v1::Request::GetToplevelDecoration { id, toplevel } => {
|
||||
data_init.init(id, toplevel.downgrade());
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Dispatch<ZxdgToplevelDecorationV1, Weak<XdgToplevel>, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
resource: &ZxdgToplevelDecorationV1,
|
||||
request: zxdg_toplevel_decoration_v1::Request,
|
||||
data: &Weak<XdgToplevel>,
|
||||
_dhandle: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
zxdg_toplevel_decoration_v1::Request::SetMode { mode: _ } => {
|
||||
resource.configure(Mode::ServerSide);
|
||||
data.upgrade()
|
||||
.unwrap()
|
||||
.data::<XdgSurfaceData>()
|
||||
.unwrap()
|
||||
.xdg_surface
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.configure(0);
|
||||
}
|
||||
zxdg_toplevel_decoration_v1::Request::UnsetMode => {
|
||||
resource.configure(Mode::ServerSide);
|
||||
data.upgrade()
|
||||
.unwrap()
|
||||
.data::<XdgSurfaceData>()
|
||||
.unwrap()
|
||||
.xdg_surface
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.configure(0);
|
||||
}
|
||||
zxdg_toplevel_decoration_v1::Request::Destroy => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn unset_mode(&mut self, _toplevel: smithay::wayland::shell::xdg::ToplevelSurface) {}
|
||||
}
|
||||
delegate_xdg_decoration!(WaylandState);
|
||||
|
||||
impl KdeDecorationHandler for WaylandState {
|
||||
fn kde_decoration_state(&self) -> &shell::kde::decoration::KdeDecorationState {
|
||||
|
||||
@@ -9,28 +9,28 @@ mod surface;
|
||||
mod xdg_activation;
|
||||
mod xdg_shell;
|
||||
|
||||
use self::{panel_item::PanelItem, state::WaylandState, surface::CORE_SURFACES};
|
||||
use self::{state::WaylandState, surface::CORE_SURFACES};
|
||||
use crate::wayland::state::ClientState;
|
||||
use color_eyre::eyre::{ensure, Result};
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use slog::Drain;
|
||||
use smithay::{
|
||||
backend::{egl::EGLContext, renderer::{gles2::Gles2Renderer}},
|
||||
reexports::wayland_server::{backend::GlobalId, Display, ListeningSocket, Resource},
|
||||
backend::{egl::EGLContext, renderer::gles2::Gles2Renderer},
|
||||
reexports::wayland_server::{backend::GlobalId, Display, ListeningSocket},
|
||||
};
|
||||
use tracing::info;
|
||||
use std::os::unix::prelude::AsRawFd;
|
||||
use std::{
|
||||
ffi::c_void,
|
||||
os::unix::{net::UnixListener, prelude::FromRawFd},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{os::unix::prelude::AsRawFd};
|
||||
use stereokit as sk;
|
||||
use stereokit::StereoKit;
|
||||
use tokio::{
|
||||
io::unix::AsyncFd, net::UnixListener as AsyncUnixListener, sync::mpsc, task::JoinHandle,
|
||||
};
|
||||
use tracing::info;
|
||||
|
||||
struct EGLRawHandles {
|
||||
display: *const c_void,
|
||||
@@ -147,26 +147,9 @@ impl Wayland {
|
||||
|
||||
pub fn frame(&mut self, sk: &StereoKit) {
|
||||
for core_surface in CORE_SURFACES.get_valid_contents() {
|
||||
let Some(client_id) =
|
||||
core_surface
|
||||
.wl_surface()
|
||||
.and_then(|surf| surf.client())
|
||||
.map(|c| c.id()) else { continue };
|
||||
let state = self.state.lock();
|
||||
let Some(seat_data) = state.seats.get(&client_id).cloned() else { continue };
|
||||
let output = state.output.clone();
|
||||
core_surface.process(
|
||||
sk,
|
||||
&mut self.renderer,
|
||||
output,
|
||||
&self.log,
|
||||
|data| {
|
||||
PanelItem::on_mapped(&core_surface, data, seat_data);
|
||||
},
|
||||
|data| {
|
||||
PanelItem::if_mapped(&core_surface, data);
|
||||
},
|
||||
);
|
||||
core_surface.process(sk, &mut self.renderer, output, &self.log);
|
||||
}
|
||||
|
||||
self.display.lock().flush_clients().unwrap();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::{
|
||||
seat::{KeyboardInfo, SeatData},
|
||||
seat::{Cursor, KeyboardInfo, SeatData},
|
||||
surface::CoreSurface,
|
||||
xdg_shell::{XdgSurfaceData, XdgToplevelData},
|
||||
};
|
||||
use crate::{
|
||||
core::{
|
||||
@@ -18,14 +19,23 @@ use glam::Mat4;
|
||||
use lazy_static::lazy_static;
|
||||
use mint::Vector2;
|
||||
use nanoid::nanoid;
|
||||
use serde::Deserialize;
|
||||
use parking_lot::Mutex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smithay::{
|
||||
reexports::wayland_server::protocol::wl_pointer::{Axis, ButtonState},
|
||||
utils::Size,
|
||||
wayland::{
|
||||
compositor::SurfaceData,
|
||||
shell::xdg::{Configure, XdgToplevelSurfaceData},
|
||||
reexports::{
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel::{
|
||||
XdgToplevel, EVT_CONFIGURE_BOUNDS_SINCE,
|
||||
},
|
||||
wayland_server::{
|
||||
backend::Credentials,
|
||||
protocol::{
|
||||
wl_pointer::{Axis, ButtonState},
|
||||
wl_surface::WlSurface,
|
||||
},
|
||||
Resource, Weak as WlWeak,
|
||||
},
|
||||
},
|
||||
wayland::compositor,
|
||||
};
|
||||
use stardust_xr::schemas::flex::{deserialize, serialize};
|
||||
use std::sync::{Arc, Weak};
|
||||
@@ -48,20 +58,57 @@ lazy_static! {
|
||||
"close",
|
||||
],
|
||||
aliased_local_methods: vec![],
|
||||
aliased_remote_signals: vec!["resize", "set_cursor",],
|
||||
aliased_remote_signals: vec!["commit_toplevel", "set_cursor",],
|
||||
ui: Default::default(),
|
||||
items: Registry::new(),
|
||||
acceptors: Registry::new(),
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct ToplevelState {
|
||||
#[serde(skip_serializing)]
|
||||
pub mapped: bool,
|
||||
#[serde(skip_serializing)]
|
||||
pub parent: Option<WlWeak<XdgToplevel>>,
|
||||
pub title: String,
|
||||
pub app_id: String,
|
||||
pub size: Vector2<u32>,
|
||||
pub max_size: Vector2<u32>,
|
||||
pub min_size: Vector2<u32>,
|
||||
pub states: Vec<u8>,
|
||||
#[serde(skip_serializing)]
|
||||
pub queued_state: Option<Box<ToplevelState>>,
|
||||
}
|
||||
impl Default for ToplevelState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mapped: false,
|
||||
parent: None,
|
||||
title: String::default(),
|
||||
app_id: String::default(),
|
||||
size: Vector2::from([0; 2]),
|
||||
max_size: Vector2::from([0; 2]),
|
||||
min_size: Vector2::from([0; 2]),
|
||||
states: Vec::new(),
|
||||
queued_state: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PanelItem {
|
||||
node: Weak<Node>,
|
||||
core_surface: Weak<CoreSurface>,
|
||||
client_credentials: Option<Credentials>,
|
||||
pub toplevel: WlWeak<XdgToplevel>,
|
||||
pub cursor: Mutex<Option<WlWeak<WlSurface>>>,
|
||||
seat_data: SeatData,
|
||||
}
|
||||
impl PanelItem {
|
||||
pub fn create(core_surface: &Arc<CoreSurface>, seat_data: SeatData) -> Arc<Node> {
|
||||
pub fn create(
|
||||
toplevel: XdgToplevel,
|
||||
client_credentials: Option<Credentials>,
|
||||
seat_data: SeatData,
|
||||
) -> (Arc<Node>, Arc<PanelItem>) {
|
||||
let node = Arc::new(Node::create(
|
||||
&INTERNAL_CLIENT,
|
||||
"/item/panel/item",
|
||||
@@ -69,17 +116,23 @@ impl PanelItem {
|
||||
true,
|
||||
));
|
||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap();
|
||||
|
||||
let specialization = ItemType::Panel(PanelItem {
|
||||
let panel_item = Arc::new(PanelItem {
|
||||
node: Arc::downgrade(&node),
|
||||
core_surface: Arc::downgrade(core_surface),
|
||||
client_credentials,
|
||||
toplevel: toplevel.downgrade(),
|
||||
cursor: Mutex::new(None),
|
||||
seat_data,
|
||||
});
|
||||
let item = Item::add_to(&node, &ITEM_TYPE_INFO_PANEL, specialization);
|
||||
if let ItemType::Panel(panel) = &item.specialization {
|
||||
let _ = panel.seat_data.panel_item.set(Arc::downgrade(&item));
|
||||
}
|
||||
let _ = panel_item
|
||||
.seat_data
|
||||
.panel_item
|
||||
.set(Arc::downgrade(&panel_item));
|
||||
|
||||
let item = Item::add_to(
|
||||
&node,
|
||||
&ITEM_TYPE_INFO_PANEL,
|
||||
ItemType::Panel(panel_item.clone()),
|
||||
);
|
||||
node.add_local_signal(
|
||||
"apply_surface_material",
|
||||
PanelItem::apply_surface_material_flex,
|
||||
@@ -102,11 +155,11 @@ impl PanelItem {
|
||||
);
|
||||
node.add_local_signal("keyboard_deactivate", PanelItem::keyboard_deactivate_flex);
|
||||
node.add_local_signal("keyboard_key_state", PanelItem::keyboard_key_state_flex);
|
||||
node.add_local_signal("resize", PanelItem::resize_flex);
|
||||
node.add_local_signal("configure_toplevel", PanelItem::configure_toplevel_flex);
|
||||
|
||||
if let Some(startup_settings) = core_surface
|
||||
.pid()
|
||||
.and_then(|pid| get_env(pid).ok())
|
||||
if let Some(startup_settings) = panel_item
|
||||
.client_credentials
|
||||
.and_then(|cred| get_env(cred.pid).ok())
|
||||
.and_then(|env| startup_settings(&env))
|
||||
{
|
||||
spatial.set_local_transform(startup_settings.transform);
|
||||
@@ -119,16 +172,45 @@ impl PanelItem {
|
||||
}
|
||||
}
|
||||
|
||||
node
|
||||
(node, panel_item)
|
||||
}
|
||||
|
||||
pub fn from_node(node: &Node) -> Option<&PanelItem> {
|
||||
node.item.get().and_then(|item| match &item.specialization {
|
||||
ItemType::Panel(panel_item) => Some(panel_item),
|
||||
ItemType::Panel(panel_item) => Some(&**panel_item),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn toplevel_surface_data(&self) -> Option<XdgSurfaceData> {
|
||||
Some(
|
||||
self.toplevel
|
||||
.upgrade()
|
||||
.ok()?
|
||||
.data::<XdgToplevelData>()?
|
||||
.xdg_surface_data
|
||||
.clone(),
|
||||
)
|
||||
}
|
||||
pub fn toplevel_state(&self) -> Option<Arc<Mutex<ToplevelState>>> {
|
||||
Some(
|
||||
self.toplevel
|
||||
.upgrade()
|
||||
.ok()?
|
||||
.data::<XdgToplevelData>()?
|
||||
.state
|
||||
.clone(),
|
||||
)
|
||||
}
|
||||
fn toplevel_wl_surface(&self) -> Option<WlSurface> {
|
||||
self.toplevel_surface_data()?.wl_surface.upgrade().ok()
|
||||
}
|
||||
fn core_surface(&self) -> Option<Arc<CoreSurface>> {
|
||||
compositor::with_states(&self.toplevel_wl_surface()?, |data| {
|
||||
data.data_map.get::<Arc<CoreSurface>>().cloned()
|
||||
})
|
||||
}
|
||||
|
||||
fn apply_surface_material_flex(
|
||||
node: &Node,
|
||||
calling_client: Arc<Client>,
|
||||
@@ -150,7 +232,7 @@ impl PanelItem {
|
||||
.ok_or_else(|| eyre!("Node is not a model"))?;
|
||||
|
||||
if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization {
|
||||
if let Some(core_surface) = panel_item.core_surface.upgrade() {
|
||||
if let Some(core_surface) = panel_item.core_surface() {
|
||||
core_surface.apply_material(model.clone(), info.idx);
|
||||
}
|
||||
}
|
||||
@@ -164,9 +246,8 @@ impl PanelItem {
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let cursor = panel_item.seat_data.cursor.lock();
|
||||
let Some(cursor) = &*cursor else { return Ok(())};
|
||||
let Some(core_surface) = cursor.lock().core_surface.upgrade() else { return Ok(()) };
|
||||
let Some(cursor) = panel_item.seat_data.cursor() else { return Ok(())};
|
||||
let Some(core_surface) = CoreSurface::from_wl_surface(&cursor) else { return Ok(()) };
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SurfaceMaterialInfo<'a> {
|
||||
@@ -188,65 +269,6 @@ impl PanelItem {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on_mapped(
|
||||
core_surface: &Arc<CoreSurface>,
|
||||
surface_data: &SurfaceData,
|
||||
seat_data: SeatData,
|
||||
) {
|
||||
if surface_data
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.is_some()
|
||||
{
|
||||
surface_data
|
||||
.data_map
|
||||
.insert_if_missing_threadsafe(|| PanelItem::create(core_surface, seat_data));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn if_mapped(_core_surface: &Arc<CoreSurface>, surface_data: &SurfaceData) {
|
||||
let Some(panel_node) = surface_data.data_map.get::<Arc<Node>>() else { return };
|
||||
let Some(panel_item) = PanelItem::from_node(panel_node) else { return };
|
||||
|
||||
panel_item.set_cursor();
|
||||
}
|
||||
|
||||
pub fn ack_resize(&self, xdg_config: Configure) {
|
||||
let Configure::Toplevel(config) = xdg_config else { return };
|
||||
let Some(size) = config.state.size else { return };
|
||||
let Some(core_surface) = self.core_surface.upgrade() else { return };
|
||||
core_surface.with_data(|data| data.size = Vector2::from([size.w as u32, size.h as u32]));
|
||||
let _ = self
|
||||
.node
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.send_remote_signal("resize", &serialize((size.w, size.h)).unwrap());
|
||||
}
|
||||
|
||||
pub fn set_cursor(&self) {
|
||||
let mut cursor_changed = self.seat_data.cursor_changed.lock();
|
||||
if !*cursor_changed {
|
||||
return;
|
||||
}
|
||||
let mut data = serialize(()).unwrap();
|
||||
|
||||
let cursor = self.seat_data.cursor.lock();
|
||||
if let Some(cursor) = cursor.as_ref().map(|cursor| cursor.lock()) {
|
||||
if let Some(core_surface) = cursor.core_surface.upgrade() {
|
||||
core_surface.with_data(|mapped_data| {
|
||||
data = serialize((mapped_data.size, cursor.hotspot)).unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let _ = self
|
||||
.node
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.send_remote_signal("set_cursor", &data);
|
||||
*cursor_changed = false;
|
||||
}
|
||||
|
||||
fn pointer_deactivate_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
@@ -256,7 +278,7 @@ impl PanelItem {
|
||||
if !panel_item.seat_data.pointer_active() {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) };
|
||||
let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) };
|
||||
|
||||
@@ -270,7 +292,7 @@ impl PanelItem {
|
||||
|
||||
fn pointer_motion_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) };
|
||||
let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) };
|
||||
|
||||
@@ -297,7 +319,7 @@ impl PanelItem {
|
||||
if !panel_item.seat_data.pointer_active() {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) };
|
||||
|
||||
let (button, state): (u32, u32) = deserialize(data)?;
|
||||
@@ -324,7 +346,7 @@ impl PanelItem {
|
||||
if !panel_item.seat_data.pointer_active() {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) };
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -399,7 +421,7 @@ impl PanelItem {
|
||||
|
||||
fn keyboard_activate_flex(node: &Node, keymap: &Keymap) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) };
|
||||
let Some(keyboard) = panel_item.seat_data.keyboard() else { return Ok(()) };
|
||||
|
||||
@@ -420,7 +442,7 @@ impl PanelItem {
|
||||
_data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) };
|
||||
let Some(keyboard) = panel_item.seat_data.keyboard() else { return Ok(()) };
|
||||
|
||||
@@ -450,55 +472,94 @@ impl PanelItem {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resize_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
fn configure_toplevel_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface.upgrade() else { return Ok(()) };
|
||||
let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) };
|
||||
let size: Vector2<u32> = deserialize(data)?;
|
||||
let Ok(xdg_toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let Some(xdg_surface) = panel_item.toplevel_surface_data().and_then(|d| d.xdg_surface.upgrade().ok()) else { return Ok(()) };
|
||||
|
||||
let toplevel_surface = core_surface
|
||||
.wayland_state()
|
||||
.lock()
|
||||
.xdg_shell_state
|
||||
.toplevel_surfaces(|surfaces| {
|
||||
surfaces
|
||||
.iter()
|
||||
.find(|surf| surf.wl_surface().clone() == wl_surface)
|
||||
.cloned()
|
||||
});
|
||||
|
||||
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 = size.x as i32;
|
||||
state.size.as_mut().unwrap().h = size.y as i32;
|
||||
size_set = true;
|
||||
});
|
||||
if size_set {
|
||||
toplevel_surface.send_configure();
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct ConfigureToplevelInfo {
|
||||
size: Option<Vector2<u32>>,
|
||||
states: Vec<u8>,
|
||||
bounds: Option<Vector2<u32>>,
|
||||
}
|
||||
|
||||
let info: ConfigureToplevelInfo = deserialize(data)?;
|
||||
if let Some(xdg_state) = panel_item.toplevel_state() {
|
||||
xdg_state.lock().queued_state.as_mut().unwrap().states = info.states.clone();
|
||||
}
|
||||
if let Some(bounds) = info.bounds {
|
||||
if xdg_toplevel.version() > EVT_CONFIGURE_BOUNDS_SINCE {
|
||||
xdg_toplevel.configure_bounds(bounds.x as i32, bounds.y as i32);
|
||||
}
|
||||
}
|
||||
let size = info.size.unwrap_or(Vector2::from([0; 2]));
|
||||
xdg_toplevel.configure(size.x as i32, size.y as i32, info.states);
|
||||
xdg_surface.configure(0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn commit_toplevel(&self) {
|
||||
let mapped = self.core_surface().map(|c| c.mapped()).unwrap_or(false);
|
||||
let Some(state) = self.toplevel_state() else { return };
|
||||
let Some(surface_data) = self.toplevel_surface_data() else { return };
|
||||
let mut state = state.lock();
|
||||
{
|
||||
let queued_state = state.queued_state.as_mut().unwrap();
|
||||
queued_state.mapped = mapped;
|
||||
queued_state.size = *surface_data.size.lock();
|
||||
}
|
||||
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
let queued_state = state.queued_state.take().unwrap();
|
||||
*state = (*queued_state).clone();
|
||||
state.queued_state = Some(queued_state);
|
||||
|
||||
let _ = node.send_remote_signal("commit_toplevel", &serialize(&*state).unwrap());
|
||||
}
|
||||
|
||||
pub fn set_cursor(&self, surface: Option<&WlSurface>, hotspot_x: i32, hotspot_y: i32) {
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
let mut data = serialize(()).unwrap();
|
||||
|
||||
let cursor_size = surface
|
||||
.and_then(|c| CoreSurface::from_wl_surface(c))
|
||||
.and_then(|c| c.with_data(|data| data.size));
|
||||
|
||||
if let Some(size) = cursor_size {
|
||||
data = serialize((size, (hotspot_x, hotspot_y))).unwrap();
|
||||
}
|
||||
|
||||
let _ = node.send_remote_signal("set_cursor", &data);
|
||||
}
|
||||
}
|
||||
impl ItemSpecialization for PanelItem {
|
||||
fn serialize_start_data(&self, id: &str) -> Vec<u8> {
|
||||
// Panel size
|
||||
let panel_size = self
|
||||
.core_surface
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.with_data(|data| data.size);
|
||||
let cursor = self.cursor.lock().as_ref().and_then(|c| c.upgrade().ok());
|
||||
let cursor_size = cursor
|
||||
.as_ref()
|
||||
.and_then(|c| CoreSurface::from_wl_surface(&c))
|
||||
.and_then(|c| c.with_data(|data| data.size));
|
||||
let cursor_hotspot = cursor
|
||||
.and_then(|c| {
|
||||
compositor::with_states(&c, |data| data.data_map.get::<Arc<Cursor>>().cloned())
|
||||
})
|
||||
.map(|cursor| cursor.hotspot);
|
||||
|
||||
let cursor_lock = (*self.seat_data.cursor.lock()).clone();
|
||||
let cursor_size = cursor_lock
|
||||
.clone()
|
||||
.and_then(|cursor| cursor.lock().core_surface.upgrade())
|
||||
.and_then(|surf| surf.with_data(|data| data.size));
|
||||
let cursor_hotspot = cursor_lock.map(|cursor| cursor.lock().hotspot);
|
||||
|
||||
serialize((id, (panel_size, cursor_size.zip(cursor_hotspot)))).unwrap()
|
||||
let toplevel_state = self.toplevel_state();
|
||||
let toplevel_state = toplevel_state.as_ref().map(|state| state.lock());
|
||||
serialize((
|
||||
id,
|
||||
(
|
||||
toplevel_state.and_then(|state| state.mapped.then_some(state.clone())),
|
||||
cursor_size.zip(cursor_hotspot),
|
||||
),
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use super::{state::WaylandState, surface::CoreSurface, GLOBAL_DESTROY_QUEUE};
|
||||
use crate::nodes::items::Item;
|
||||
use super::{
|
||||
panel_item::PanelItem, state::WaylandState, surface::CoreSurface, GLOBAL_DESTROY_QUEUE,
|
||||
};
|
||||
use color_eyre::eyre::Result;
|
||||
use mint::Vector2;
|
||||
use nanoid::nanoid;
|
||||
@@ -9,11 +10,11 @@ use smithay::{
|
||||
input::keyboard::{KeymapFile, ModifiersState},
|
||||
reexports::wayland_server::{
|
||||
backend::{ClientId, GlobalId},
|
||||
delegate_dispatch, delegate_global_dispatch,
|
||||
protocol::{
|
||||
wl_keyboard::{self, KeyState, WlKeyboard},
|
||||
wl_pointer::{self, WlPointer},
|
||||
wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE},
|
||||
wl_surface::WlSurface,
|
||||
wl_touch::{self, WlTouch},
|
||||
},
|
||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
|
||||
@@ -25,7 +26,6 @@ use std::{ops::Deref, sync::Weak};
|
||||
use xkbcommon::xkb::{self, Keymap};
|
||||
|
||||
pub struct Cursor {
|
||||
pub core_surface: Weak<CoreSurface>,
|
||||
pub hotspot: Vector2<i32>,
|
||||
}
|
||||
|
||||
@@ -70,8 +70,6 @@ impl KeyboardInfo {
|
||||
}
|
||||
unsafe impl Send for KeyboardInfo {}
|
||||
|
||||
pub struct SeatDelegate;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SeatData(Arc<SeatDataInner>);
|
||||
impl SeatData {
|
||||
@@ -80,8 +78,6 @@ impl SeatData {
|
||||
client,
|
||||
global_id: OnceCell::new(),
|
||||
panel_item: OnceCell::new(),
|
||||
cursor: Mutex::new(None),
|
||||
cursor_changed: Mutex::new(false),
|
||||
pointer: OnceCell::new(),
|
||||
pointer_active: Mutex::new(false),
|
||||
keyboard: OnceCell::new(),
|
||||
@@ -107,10 +103,8 @@ impl Deref for SeatData {
|
||||
|
||||
pub struct SeatDataInner {
|
||||
client: ClientId,
|
||||
pub global_id: OnceCell<GlobalId>,
|
||||
pub panel_item: OnceCell<Weak<Item>>,
|
||||
pub cursor: Mutex<Option<Arc<Mutex<Cursor>>>>,
|
||||
pub cursor_changed: Mutex<bool>,
|
||||
global_id: OnceCell<GlobalId>,
|
||||
pub panel_item: OnceCell<Weak<PanelItem>>,
|
||||
pointer: OnceCell<WlPointer>,
|
||||
pub pointer_active: Mutex<bool>,
|
||||
keyboard: OnceCell<WlKeyboard>,
|
||||
@@ -131,6 +125,16 @@ impl SeatDataInner {
|
||||
pub fn touch(&self) -> Option<&WlTouch> {
|
||||
self.touch.get()
|
||||
}
|
||||
|
||||
pub fn cursor(&self) -> Option<WlSurface> {
|
||||
self.panel_item
|
||||
.get()?
|
||||
.upgrade()?
|
||||
.cursor
|
||||
.lock()
|
||||
.as_ref()
|
||||
.and_then(|c| c.upgrade().ok())
|
||||
}
|
||||
}
|
||||
impl Drop for SeatDataInner {
|
||||
fn drop(&mut self) {
|
||||
@@ -139,7 +143,7 @@ impl Drop for SeatDataInner {
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalDispatch<WlSeat, SeatData, WaylandState> for SeatDelegate {
|
||||
impl GlobalDispatch<WlSeat, SeatData, WaylandState> for WaylandState {
|
||||
fn bind(
|
||||
_state: &mut WaylandState,
|
||||
_handle: &DisplayHandle,
|
||||
@@ -161,9 +165,8 @@ impl GlobalDispatch<WlSeat, SeatData, WaylandState> for SeatDelegate {
|
||||
client.id() == data.0.client
|
||||
}
|
||||
}
|
||||
delegate_global_dispatch!(WaylandState: [WlSeat: SeatData] => SeatDelegate);
|
||||
|
||||
impl Dispatch<WlSeat, SeatData, WaylandState> for SeatDelegate {
|
||||
impl Dispatch<WlSeat, SeatData, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
@@ -190,14 +193,13 @@ impl Dispatch<WlSeat, SeatData, WaylandState> for SeatDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate_dispatch!(WaylandState: [WlSeat: SeatData] => SeatDelegate);
|
||||
|
||||
impl Dispatch<WlPointer, SeatData, WaylandState> for SeatDelegate {
|
||||
impl Dispatch<WlPointer, SeatData, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
_resource: &WlPointer,
|
||||
request: <WlPointer as Resource>::Request,
|
||||
request: wl_pointer::Request,
|
||||
seat_data: &SeatData,
|
||||
dh: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, WaylandState>,
|
||||
@@ -209,54 +211,42 @@ impl Dispatch<WlPointer, SeatData, WaylandState> for SeatDelegate {
|
||||
hotspot_x,
|
||||
hotspot_y,
|
||||
} => {
|
||||
// if !seat_data.pointer_active() {
|
||||
// return;
|
||||
// }
|
||||
*seat_data.0.cursor_changed.lock() = true;
|
||||
if let Some(surface) = surface.as_ref() {
|
||||
CoreSurface::add_to(&state.display, dh.clone(), surface);
|
||||
compositor::with_states(surface, |data| {
|
||||
data.data_map.insert_if_missing_threadsafe(|| {
|
||||
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 {
|
||||
core_surface: Arc::downgrade(
|
||||
data.data_map.get::<Arc<CoreSurface>>().unwrap(),
|
||||
),
|
||||
hotspot: Vector2::from([hotspot_x, hotspot_y]),
|
||||
}))
|
||||
}) {
|
||||
let mut cursor =
|
||||
data.data_map.get::<Arc<Mutex<Cursor>>>().unwrap().lock();
|
||||
cursor.hotspot = Vector2::from([hotspot_x, hotspot_y]);
|
||||
});
|
||||
let mut cursor = data.data_map.get::<Arc<Mutex<Cursor>>>().unwrap().lock();
|
||||
cursor.hotspot = Vector2::from([hotspot_x, hotspot_y]);
|
||||
|
||||
if let Some(core_surface) = data.data_map.get::<Arc<CoreSurface>>() {
|
||||
core_surface.set_material_offset(1);
|
||||
}
|
||||
})
|
||||
}
|
||||
*seat_data.cursor.lock() = surface.and_then(|surf| {
|
||||
compositor::with_states(&surf, |data| {
|
||||
let cursor = data.data_map.get::<Arc<Mutex<Cursor>>>();
|
||||
if let Some(cursor) = cursor {
|
||||
if let Some(core_surface) = cursor.lock().core_surface.upgrade() {
|
||||
core_surface.set_material_offset(1);
|
||||
}
|
||||
}
|
||||
cursor.cloned()
|
||||
})
|
||||
});
|
||||
*seat_data
|
||||
.panel_item
|
||||
.get()
|
||||
.unwrap()
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.cursor
|
||||
.lock() = surface.as_ref().map(|surf| surf.downgrade());
|
||||
|
||||
if let Some(panel_item) = seat_data.panel_item.get().and_then(|i| i.upgrade()) {
|
||||
panel_item.set_cursor(surface.as_ref(), hotspot_x, hotspot_y);
|
||||
}
|
||||
}
|
||||
wl_pointer::Request::Release => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate_dispatch!(WaylandState: [WlPointer: SeatData] => SeatDelegate);
|
||||
|
||||
impl Dispatch<WlKeyboard, SeatData, WaylandState> for SeatDelegate {
|
||||
impl Dispatch<WlKeyboard, SeatData, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
@@ -272,9 +262,8 @@ impl Dispatch<WlKeyboard, SeatData, WaylandState> for SeatDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate_dispatch!(WaylandState: [WlKeyboard: SeatData] => SeatDelegate);
|
||||
|
||||
impl Dispatch<WlTouch, SeatData, WaylandState> for SeatDelegate {
|
||||
impl Dispatch<WlTouch, SeatData, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
@@ -290,4 +279,3 @@ impl Dispatch<WlTouch, SeatData, WaylandState> for SeatDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate_dispatch!(WaylandState: [WlTouch: SeatData] => SeatDelegate);
|
||||
|
||||
@@ -10,6 +10,7 @@ use smithay::{
|
||||
delegate_dmabuf, delegate_output, delegate_shm,
|
||||
output::{Mode, Output, Scale, Subpixel},
|
||||
reexports::{
|
||||
wayland_protocols::xdg::shell::server::xdg_wm_base::XdgWmBase,
|
||||
wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::Mode as DecorationMode,
|
||||
wayland_server::{
|
||||
backend::{ClientData, ClientId, DisconnectReason},
|
||||
@@ -23,10 +24,7 @@ use smithay::{
|
||||
compositor::CompositorState,
|
||||
dmabuf::{self, DmabufGlobal, DmabufHandler, DmabufState},
|
||||
output::OutputManagerState,
|
||||
shell::{
|
||||
kde::decoration::KdeDecorationState,
|
||||
xdg::{decoration::XdgDecorationState, XdgShellState},
|
||||
},
|
||||
shell::kde::decoration::KdeDecorationState,
|
||||
shm::{ShmHandler, ShmState},
|
||||
xdg_activation::XdgActivationState,
|
||||
},
|
||||
@@ -56,9 +54,7 @@ pub struct WaylandState {
|
||||
|
||||
pub compositor_state: CompositorState,
|
||||
pub xdg_activation_state: XdgActivationState,
|
||||
pub xdg_decoration_state: XdgDecorationState,
|
||||
pub kde_decoration_state: KdeDecorationState,
|
||||
pub xdg_shell_state: XdgShellState,
|
||||
pub shm_state: ShmState,
|
||||
pub dmabuf_state: DmabufState,
|
||||
pub dmabuf_global: DmabufGlobal,
|
||||
@@ -77,8 +73,6 @@ impl WaylandState {
|
||||
) -> Arc<Mutex<Self>> {
|
||||
let compositor_state = CompositorState::new::<Self, _>(&display_handle, log.clone());
|
||||
let xdg_activation_state = XdgActivationState::new::<Self, _>(&display_handle, log.clone());
|
||||
let xdg_shell_state = XdgShellState::new::<Self, _>(&display_handle, log.clone());
|
||||
let xdg_decoration_state = XdgDecorationState::new::<Self, _>(&display_handle, log.clone());
|
||||
let kde_decoration_state = KdeDecorationState::new::<Self, _>(
|
||||
&display_handle,
|
||||
DecorationMode::Server,
|
||||
@@ -113,6 +107,7 @@ impl WaylandState {
|
||||
None,
|
||||
);
|
||||
display_handle.create_global::<Self, WlDataDeviceManager, _>(3, ());
|
||||
display_handle.create_global::<Self, XdgWmBase, _>(5, ());
|
||||
|
||||
info!("Init Wayland compositor");
|
||||
|
||||
@@ -125,9 +120,7 @@ impl WaylandState {
|
||||
|
||||
compositor_state,
|
||||
xdg_activation_state,
|
||||
xdg_decoration_state,
|
||||
kde_decoration_state,
|
||||
xdg_shell_state,
|
||||
shm_state,
|
||||
dmabuf_state,
|
||||
dmabuf_global,
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::{
|
||||
nodes::drawable::model::Model,
|
||||
};
|
||||
use mint::Vector2;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use send_wrapper::SendWrapper;
|
||||
use slog::Logger;
|
||||
@@ -35,112 +36,75 @@ pub static CORE_SURFACES: Registry<CoreSurface> = Registry::new();
|
||||
|
||||
pub struct CoreSurfaceData {
|
||||
wl_tex: Option<SendWrapper<Gles2Texture>>,
|
||||
sk_tex: Option<SendWrapper<SKTexture>>,
|
||||
sk_mat: Option<Arc<SendWrapper<Material>>>,
|
||||
pub size: Vector2<u32>,
|
||||
}
|
||||
impl CoreSurfaceData {
|
||||
fn new(sk: &StereoKit) -> Self {
|
||||
let sk_tex = SendWrapper::new(
|
||||
SKTexture::create(sk, TextureType::ImageNoMips, TextureFormat::RGBA32).unwrap(),
|
||||
);
|
||||
let sk_mat = {
|
||||
let shader = Shader::from_mem(sk, PANEL_SHADER_BYTES).unwrap();
|
||||
let mat = Material::create(sk, &shader).unwrap();
|
||||
mat.set_parameter("diffuse", &*sk_tex);
|
||||
mat.set_transparency(Transparency::Blend);
|
||||
Arc::new(SendWrapper::new(mat))
|
||||
};
|
||||
CoreSurfaceData {
|
||||
wl_tex: None,
|
||||
sk_tex: Some(sk_tex),
|
||||
sk_mat: Some(sk_mat),
|
||||
size: Vector2::from([0, 0]),
|
||||
}
|
||||
}
|
||||
fn update_tex(
|
||||
&mut self,
|
||||
surface: &CoreSurface,
|
||||
data: &RendererSurfaceStateUserData,
|
||||
renderer_id: usize,
|
||||
) {
|
||||
if let Some(surface_size) = data.borrow().surface_size() {
|
||||
self.size = Vector2::from([surface_size.w as u32, surface_size.h as u32]);
|
||||
}
|
||||
self.wl_tex = data
|
||||
.borrow()
|
||||
.texture::<Gles2Renderer>(renderer_id)
|
||||
.cloned()
|
||||
.map(SendWrapper::new);
|
||||
if let Some(smithay_tex) = self.wl_tex.as_ref() {
|
||||
let sk_tex = self.sk_tex.as_ref().unwrap();
|
||||
unsafe {
|
||||
sk_tex.set_native(
|
||||
smithay_tex.tex_id() as usize,
|
||||
smithay::backend::renderer::gles2::ffi::RGBA8.into(),
|
||||
TextureType::ImageNoMips,
|
||||
smithay_tex.width(),
|
||||
smithay_tex.height(),
|
||||
false,
|
||||
);
|
||||
sk_tex.set_sample(TextureSample::Point);
|
||||
sk_tex.set_address_mode(TextureAddress::Clamp);
|
||||
}
|
||||
}
|
||||
if let Some(sk_mat) = &self.sk_mat {
|
||||
if let Some(material_offset) = surface.material_offset.lock().delta() {
|
||||
sk_mat.set_queue_offset(*material_offset as i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Drop for CoreSurfaceData {
|
||||
fn drop(&mut self) {
|
||||
destroy_queue::add(self.wl_tex.take());
|
||||
destroy_queue::add(self.sk_tex.take());
|
||||
destroy_queue::add(self.sk_mat.take());
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CoreSurface {
|
||||
display: Weak<Mutex<Display<WaylandState>>>,
|
||||
pub state: Weak<Mutex<WaylandState>>,
|
||||
pub dh: DisplayHandle,
|
||||
pub weak_surface: wayland_server::Weak<WlSurface>,
|
||||
mapped_data: Mutex<Option<CoreSurfaceData>>,
|
||||
sk_tex: OnceCell<SendWrapper<SKTexture>>,
|
||||
sk_mat: OnceCell<Arc<SendWrapper<Material>>>,
|
||||
material_offset: Mutex<Delta<u32>>,
|
||||
pub pending_material_applications: Mutex<Vec<(Arc<Model>, u32)>>,
|
||||
}
|
||||
|
||||
impl CoreSurface {
|
||||
pub fn new(
|
||||
state: &Arc<Mutex<WaylandState>>,
|
||||
pub fn add_to(
|
||||
display: &Arc<Mutex<Display<WaylandState>>>,
|
||||
dh: DisplayHandle,
|
||||
surface: &WlSurface,
|
||||
) -> Arc<Self> {
|
||||
CORE_SURFACES.add(CoreSurface {
|
||||
display: Arc::downgrade(display),
|
||||
state: Arc::downgrade(state),
|
||||
dh,
|
||||
weak_surface: surface.downgrade(),
|
||||
mapped_data: Mutex::new(None),
|
||||
material_offset: Mutex::new(Delta::new(0)),
|
||||
pending_material_applications: Mutex::new(Vec::new()),
|
||||
) {
|
||||
compositor::with_states(surface, |data| {
|
||||
data.data_map.insert_if_missing_threadsafe(|| {
|
||||
CORE_SURFACES.add(CoreSurface {
|
||||
display: Arc::downgrade(display),
|
||||
dh,
|
||||
weak_surface: surface.downgrade(),
|
||||
mapped_data: Mutex::new(None),
|
||||
sk_tex: OnceCell::new(),
|
||||
sk_mat: OnceCell::new(),
|
||||
material_offset: Mutex::new(Delta::new(0)),
|
||||
pending_material_applications: Mutex::new(Vec::new()),
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn from_wl_surface(surf: &WlSurface) -> Option<Arc<CoreSurface>> {
|
||||
compositor::with_states(surf, |data| {
|
||||
data.data_map.get::<Arc<CoreSurface>>().cloned()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process<F: FnOnce(&SurfaceData), M: FnOnce(&SurfaceData)>(
|
||||
pub fn process(
|
||||
&self,
|
||||
sk: &StereoKit,
|
||||
renderer: &mut Gles2Renderer,
|
||||
output: Output,
|
||||
log: &Logger,
|
||||
on_mapped: F,
|
||||
if_mapped: M,
|
||||
) {
|
||||
let Some(wl_surface) = self.wl_surface() else { return };
|
||||
|
||||
let sk_tex = self.sk_tex.get_or_init(|| {
|
||||
SendWrapper::new(
|
||||
SKTexture::create(sk, TextureType::ImageNoMips, TextureFormat::RGBA32).unwrap(),
|
||||
)
|
||||
});
|
||||
self.sk_mat.get_or_init(|| {
|
||||
let shader = Shader::from_mem(sk, PANEL_SHADER_BYTES).unwrap();
|
||||
let mat = Material::create(sk, &shader).unwrap();
|
||||
mat.set_parameter("diffuse", &**sk_tex);
|
||||
mat.set_transparency(Transparency::Blend);
|
||||
Arc::new(SendWrapper::new(mat))
|
||||
});
|
||||
|
||||
// Let smithay handle buffer management (has to be done here as RendererSurfaceStates is not thread safe)
|
||||
on_commit_buffer_handler(&wl_surface);
|
||||
// Import all surface buffers into textures
|
||||
@@ -160,26 +124,44 @@ impl CoreSurface {
|
||||
}
|
||||
|
||||
let mut mapped_data = self.mapped_data.lock();
|
||||
let just_mapped = mapped_data.is_none();
|
||||
if just_mapped {
|
||||
*mapped_data = Some(CoreSurfaceData::new(sk));
|
||||
}
|
||||
drop(mapped_data);
|
||||
self.with_states(|data| {
|
||||
self.with_data(|mapped_data| {
|
||||
mapped_data.update_tex(
|
||||
self,
|
||||
data.data_map.get::<RendererSurfaceStateUserData>().unwrap(),
|
||||
renderer.id(),
|
||||
);
|
||||
});
|
||||
self.apply_surface_materials();
|
||||
|
||||
let just_mapped = mapped_data.is_none();
|
||||
if just_mapped {
|
||||
on_mapped(data);
|
||||
let smithay_tex = data
|
||||
.data_map
|
||||
.get::<RendererSurfaceStateUserData>()
|
||||
.unwrap()
|
||||
.borrow()
|
||||
.texture::<Gles2Renderer>(renderer.id())
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
let sk_tex = self.sk_tex.get().unwrap();
|
||||
let sk_mat = self.sk_mat.get().unwrap();
|
||||
unsafe {
|
||||
sk_tex.set_native(
|
||||
smithay_tex.tex_id() as usize,
|
||||
smithay::backend::renderer::gles2::ffi::RGBA8.into(),
|
||||
TextureType::ImageNoMips,
|
||||
smithay_tex.width(),
|
||||
smithay_tex.height(),
|
||||
false,
|
||||
);
|
||||
sk_tex.set_sample(TextureSample::Point);
|
||||
sk_tex.set_address_mode(TextureAddress::Clamp);
|
||||
}
|
||||
if let Some(material_offset) = self.material_offset.lock().delta() {
|
||||
sk_mat.set_queue_offset(*material_offset as i32);
|
||||
}
|
||||
|
||||
let new_mapped_data = CoreSurfaceData {
|
||||
size: Vector2::from([smithay_tex.width(), smithay_tex.height()]),
|
||||
wl_tex: Some(SendWrapper::new(smithay_tex)),
|
||||
};
|
||||
*mapped_data = Some(new_mapped_data);
|
||||
}
|
||||
if_mapped(data);
|
||||
});
|
||||
self.apply_surface_materials();
|
||||
|
||||
send_frames_surface_tree(
|
||||
&wl_surface,
|
||||
@@ -190,6 +172,10 @@ impl CoreSurface {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn mapped(&self) -> bool {
|
||||
self.mapped_data.lock().is_some()
|
||||
}
|
||||
|
||||
pub fn set_material_offset(&self, material_offset: u32) {
|
||||
*self.material_offset.lock().value_mut() = material_offset;
|
||||
}
|
||||
@@ -201,32 +187,12 @@ impl CoreSurface {
|
||||
}
|
||||
|
||||
fn apply_surface_materials(&self) {
|
||||
self.with_data(|mapped_data| {
|
||||
let mut pending_material_applications = self.pending_material_applications.lock();
|
||||
for (model, material_idx) in &*pending_material_applications {
|
||||
model
|
||||
.pending_material_replacements
|
||||
.lock()
|
||||
.insert(*material_idx, mapped_data.sk_mat.clone().unwrap());
|
||||
}
|
||||
pending_material_applications.clear();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn pid(&self) -> Option<i32> {
|
||||
Some(
|
||||
self.weak_surface
|
||||
.upgrade()
|
||||
.ok()?
|
||||
.client()?
|
||||
.get_credentials(&self.dh)
|
||||
.ok()?
|
||||
.pid,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn wayland_state(&self) -> Arc<Mutex<WaylandState>> {
|
||||
self.state.upgrade().unwrap()
|
||||
for (model, material_idx) in self.pending_material_applications.lock().drain(0..) {
|
||||
model
|
||||
.pending_material_replacements
|
||||
.lock()
|
||||
.insert(material_idx, self.sk_mat.get().unwrap().clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wl_surface(&self) -> Option<WlSurface> {
|
||||
@@ -260,5 +226,8 @@ impl CoreSurface {
|
||||
impl Drop for CoreSurface {
|
||||
fn drop(&mut self) {
|
||||
CORE_SURFACES.remove(self);
|
||||
|
||||
destroy_queue::add(self.sk_tex.take());
|
||||
destroy_queue::add(self.sk_mat.take());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,69 +1,362 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::nodes::Node;
|
||||
|
||||
use super::{panel_item::PanelItem, state::WaylandState};
|
||||
use super::{
|
||||
panel_item::{PanelItem, ToplevelState},
|
||||
state::WaylandState,
|
||||
};
|
||||
use mint::Vector2;
|
||||
use parking_lot::Mutex;
|
||||
use serde::Serialize;
|
||||
use smithay::{
|
||||
delegate_xdg_shell,
|
||||
reexports::{
|
||||
wayland_protocols::xdg::{
|
||||
decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode,
|
||||
shell::server::xdg_toplevel::State,
|
||||
wayland_protocols::xdg::shell::server::{
|
||||
xdg_popup::{self, XdgPopup},
|
||||
xdg_positioner::{self, Anchor, ConstraintAdjustment, Gravity, XdgPositioner},
|
||||
xdg_surface::{self, XdgSurface},
|
||||
xdg_toplevel::{self, XdgToplevel},
|
||||
xdg_wm_base::{self, XdgWmBase},
|
||||
},
|
||||
wayland_server::protocol::{wl_seat::WlSeat, wl_surface::WlSurface},
|
||||
},
|
||||
utils::Serial,
|
||||
wayland::{
|
||||
compositor,
|
||||
shell::xdg::{
|
||||
Configure, PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler,
|
||||
XdgShellState,
|
||||
wayland_server::{
|
||||
protocol::wl_surface::WlSurface, Client, DataInit, Dispatch, DisplayHandle,
|
||||
GlobalDispatch, New, Resource, WEnum, Weak,
|
||||
},
|
||||
},
|
||||
wayland::compositor,
|
||||
};
|
||||
|
||||
impl XdgShellHandler for WaylandState {
|
||||
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
|
||||
&mut self.xdg_shell_state
|
||||
}
|
||||
// impl XdgShellHandler for WaylandState {
|
||||
// fn xdg_shell_state(&mut self) -> &mut WaylandState {
|
||||
// &mut self.xdg_shell_state
|
||||
// }
|
||||
|
||||
fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||
self.output.enter(surface.wl_surface());
|
||||
surface.with_pending_state(|state| {
|
||||
state.states.set(State::Maximized);
|
||||
state.states.set(State::Activated);
|
||||
state.decoration_mode = Some(Mode::ServerSide);
|
||||
});
|
||||
surface.send_configure();
|
||||
}
|
||||
fn ack_configure(&mut self, surface: WlSurface, configure: Configure) {
|
||||
// let size = match configure {
|
||||
// Configure::Toplevel(config) => config.state.size,
|
||||
// Configure::Popup(_) => return,
|
||||
// };
|
||||
// let core_surface = match configure {
|
||||
// Configure::Toplevel(config) => {
|
||||
// .and_then(|panel| panel.core_surface())
|
||||
// }
|
||||
// Configure::Popup(_) => return,
|
||||
// };
|
||||
let Some(panel_item_node) = compositor::with_states(&surface, |data| {
|
||||
data.data_map.get::<Arc<Node>>().cloned()
|
||||
}) else { return };
|
||||
let Some(panel_item) = PanelItem::from_node(&panel_item_node) else { return };
|
||||
panel_item.ack_resize(configure);
|
||||
// fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||
// self.output.enter(surface.wl_surface());
|
||||
// surface.with_pending_state(|state| {
|
||||
// state.states.set(State::Maximized);
|
||||
// state.states.set(State::Activated);
|
||||
// state.decoration_mode = Some(Mode::ServerSide);
|
||||
// });
|
||||
// surface.send_configure();
|
||||
|
||||
// let has_data = core_surface
|
||||
// .with_data(|data| {
|
||||
// data.size.x = size.w as u32;
|
||||
// data.size.y = size.h as u32;
|
||||
// })
|
||||
// .is_some();
|
||||
// if has_data {
|
||||
// }
|
||||
}
|
||||
// let client = surface.wl_surface().client().unwrap();
|
||||
// let (node, item) = PanelItem::create(
|
||||
// &surface,
|
||||
// client.get_credentials(&self.display_handle).ok(),
|
||||
// self.seats.get(&client.id()).unwrap().clone(),
|
||||
// );
|
||||
// compositor::with_states(surface.wl_surface(), |surface_data| {
|
||||
// surface_data.data_map.insert_if_missing_threadsafe(|| node);
|
||||
// surface_data.data_map.insert_if_missing_threadsafe(|| item);
|
||||
// });
|
||||
// }
|
||||
// fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
|
||||
// self.output.enter(surface.wl_surface());
|
||||
// let _ = surface.send_configure();
|
||||
// // let panel_item = compositor::with_states(&surface.get_parent_surface().unwrap(), |data| {
|
||||
// // data.data_map.get::<Arc<PanelItem>>().cloned()
|
||||
// // });
|
||||
// }
|
||||
// fn ack_configure(&mut self, surface: WlSurface, configure: Configure) {
|
||||
// compositor::with_states(&surface, |data| {
|
||||
// if let Some(panel_item) = data.data_map.get::<Arc<PanelItem>>() {
|
||||
// panel_item.ack_resize(configure);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {}
|
||||
fn grab(&mut self, _surface: PopupSurface, _seat: WlSeat, _serial: Serial) {}
|
||||
// fn grab(&mut self, _surface: PopupSurface, _seat: WlSeat, _serial: Serial) {}
|
||||
// }
|
||||
// delegate_xdg_shell!(WaylandState);
|
||||
|
||||
impl GlobalDispatch<XdgWmBase, (), WaylandState> for WaylandState {
|
||||
fn bind(
|
||||
_state: &mut WaylandState,
|
||||
_handle: &DisplayHandle,
|
||||
_client: &Client,
|
||||
resource: New<XdgWmBase>,
|
||||
_global_data: &(),
|
||||
data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
data_init.init(resource, ());
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct WaylandSurface {
|
||||
wl_surface: Weak<WlSurface>,
|
||||
size: Arc<Mutex<Vector2<u32>>>,
|
||||
}
|
||||
|
||||
impl Dispatch<XdgWmBase, (), WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
_resource: &XdgWmBase,
|
||||
request: xdg_wm_base::Request,
|
||||
_data: &(),
|
||||
_dhandle: &DisplayHandle,
|
||||
data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
xdg_wm_base::Request::CreatePositioner { id } => {
|
||||
data_init.init(id, Arc::new(Mutex::new(PositionerData::default())));
|
||||
}
|
||||
xdg_wm_base::Request::GetXdgSurface { id, surface } => {
|
||||
data_init.init(
|
||||
id,
|
||||
WaylandSurface {
|
||||
wl_surface: surface.downgrade(),
|
||||
size: Arc::new(Mutex::new(Vector2::from([0; 2]))),
|
||||
},
|
||||
);
|
||||
}
|
||||
xdg_wm_base::Request::Pong { serial: _ } => (),
|
||||
xdg_wm_base::Request::Destroy => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct PositionerData {
|
||||
size: Vector2<u32>,
|
||||
anchor_rect_pos: Vector2<i32>,
|
||||
anchor_rect_size: Vector2<u32>,
|
||||
anchor: u32,
|
||||
gravity: u32,
|
||||
constraint_adjustment: u32,
|
||||
offset: Vector2<i32>,
|
||||
reactive: bool,
|
||||
}
|
||||
impl Default for PositionerData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
size: Vector2::from([0; 2]),
|
||||
anchor_rect_pos: Vector2::from([0; 2]),
|
||||
anchor_rect_size: Vector2::from([0; 2]),
|
||||
anchor: Anchor::None as u32,
|
||||
gravity: Gravity::None as u32,
|
||||
constraint_adjustment: ConstraintAdjustment::None.bits(),
|
||||
offset: Vector2::from([0; 2]),
|
||||
reactive: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<XdgPositioner, Arc<Mutex<PositionerData>>, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
resource: &XdgPositioner,
|
||||
request: xdg_positioner::Request,
|
||||
data: &Arc<Mutex<PositionerData>>,
|
||||
_dhandle: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
xdg_positioner::Request::SetSize { width, height } => {
|
||||
data.lock().size = Vector2::from([width as u32, height as u32]);
|
||||
}
|
||||
xdg_positioner::Request::SetAnchorRect {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => {
|
||||
if width < 1 || height < 1 {
|
||||
resource.post_error(
|
||||
xdg_positioner::Error::InvalidInput,
|
||||
"Invalid size for positioner's anchor rectangle.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut data = data.lock();
|
||||
data.anchor_rect_pos = [x, y].into();
|
||||
data.anchor_rect_size = [width as u32, height as u32].into();
|
||||
}
|
||||
xdg_positioner::Request::SetAnchor { anchor } => {
|
||||
if let WEnum::Value(anchor) = anchor {
|
||||
data.lock().anchor = anchor as u32;
|
||||
}
|
||||
}
|
||||
xdg_positioner::Request::SetGravity { gravity } => {
|
||||
if let WEnum::Value(gravity) = gravity {
|
||||
data.lock().gravity = gravity as u32;
|
||||
}
|
||||
}
|
||||
xdg_positioner::Request::SetConstraintAdjustment {
|
||||
constraint_adjustment,
|
||||
} => {
|
||||
data.lock().constraint_adjustment = constraint_adjustment;
|
||||
}
|
||||
xdg_positioner::Request::SetOffset { x, y } => {
|
||||
data.lock().offset = [x, y].into();
|
||||
}
|
||||
xdg_positioner::Request::SetReactive => {
|
||||
data.lock().reactive = true;
|
||||
}
|
||||
xdg_positioner::Request::SetParentSize {
|
||||
parent_width: _,
|
||||
parent_height: _,
|
||||
} => (),
|
||||
xdg_positioner::Request::SetParentConfigure { serial: _ } => (),
|
||||
xdg_positioner::Request::Destroy => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct XdgSurfaceData {
|
||||
pub wl_surface: Weak<WlSurface>,
|
||||
pub xdg_surface: Weak<XdgSurface>,
|
||||
pub size: Arc<Mutex<Vector2<u32>>>,
|
||||
}
|
||||
impl Dispatch<XdgSurface, WaylandSurface, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
state: &mut WaylandState,
|
||||
client: &Client,
|
||||
xdg_surface: &XdgSurface,
|
||||
request: xdg_surface::Request,
|
||||
data: &WaylandSurface,
|
||||
_dhandle: &DisplayHandle,
|
||||
data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
xdg_surface::Request::GetToplevel { id } => {
|
||||
let toplevel_state = Arc::new(Mutex::new(ToplevelState {
|
||||
queued_state: Some(Box::new(ToplevelState::default())),
|
||||
..Default::default()
|
||||
}));
|
||||
let toplevel = data_init.init(
|
||||
id,
|
||||
XdgToplevelData {
|
||||
state: toplevel_state,
|
||||
xdg_surface_data: XdgSurfaceData {
|
||||
wl_surface: data.wl_surface.clone(),
|
||||
xdg_surface: xdg_surface.downgrade(),
|
||||
size: data.size.clone(),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
toplevel.configure(0, 0, vec![]);
|
||||
xdg_surface.configure(0);
|
||||
|
||||
let (node, item) = PanelItem::create(
|
||||
toplevel,
|
||||
client.get_credentials(&state.display_handle).ok(),
|
||||
state.seats.get(&client.id()).unwrap().clone(),
|
||||
);
|
||||
compositor::with_states(&data.wl_surface.upgrade().unwrap(), |surface_data| {
|
||||
surface_data.data_map.insert_if_missing_threadsafe(|| node);
|
||||
surface_data.data_map.insert_if_missing_threadsafe(|| item);
|
||||
});
|
||||
}
|
||||
xdg_surface::Request::GetPopup {
|
||||
id,
|
||||
parent: _,
|
||||
positioner: _,
|
||||
} => {
|
||||
data_init.init(id, ());
|
||||
}
|
||||
xdg_surface::Request::SetWindowGeometry {
|
||||
x: _,
|
||||
y: _,
|
||||
width,
|
||||
height,
|
||||
} => {
|
||||
*data.size.lock() = Vector2::from([width as u32, height as u32]);
|
||||
}
|
||||
xdg_surface::Request::AckConfigure { serial: _ } => (),
|
||||
xdg_surface::Request::Destroy => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct XdgToplevelData {
|
||||
pub state: Arc<Mutex<ToplevelState>>,
|
||||
pub xdg_surface_data: XdgSurfaceData,
|
||||
}
|
||||
impl Dispatch<XdgToplevel, XdgToplevelData, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
_resource: &XdgToplevel,
|
||||
request: xdg_toplevel::Request,
|
||||
data: &XdgToplevelData,
|
||||
_dhandle: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
xdg_toplevel::Request::SetParent { parent } => {
|
||||
let mut state = data.state.lock();
|
||||
let queued_state = state.queued_state.as_mut().unwrap();
|
||||
queued_state.parent = parent.map(|toplevel| toplevel.downgrade());
|
||||
}
|
||||
xdg_toplevel::Request::SetTitle { title } => {
|
||||
let mut state = data.state.lock();
|
||||
let queued_state = state.queued_state.as_mut().unwrap();
|
||||
queued_state.title = title;
|
||||
}
|
||||
xdg_toplevel::Request::SetAppId { app_id } => {
|
||||
let mut state = data.state.lock();
|
||||
let queued_state = state.queued_state.as_mut().unwrap();
|
||||
queued_state.app_id = app_id;
|
||||
}
|
||||
xdg_toplevel::Request::ShowWindowMenu {
|
||||
seat: _,
|
||||
serial: _,
|
||||
x: _,
|
||||
y: _,
|
||||
} => (),
|
||||
xdg_toplevel::Request::Move { seat: _, serial: _ } => (),
|
||||
xdg_toplevel::Request::Resize {
|
||||
seat: _,
|
||||
serial: _,
|
||||
edges: _,
|
||||
} => (),
|
||||
xdg_toplevel::Request::SetMaxSize { width, height } => {
|
||||
let mut state = data.state.lock();
|
||||
let queued_state = state.queued_state.as_mut().unwrap();
|
||||
queued_state.max_size = Vector2::from([width as u32, height as u32]);
|
||||
}
|
||||
xdg_toplevel::Request::SetMinSize { width, height } => {
|
||||
let mut state = data.state.lock();
|
||||
let queued_state = state.queued_state.as_mut().unwrap();
|
||||
queued_state.min_size = Vector2::from([width as u32, height as u32]);
|
||||
}
|
||||
xdg_toplevel::Request::SetMaximized => (),
|
||||
xdg_toplevel::Request::UnsetMaximized => (),
|
||||
xdg_toplevel::Request::SetFullscreen { output: _ } => (),
|
||||
xdg_toplevel::Request::UnsetFullscreen => (),
|
||||
xdg_toplevel::Request::SetMinimized => (),
|
||||
xdg_toplevel::Request::Destroy => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<XdgPopup, (), WaylandState> for WaylandState {
|
||||
fn request(
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
_resource: &XdgPopup,
|
||||
request: xdg_popup::Request,
|
||||
_data: &(),
|
||||
_dhandle: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
xdg_popup::Request::Grab { seat: _, serial: _ } => (),
|
||||
xdg_popup::Request::Reposition {
|
||||
positioner: _,
|
||||
token: _,
|
||||
} => (),
|
||||
xdg_popup::Request::Destroy => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate_xdg_shell!(WaylandState);
|
||||
|
||||
Reference in New Issue
Block a user