diff --git a/Cargo.lock b/Cargo.lock index 0dce200a..2ecee160 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -745,6 +745,7 @@ dependencies = [ "jay-libinput", "jay-logger", "jay-output-schedule", + "jay-output-types", "jay-pango", "jay-pr-caps", "jay-sighand", @@ -995,6 +996,13 @@ dependencies = [ "num-traits", ] +[[package]] +name = "jay-output-types" +version = "0.1.0" +dependencies = [ + "blake3", +] + [[package]] name = "jay-pango" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index b93ad9f0..b3c24f84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ members = [ "bugs", "logger", "video-types", + "output-types", "input-types", "keyboard", "gfx-types", @@ -99,6 +100,7 @@ jay-pr-caps = { version = "0.1.0", path = "pr-caps" } jay-bugs = { version = "0.1.0", path = "bugs" } jay-logger = { version = "0.1.0", path = "logger" } jay-video-types = { version = "0.1.0", path = "video-types" } +jay-output-types = { version = "0.1.0", path = "output-types" } jay-input-types = { version = "0.1.0", path = "input-types" } jay-keyboard = { version = "0.1.0", path = "keyboard" } jay-gfx-types = { version = "0.1.0", path = "gfx-types" } diff --git a/output-types/Cargo.toml b/output-types/Cargo.toml new file mode 100644 index 00000000..cbc26574 --- /dev/null +++ b/output-types/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "jay-output-types" +version = "0.1.0" +edition = "2024" +license = "GPL-3.0-only" +description = "Output identity types for the Jay compositor" +repository = "https://github.com/mahkoh/jay" + +[dependencies] +blake3 = "1.8.2" diff --git a/output-types/src/lib.rs b/output-types/src/lib.rs new file mode 100644 index 00000000..9d3bb80e --- /dev/null +++ b/output-types/src/lib.rs @@ -0,0 +1,77 @@ +use { + std::{ + hash::{Hash, Hasher}, + rc::Rc, + }, +}; + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct OutputIdHash(pub [u8; 32]); + +impl OutputIdHash { + pub fn hash(t: impl AsRef<[u8]>) -> Self { + Self(*blake3::hash(t.as_ref()).as_bytes()) + } +} + +#[derive(Eq, Debug)] +pub struct OutputId { + pub _connector: Option, + pub manufacturer: String, + pub model: String, + pub serial_number: String, + pub hash: OutputIdHash, +} + +impl PartialEq for OutputId { + fn eq(&self, other: &Self) -> bool { + self.hash == other.hash + } +} + +impl Hash for OutputId { + fn hash(&self, state: &mut H) { + self.hash.hash(state); + } +} + +impl OutputId { + pub fn new( + connector: impl Into, + manufacturer: impl Into, + model: impl Into, + serial_number: impl Into, + ) -> Rc { + let connector = connector.into(); + let manufacturer = manufacturer.into(); + let model = model.into(); + let serial_number = serial_number.into(); + Self::new_(connector, manufacturer, model, serial_number) + } + + fn new_( + connector: String, + manufacturer: String, + model: String, + serial_number: String, + ) -> Rc { + let connector = serial_number.is_empty().then_some(connector); + let mut hasher = blake3::Hasher::new(); + hasher.update(&[connector.is_some() as u8]); + let mut hash = |s: &str| { + hasher.update(&(s.len() as u64).to_le_bytes()); + hasher.update(s.as_bytes()); + }; + connector.as_deref().map(&mut hash); + hash(&manufacturer); + hash(&model); + hash(&serial_number); + Rc::new(Self { + _connector: connector, + manufacturer, + model, + serial_number, + hash: OutputIdHash(*hasher.finalize().as_bytes()), + }) + } +} diff --git a/src/backend.rs b/src/backend.rs index 55aa6e8e..f903995b 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -10,7 +10,6 @@ use { fixed::Fixed, format::Format, gfx_api::{FdSync, GfxApi, GfxFramebuffer}, - ifs::wl_output::OutputId, libinput::consts::DeviceCapability, utils::static_text::StaticText, video::drm::{ @@ -33,6 +32,8 @@ use { pub mod transaction; +pub use jay_output_types::OutputId; + pub use jay_input_types::{ AXIS_120, AxisSource, ButtonState, InputDeviceAccelProfile, InputDeviceClickMethod, InputDeviceGroupId, InputDeviceGroupIds, KeyState, Leds, PadButtonState, ScrollAxis, TabletId, diff --git a/src/backends/metal.rs b/src/backends/metal.rs index 7f2cdb09..d5fad637 100644 --- a/src/backends/metal.rs +++ b/src/backends/metal.rs @@ -11,8 +11,8 @@ use { backend::{ Backend, ButtonState, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceClickMethod, InputDeviceGroupId, InputDeviceId, InputEvent, KeyState, Leds, - TabletId, TabletInit, TabletPadGroupInit, TabletPadId, TabletPadInit, TransformMatrix, - transaction::BackendConnectorTransactionError, + OutputId, TabletId, TabletInit, TabletPadGroupInit, TabletPadId, TabletPadInit, + TransformMatrix, transaction::BackendConnectorTransactionError, }, backends::metal::{ allocator::{RenderBufferError, ScanoutBufferError, ScanoutBufferErrors}, @@ -24,7 +24,6 @@ use { dbus::{DbusError, SignalHandler}, drm_feedback::DrmFeedback, gfx_api::{GfxError, SyncFile}, - ifs::wl_output::OutputId, libinput::{ LibInput, LibInputAdapter, LibInputError, consts::{ diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 64dc1c59..31f68433 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -6,7 +6,7 @@ use { BackendDrmLessee, BackendEotfs, BackendEvent, BackendGammaLut, BackendGammaLutElement, BackendLuminance, CONCAP_CONNECTOR, CONCAP_MODE_SETTING, CONCAP_PHYSICAL_DISPLAY, Connector, ConnectorCaps, ConnectorEvent, ConnectorId, ConnectorKernelId, DrmDeviceId, - HardwareCursor, HardwareCursorUpdate, Mode, MonitorInfo, + HardwareCursor, HardwareCursorUpdate, Mode, MonitorInfo, OutputId, transaction::{ BackendConnectorTransaction, BackendConnectorTransactionError, BackendConnectorTransactionType, BackendConnectorTransactionTypeDyn, @@ -27,10 +27,7 @@ use { edid::{CtaDataBlock, Descriptor, EdidExtension}, format::{Format, XRGB8888}, gfx_api::{FdSync, GfxApi, GfxContext, GfxFramebuffer}, - ifs::{ - wl_output::OutputId, - wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC, KIND_ZERO_COPY}, - }, + ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC, KIND_ZERO_COPY}, state::State, tree::OutputNode, udev::UdevDevice, diff --git a/src/backends/x.rs b/src/backends/x.rs index a843f391..7309cf2c 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -7,7 +7,7 @@ use { ButtonState, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, DrmDeviceId, DrmEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceClickMethod, InputDeviceId, InputEvent, KeyState, Mode, MonitorInfo, - ScrollAxis, TransformMatrix, + OutputId, ScrollAxis, TransformMatrix, transaction::{ BackendAppliedConnectorTransaction, BackendConnectorTransaction, BackendConnectorTransactionError, BackendConnectorTransactionType, @@ -20,7 +20,6 @@ use { gfx_api::{ AcquireSync, GfxApi, GfxContext, GfxError, GfxFramebuffer, GfxTexture, ReleaseSync, }, - ifs::wl_output::OutputId, state::State, time::Time, utils::{ diff --git a/src/ifs/wl_output.rs b/src/ifs/wl_output.rs index 851fdf79..e45b2ce8 100644 --- a/src/ifs/wl_output.rs +++ b/src/ifs/wl_output.rs @@ -33,12 +33,13 @@ use { std::{ cell::{Cell, RefCell}, collections::hash_map::Entry, - hash::{Hash, Hasher}, rc::Rc, }, thiserror::Error, }; +pub use jay_output_types::OutputId; + const SP_UNKNOWN: i32 = 0; #[expect(dead_code)] const SP_NONE: i32 = 1; @@ -173,70 +174,6 @@ impl Default for PersistentOutputState { } } -#[derive(Eq, Debug)] -pub struct OutputId { - pub _connector: Option, - pub manufacturer: String, - pub model: String, - pub serial_number: String, - pub hash: OutputIdHash, -} - -hash_type!(OutputIdHash); - -impl PartialEq for OutputId { - fn eq(&self, other: &Self) -> bool { - self.hash == other.hash - } -} - -impl Hash for OutputId { - fn hash(&self, state: &mut H) { - self.hash.hash(state); - } -} - -impl OutputId { - pub fn new( - connector: impl Into, - manufacturer: impl Into, - model: impl Into, - serial_number: impl Into, - ) -> Rc { - let connector = connector.into(); - let manufacturer = manufacturer.into(); - let model = model.into(); - let serial_number = serial_number.into(); - Self::new_(connector, manufacturer, model, serial_number) - } - - fn new_( - connector: String, - manufacturer: String, - model: String, - serial_number: String, - ) -> Rc { - let connector = serial_number.is_empty().then_some(connector); - let mut hasher = blake3::Hasher::new(); - hasher.update(&[connector.is_some() as u8]); - let mut hash = |s: &str| { - hasher.update(&(s.len() as u64).to_le_bytes()); - hasher.update(s.as_bytes()); - }; - connector.as_deref().map(&mut hash); - hash(&manufacturer); - hash(&model); - hash(&serial_number); - Rc::new(Self { - _connector: connector, - manufacturer, - model, - serial_number, - hash: OutputIdHash(*hasher.finalize().as_bytes()), - }) - } -} - impl WlOutputGlobal { pub fn clear(&self) { self.opt.clear(); diff --git a/src/it/test_backend.rs b/src/it/test_backend.rs index 7c177b7b..dffcc1e7 100644 --- a/src/it/test_backend.rs +++ b/src/it/test_backend.rs @@ -6,7 +6,7 @@ use { AxisSource, Backend, BackendConnectorState, BackendEvent, ButtonState, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, DrmDeviceId, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceClickMethod, InputDeviceId, - InputEvent, KeyState, Mode, MonitorInfo, ScrollAxis, TransformMatrix, + InputEvent, KeyState, Mode, MonitorInfo, OutputId, ScrollAxis, TransformMatrix, transaction::{ BackendAppliedConnectorTransaction, BackendConnectorTransaction, BackendConnectorTransactionError, BackendConnectorTransactionType, @@ -20,7 +20,6 @@ use { format::XRGB8888, gfx_api::GfxError, gfx_apis::create_vulkan_allocator, - ifs::wl_output::OutputId, it::{ test_error::TestResult, test_gfx_api::TestGfxCtx, test_utils::test_expected_event::TEEH, }, diff --git a/src/it/tests/t0034_workspace_restoration.rs b/src/it/tests/t0034_workspace_restoration.rs index 4b01cac9..91cdc750 100644 --- a/src/it/tests/t0034_workspace_restoration.rs +++ b/src/it/tests/t0034_workspace_restoration.rs @@ -2,10 +2,10 @@ use { crate::{ backend::{ BackendConnectorState, BackendEvent, ConnectorEvent, ConnectorKernelId, MonitorInfo, + OutputId, }, cmm::cmm_primaries::Primaries, format::XRGB8888, - ifs::wl_output::OutputId, it::{test_backend::TestConnector, test_error::TestResult, testrun::TestRun}, utils::numcell::NumCell, video::drm::ConnectorType, diff --git a/src/macros.rs b/src/macros.rs index 356219b5..e3be785a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -830,35 +830,3 @@ macro_rules! opaque { } }; } - -macro_rules! hash_type { - ($name:ident) => { - #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] - pub struct $name(pub [u8; 32]); - - impl $name { - #[allow(clippy::allow_attributes, dead_code)] - pub fn hash(t: impl AsRef<[u8]>) -> Self { - Self(*blake3::hash(t.as_ref()).as_bytes()) - } - } - - impl serde::Serialize for $name { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.0.serialize(serializer) - } - } - - impl<'de> serde::Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - <[u8; 32]>::deserialize(deserializer).map(Self) - } - } - }; -} diff --git a/src/virtual_output.rs b/src/virtual_output.rs index 281c1d65..7ffc81da 100644 --- a/src/virtual_output.rs +++ b/src/virtual_output.rs @@ -4,7 +4,7 @@ use { async_engine::{Phase, SpawnedFuture}, backend::{ BackendConnectorState, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, - DrmDeviceId, HardwareCursor, HardwareCursorUpdate, Mode, MonitorInfo, + DrmDeviceId, HardwareCursor, HardwareCursorUpdate, Mode, MonitorInfo, OutputId, transaction::{ BackendAppliedConnectorTransaction, BackendConnectorTransaction, BackendConnectorTransactionError, BackendConnectorTransactionType, @@ -18,7 +18,7 @@ use { GfxError, GfxFramebuffer, GfxRenderPass, GfxTexture, ReleaseSync, create_render_pass, }, ifs::{ - wl_output::{BlendSpace, OutputId}, + wl_output::BlendSpace, wp_presentation_feedback::{ KIND_HW_CLOCK, KIND_HW_COMPLETION, KIND_VSYNC, KIND_ZERO_COPY, },