diff --git a/src/client.rs b/src/client.rs index 8ce8ee5d..0d408eb1 100644 --- a/src/client.rs +++ b/src/client.rs @@ -10,13 +10,13 @@ use { wl_display::WlDisplay, wl_registry::WlRegistry, wl_surface::{WlSurface, commit_timeline::CommitTimelines}, + xdg_activation_token_v1::ActivationToken, }, leaks::Tracker, object::{Interface, Object, ObjectId, WL_DISPLAY_ID}, security_context_acceptor::AcceptorMetadata, state::State, utils::{ - activation_token::ActivationToken, asyncevent::AsyncEvent, buffd::{MsgFormatter, MsgParser, MsgParserError, OutBufferSwapchain}, copyhashmap::{CopyHashMap, Locked}, diff --git a/src/config.rs b/src/config.rs index 5e1b7c49..64ff595f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -9,13 +9,12 @@ use { config::handler::ConfigProxyHandler, ifs::wl_seat::SeatId, state::State, - tree::{TileState, ToplevelData}, + tree::{TileState, ToplevelData, ToplevelIdentifier}, utils::{ clonecell::CloneCell, nice::{JAY_NO_REALTIME, dont_allow_config_so}, numcell::NumCell, ptr_ext::PtrExt, - toplevel_identifier::ToplevelIdentifier, unlink_on_drop::UnlinkOnDrop, xrd::xrd, }, diff --git a/src/config/handler.rs b/src/config/handler.rs index 1979dc38..1d07e1c6 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -28,8 +28,8 @@ use { tagged_acceptor::TaggedAcceptorError, theme::{ThemeColor, ThemeSized}, tree::{ - ContainerSplit, OutputNode, TearingMode, TileState, ToplevelData, ToplevelNode, - VrrMode, WorkspaceNode, toplevel_create_split, toplevel_parent_container, + ContainerSplit, OutputNode, TearingMode, TileState, ToplevelData, ToplevelIdentifier, + ToplevelNode, VrrMode, WorkspaceNode, toplevel_create_split, toplevel_parent_container, toplevel_set_floating, toplevel_set_workspace, }, utils::{ @@ -40,7 +40,6 @@ use { oserror::{OsError, OsErrorExt}, stack::Stack, timer::{TimerError, TimerFd}, - toplevel_identifier::ToplevelIdentifier, }, }, bincode::Options, diff --git a/src/control_center/cc_clients.rs b/src/control_center/cc_clients.rs index 1a1bd7b3..75e52d67 100644 --- a/src/control_center/cc_clients.rs +++ b/src/control_center/cc_clients.rs @@ -10,11 +10,8 @@ use { criteria::{CritMgrExt, CritUpstreamNode, crit_leaf::CritLeafMatcher}, egui_adapter::egui_platform::icons::ICON_OPEN_IN_NEW, state::State, - tree::ToplevelData, - utils::{ - copyhashmap::CopyHashMap, static_text::StaticText, - toplevel_identifier::ToplevelIdentifier, - }, + tree::{ToplevelData, ToplevelIdentifier}, + utils::{copyhashmap::CopyHashMap, static_text::StaticText}, }, ahash::AHashMap, egui::{ diff --git a/src/control_center/cc_window.rs b/src/control_center/cc_window.rs index 5da2c927..34974033 100644 --- a/src/control_center/cc_window.rs +++ b/src/control_center/cc_window.rs @@ -9,12 +9,11 @@ use { criteria::{CritMgrExt, CritUpstreamNode, crit_leaf::CritLeafMatcher}, egui_adapter::egui_platform::icons::ICON_OPEN_IN_NEW, state::State, - tree::{NodeId, ToplevelData, ToplevelNode, ToplevelType}, + tree::{NodeId, ToplevelData, ToplevelIdentifier, ToplevelNode, ToplevelType}, utils::{ copyhashmap::CopyHashMap, event_listener::{EventListener, LazyEventSourceListener}, static_text::StaticText, - toplevel_identifier::ToplevelIdentifier, }, }, ahash::AHashMap, diff --git a/src/criteria/tlm.rs b/src/criteria/tlm.rs index a4fe005d..d7b5bece 100644 --- a/src/criteria/tlm.rs +++ b/src/criteria/tlm.rs @@ -29,11 +29,8 @@ use { }, ifs::wl_seat::WlSeatGlobal, state::State, - tree::{NodeId, ToplevelData, ToplevelNode}, - utils::{ - copyhashmap::CopyHashMap, hash_map_ext::HashMapExt, queue::AsyncQueue, - toplevel_identifier::ToplevelIdentifier, - }, + tree::{NodeId, ToplevelData, ToplevelIdentifier, ToplevelNode}, + utils::{copyhashmap::CopyHashMap, hash_map_ext::HashMapExt, queue::AsyncQueue}, }, jay_config::window::{ContentType, WindowType}, linearize::static_map, diff --git a/src/gfx_apis/gl.rs b/src/gfx_apis/gl.rs index 1e974f6a..5f1b63e3 100644 --- a/src/gfx_apis/gl.rs +++ b/src/gfx_apis/gl.rs @@ -18,53 +18,6 @@ macro_rules! egl_transparent { }; } -macro_rules! dynload { - ( - $item:ident: $container:ident from $name:literal { - $( - $fun:ident: $ty:ty, - )* - } - ) => { - #[expect(non_snake_case)] - #[derive(Debug)] - pub struct $container { - _lib: libloading::Library, - $( - pub $fun: $ty, - )* - } - - pub static $item: std::sync::LazyLock> = std::sync::LazyLock::new(|| unsafe { - use crate::utils::errorfmt::ErrorFmt; - let lib = match libloading::Library::new($name) { - Ok(l) => l, - Err(e) => { - log::error!("Could not load lib{}: {}", $name, ErrorFmt(e)); - return None; - } - }; - $( - #[expect(non_snake_case)] - let $fun: $ty = - match lib.get(stringify!($fun).as_bytes()) { - Ok(s) => *s, - Err(e) => { - log::error!("Could not load {} from {}: {}", stringify!($fun), $name, ErrorFmt(e)); - return None; - } - }; - )* - Some($container { - _lib: lib, - $( - $fun, - )* - }) - }); - }; -} - use { crate::{ cmm::cmm_eotf::Eotf, diff --git a/src/ifs/jay_compositor.rs b/src/ifs/jay_compositor.rs index c406b87c..90c4f3ae 100644 --- a/src/ifs/jay_compositor.rs +++ b/src/ifs/jay_compositor.rs @@ -30,7 +30,8 @@ use { leaks::Tracker, object::{Object, Version}, screenshoter::take_screenshot, - utils::{errorfmt::ErrorFmt, toplevel_identifier::ToplevelIdentifier}, + tree::ToplevelIdentifier, + utils::errorfmt::ErrorFmt, wire::{ JayCompositorId, JayScreenshotId, jay_compositor::{self, *}, diff --git a/src/ifs/jay_tree_query.rs b/src/ifs/jay_tree_query.rs index 1a381b35..27493eb5 100644 --- a/src/ifs/jay_tree_query.rs +++ b/src/ifs/jay_tree_query.rs @@ -16,9 +16,10 @@ use { rect::Rect, tree::{ self, ContainerNode, DisplayNode, FloatNode, Node, NodeVisitor, OutputNode, - PlaceholderNode, ToplevelData, ToplevelNodeBase, ToplevelType, WorkspaceNode, + PlaceholderNode, ToplevelData, ToplevelIdentifier, ToplevelNodeBase, ToplevelType, + WorkspaceNode, }, - utils::{opaque::OpaqueError, opt::Opt, toplevel_identifier::ToplevelIdentifier}, + utils::{opaque::OpaqueError, opt::Opt}, wire::{JayTreeQueryId, jay_tree_query::*}, }, isnt::std_1::primitive::IsntStrExt, diff --git a/src/ifs/xdg_activation_token_v1.rs b/src/ifs/xdg_activation_token_v1.rs index 1209ada9..e00fb440 100644 --- a/src/ifs/xdg_activation_token_v1.rs +++ b/src/ifs/xdg_activation_token_v1.rs @@ -3,13 +3,14 @@ use { client::{Client, ClientError}, leaks::Tracker, object::{Object, Version}, - utils::activation_token::{ActivationToken, activation_token}, wire::{XdgActivationTokenV1Id, xdg_activation_token_v1::*}, }, std::{cell::Cell, rc::Rc}, thiserror::Error, }; +opaque!(ActivationToken, activation_token); + const MAX_TOKENS_PER_CLIENT: usize = 8; pub struct XdgActivationTokenV1 { diff --git a/src/ifs/xdg_activation_v1.rs b/src/ifs/xdg_activation_v1.rs index f9879444..ae12af5f 100644 --- a/src/ifs/xdg_activation_v1.rs +++ b/src/ifs/xdg_activation_v1.rs @@ -2,10 +2,10 @@ use { crate::{ client::{Client, ClientError}, globals::{Global, GlobalName}, - ifs::xdg_activation_token_v1::XdgActivationTokenV1, + ifs::xdg_activation_token_v1::{ActivationToken, XdgActivationTokenV1}, leaks::Tracker, object::{Object, Version}, - utils::{activation_token::ActivationToken, errorfmt::ErrorFmt, opaque::OpaqueError}, + utils::{errorfmt::ErrorFmt, opaque::OpaqueError}, wire::{XdgActivationV1Id, xdg_activation_v1::*}, }, std::rc::Rc, diff --git a/src/macros.rs b/src/macros.rs index 99fd01a4..b5088a23 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -853,3 +853,83 @@ macro_rules! dbg { } }; } + +macro_rules! dynload { + ( + $item:ident: $container:ident from $name:literal { + $( + $fun:ident: $ty:ty, + )* + } + ) => { + #[expect(non_snake_case)] + #[derive(Debug)] + pub struct $container { + _lib: libloading::Library, + $( + pub $fun: $ty, + )* + } + + pub static $item: std::sync::LazyLock> = std::sync::LazyLock::new(|| unsafe { + use crate::utils::errorfmt::ErrorFmt; + let lib = match libloading::Library::new($name) { + Ok(l) => l, + Err(e) => { + log::error!("Could not load {}: {}", $name, ErrorFmt(e)); + return None; + } + }; + $( + #[allow(clippy::allow_attributes, non_snake_case)] + let $fun: $ty = + match lib.get(stringify!($fun).as_bytes()) { + Ok(s) => *s, + Err(e) => { + log::error!("Could not load {} from {}: {}", stringify!($fun), $name, ErrorFmt(e)); + return None; + } + }; + )* + Some($container { + _lib: lib, + $( + $fun, + )* + }) + }); + }; +} + +macro_rules! opaque { + ($ty:ident, $fun:ident) => { + #[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, Ord, PartialOrd)] + pub struct $ty(crate::utils::opaque::Opaque); + + unsafe impl crate::utils::clonecell::UnsafeCellCloneSafe for $ty {} + + pub fn $fun() -> $ty { + $ty(crate::utils::opaque::opaque()) + } + + impl $ty { + pub fn to_string(self) -> arrayvec::ArrayString<{ crate::utils::opaque::OPAQUE_LEN }> { + self.0.to_string() + } + } + + impl std::fmt::Display for $ty { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } + } + + impl std::str::FromStr for $ty { + type Err = crate::utils::opaque::OpaqueError; + + fn from_str(s: &str) -> Result { + Ok(Self(s.parse()?)) + } + } + }; +} diff --git a/src/state.rs b/src/state.rs index 03a949dc..30f2c5ad 100644 --- a/src/state.rs +++ b/src/state.rs @@ -87,6 +87,7 @@ use { workspace_manager::WorkspaceManagerState, wp_drm_lease_connector_v1::WpDrmLeaseConnectorV1, wp_drm_lease_device_v1::WpDrmLeaseDeviceV1Global, + xdg_activation_token_v1::ActivationToken, zwlr_foreign_toplevel_manager_v1::ZwlrForeignToplevelManagerV1, zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1, @@ -107,13 +108,12 @@ use { tree::{ ContainerNode, ContainerSplit, Direction, DisplayNode, FindTreeUsecase, FloatNode, FoundNode, LatchListener, Node, NodeIds, NodeVisitorBase, OutputNode, PlaceholderNode, - TearingMode, TileState, ToplevelData, ToplevelNode, ToplevelNodeBase, Transform, - VrrMode, WorkspaceDisplayOrder, WorkspaceNode, WsMoveConfig, generic_node_visitor, - move_ws_to_output, + TearingMode, TileState, ToplevelData, ToplevelIdentifier, ToplevelNode, + ToplevelNodeBase, Transform, VrrMode, WorkspaceDisplayOrder, WorkspaceNode, + WsMoveConfig, generic_node_visitor, move_ws_to_output, }, udmabuf::UdmabufHolder, utils::{ - activation_token::ActivationToken, asyncevent::AsyncEvent, bindings::Bindings, clonecell::CloneCell, @@ -128,7 +128,6 @@ use { queue::AsyncQueue, refcounted::RefCounted, run_toplevel::RunToplevel, - toplevel_identifier::ToplevelIdentifier, }, video::{ dmabuf::DmaBufIds, diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index 4f7d77e1..5b2167c9 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -31,15 +31,9 @@ use { NodeLayerLink, OutputNode, PlaceholderNode, WorkspaceNode, }, utils::{ - array_to_tuple::ArrayToTuple, - clonecell::CloneCell, - copyhashmap::CopyHashMap, - event_listener::LazyEventSource, - hash_map_ext::HashMapExt, - numcell::NumCell, - rc_eq::rc_eq, - threshold_counter::ThresholdCounter, - toplevel_identifier::{ToplevelIdentifier, toplevel_identifier}, + array_to_tuple::ArrayToTuple, clonecell::CloneCell, copyhashmap::CopyHashMap, + event_listener::LazyEventSource, hash_map_ext::HashMapExt, numcell::NumCell, + rc_eq::rc_eq, threshold_counter::ThresholdCounter, }, wire::{ ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayScreencastId, @@ -55,6 +49,8 @@ use { }, }; +opaque!(ToplevelIdentifier, toplevel_identifier); + tree_id!(ToplevelNodeId); pub trait ToplevelNode: ToplevelNodeBase { diff --git a/src/utils.rs b/src/utils.rs index 31cadb59..1dbf2bac 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,3 @@ -pub mod activation_token; pub mod array; pub mod array_to_tuple; pub mod asyncevent; @@ -60,7 +59,6 @@ pub mod string_ext; pub mod syncqueue; pub mod threshold_counter; pub mod timer; -pub mod toplevel_identifier; pub mod tri; pub mod unlink_on_drop; pub mod vec_ext; diff --git a/src/utils/activation_token.rs b/src/utils/activation_token.rs deleted file mode 100644 index 7296b21c..00000000 --- a/src/utils/activation_token.rs +++ /dev/null @@ -1,35 +0,0 @@ -use { - crate::utils::opaque::{OPAQUE_LEN, Opaque, OpaqueError, opaque}, - arrayvec::ArrayString, - std::{ - fmt::{Display, Formatter}, - str::FromStr, - }, -}; - -#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] -pub struct ActivationToken(Opaque); - -pub fn activation_token() -> ActivationToken { - ActivationToken(opaque()) -} - -impl ActivationToken { - pub fn to_string(self) -> ArrayString { - self.0.to_string() - } -} - -impl Display for ActivationToken { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } -} - -impl FromStr for ActivationToken { - type Err = OpaqueError; - - fn from_str(s: &str) -> Result { - Ok(Self(s.parse()?)) - } -} diff --git a/src/utils/opaque.rs b/src/utils/opaque.rs index 209e77a9..2f2c58a4 100644 --- a/src/utils/opaque.rs +++ b/src/utils/opaque.rs @@ -1,4 +1,5 @@ use { + crate::utils::array, arrayvec::ArrayString, rand::{RngExt, rng}, serde::{Deserialize, Deserializer, Serialize, Serializer, de}, @@ -10,17 +11,19 @@ use { thiserror::Error, }; +#[cfg(test)] +mod tests; + #[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] +#[repr(transparent)] pub struct Opaque { - lo: u64, - hi: u64, + v: [u64; 3], } pub fn opaque() -> Opaque { let mut rng = rng(); Opaque { - lo: rng.random(), - hi: rng.random(), + v: array::from_fn(|_| rng.random()), } } @@ -35,8 +38,9 @@ impl Opaque { impl Display for Opaque { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{:016x}", self.hi)?; - write!(f, "{:016x}", self.lo)?; + write!(f, "{:016x}", self.v[2])?; + write!(f, "{:016x}", self.v[1])?; + write!(f, "{:016x}", self.v[0])?; Ok(()) } } @@ -72,24 +76,32 @@ impl FromStr for Opaque { fn from_str(s: &str) -> Result { if s.len() != OPAQUE_LEN { - return Err(OpaqueError::InvalidLength); + return Err(OpaqueError::InvalidStringLength); } - if !s.is_char_boundary(OPAQUE_LEN / 2) { + if !s.is_char_boundary(OPAQUE_SEGMENT) { return Err(OpaqueError::NotAscii); } - let (hi, lo) = s.split_at(OPAQUE_LEN / 2); - let hi = u64::from_str_radix(hi, 16).map_err(OpaqueError::Parse)?; - let lo = u64::from_str_radix(lo, 16).map_err(OpaqueError::Parse)?; - Ok(Self { lo, hi }) + let (a, s) = s.split_at(OPAQUE_SEGMENT); + if !s.is_char_boundary(OPAQUE_SEGMENT) { + return Err(OpaqueError::NotAscii); + } + let (b, c) = s.split_at(OPAQUE_SEGMENT); + let v = [ + u64::from_str_radix(c, 16).map_err(OpaqueError::Parse)?, + u64::from_str_radix(b, 16).map_err(OpaqueError::Parse)?, + u64::from_str_radix(a, 16).map_err(OpaqueError::Parse)?, + ]; + Ok(Self { v }) } } -pub const OPAQUE_LEN: usize = 32; +pub const OPAQUE_LEN: usize = 48; +const OPAQUE_SEGMENT: usize = OPAQUE_LEN / 3; #[derive(Debug, Error)] pub enum OpaqueError { - #[error("The string is not exactly 32 bytes long")] - InvalidLength, + #[error("The string is not exactly {OPAQUE_LEN} bytes long")] + InvalidStringLength, #[error("The string is not ascii")] NotAscii, #[error("Could not parse the string as a hex number")] diff --git a/src/utils/opaque/tests.rs b/src/utils/opaque/tests.rs new file mode 100644 index 00000000..b9a8aa59 --- /dev/null +++ b/src/utils/opaque/tests.rs @@ -0,0 +1,12 @@ +use { + crate::utils::opaque::{Opaque, opaque}, + std::str::FromStr, +}; + +#[test] +fn roundtrip() { + let v1 = opaque(); + let s = v1.to_string(); + let v2 = Opaque::from_str(&s).unwrap(); + assert_eq!(v1, v2); +} diff --git a/src/utils/toplevel_identifier.rs b/src/utils/toplevel_identifier.rs deleted file mode 100644 index e9b1f30b..00000000 --- a/src/utils/toplevel_identifier.rs +++ /dev/null @@ -1,40 +0,0 @@ -use { - crate::utils::{ - clonecell::UnsafeCellCloneSafe, - opaque::{OPAQUE_LEN, Opaque, OpaqueError, opaque}, - }, - arrayvec::ArrayString, - std::{ - fmt::{Display, Formatter}, - str::FromStr, - }, -}; - -#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, Ord, PartialOrd)] -pub struct ToplevelIdentifier(Opaque); - -unsafe impl UnsafeCellCloneSafe for ToplevelIdentifier {} - -pub fn toplevel_identifier() -> ToplevelIdentifier { - ToplevelIdentifier(opaque()) -} - -impl ToplevelIdentifier { - pub fn to_string(self) -> ArrayString { - self.0.to_string() - } -} - -impl Display for ToplevelIdentifier { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } -} - -impl FromStr for ToplevelIdentifier { - type Err = OpaqueError; - - fn from_str(s: &str) -> Result { - Ok(Self(s.parse()?)) - } -}