Implement common Std traits on many types (#3796)

This commit is contained in:
daxpedda 2024-08-08 00:46:28 +02:00 committed by GitHub
parent 9dff801f93
commit 1168cd4113
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 167 additions and 103 deletions

View file

@ -57,7 +57,7 @@ android-native-activity = ["android-activity/native-activity"]
default = ["rwh_06", "x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"] default = ["rwh_06", "x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
mint = ["dpi/mint"] mint = ["dpi/mint"]
rwh_06 = ["dep:rwh_06", "ndk/rwh_06"] rwh_06 = ["dep:rwh_06", "ndk/rwh_06"]
serde = ["dep:serde", "cursor-icon/serde", "smol_str/serde", "dpi/serde"] serde = ["dep:serde", "cursor-icon/serde", "smol_str/serde", "dpi/serde", "bitflags/serde"]
wayland = [ wayland = [
"wayland-client", "wayland-client",
"wayland-backend", "wayland-backend",

View file

@ -59,6 +59,8 @@ changelog entry.
- Add `Touch::finger_id` with a new type `FingerId`. - Add `Touch::finger_id` with a new type `FingerId`.
- On Web and Windows, add `FingerIdExt*::is_primary()`, exposing a way to determine - On Web and Windows, add `FingerIdExt*::is_primary()`, exposing a way to determine
the primary finger in a multi-touch interaction. the primary finger in a multi-touch interaction.
- Implement `Clone`, `Copy`, `Debug`, `Deserialize`, `Eq`, `Hash`, `Ord`, `PartialEq`, `PartialOrd`
and `Serialize` on many types.
### Changed ### Changed
@ -91,6 +93,7 @@ changelog entry.
- On Web, `CursorGrabMode::Locked` now lets `DeviceEvent::MouseMotion` return raw data, not OS - On Web, `CursorGrabMode::Locked` now lets `DeviceEvent::MouseMotion` return raw data, not OS
accelerated, if the browser supports it. accelerated, if the browser supports it.
- `(Active)EventLoop::create_custom_cursor()` now returns a `Result<CustomCursor, ExternalError>`. - `(Active)EventLoop::create_custom_cursor()` now returns a `Result<CustomCursor, ExternalError>`.
- Changed how `ModifiersState` is serialized by Serde.
### Removed ### Removed

View file

@ -107,7 +107,7 @@ impl CustomCursor {
/// Source for [`CustomCursor`]. /// Source for [`CustomCursor`].
/// ///
/// See [`CustomCursor`] for more details. /// See [`CustomCursor`] for more details.
#[derive(Debug)] #[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub struct CustomCursorSource { pub struct CustomCursorSource {
// Some platforms don't support custom cursors. // Some platforms don't support custom cursors.
#[allow(dead_code)] #[allow(dead_code)]
@ -115,7 +115,8 @@ pub struct CustomCursorSource {
} }
/// An error produced when using [`CustomCursor::from_rgba`] with invalid arguments. /// An error produced when using [`CustomCursor::from_rgba`] with invalid arguments.
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum BadImage { pub enum BadImage {
/// Produced when the image dimensions are larger than [`MAX_CURSOR_SIZE`]. This doesn't /// Produced when the image dimensions are larger than [`MAX_CURSOR_SIZE`]. This doesn't
/// guarantee that the cursor will work, but should avoid many platform and device specific /// guarantee that the cursor will work, but should avoid many platform and device specific
@ -166,7 +167,7 @@ impl Error for BadImage {}
/// Platforms export this directly as `PlatformCustomCursorSource` if they need to only work with /// Platforms export this directly as `PlatformCustomCursorSource` if they need to only work with
/// images. /// images.
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug)] #[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub(crate) struct OnlyCursorImageSource(pub(crate) CursorImage); pub(crate) struct OnlyCursorImageSource(pub(crate) CursorImage);
#[allow(dead_code)] #[allow(dead_code)]
@ -201,7 +202,7 @@ impl PartialEq for OnlyCursorImage {
impl Eq for OnlyCursorImage {} impl Eq for OnlyCursorImage {}
#[derive(Debug)] #[derive(Debug, Clone, Eq, Hash, PartialEq)]
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) struct CursorImage { pub(crate) struct CursorImage {
pub(crate) rgba: Vec<u8>, pub(crate) rgba: Vec<u8>,

View file

@ -15,7 +15,8 @@ pub enum ExternalError {
} }
/// The error type for when the requested operation is not supported by the backend. /// The error type for when the requested operation is not supported by the backend.
#[derive(Clone)] #[derive(Clone, Copy, Default, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct NotSupportedError { pub struct NotSupportedError {
_marker: (), _marker: (),
} }

View file

@ -115,7 +115,7 @@ pub(crate) enum Event {
} }
/// Describes the reason the event loop is resuming. /// Describes the reason the event loop is resuming.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StartCause { pub enum StartCause {
/// Sent if the time specified by [`ControlFlow::WaitUntil`] has been reached. Contains the /// Sent if the time specified by [`ControlFlow::WaitUntil`] has been reached. Contains the
/// moment the timeout was requested and the requested resume time. The actual resume time is /// moment the timeout was requested and the requested resume time. The actual resume time is
@ -434,6 +434,12 @@ pub enum WindowEvent {
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(pub(crate) platform_impl::DeviceId); pub struct DeviceId(pub(crate) platform_impl::DeviceId);
impl Default for DeviceId {
fn default() -> Self {
Self::dummy()
}
}
impl DeviceId { impl DeviceId {
/// Returns a dummy id, useful for unit testing. /// Returns a dummy id, useful for unit testing.
/// ///
@ -475,7 +481,7 @@ impl FingerId {
/// (corresponding to GUI cursors and keyboard focus) the device IDs may not match. /// (corresponding to GUI cursors and keyboard focus) the device IDs may not match.
/// ///
/// Note that these events are delivered regardless of input focus. /// Note that these events are delivered regardless of input focus.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum DeviceEvent { pub enum DeviceEvent {
/// Change in physical position of a pointing device. /// Change in physical position of a pointing device.
/// ///
@ -524,7 +530,7 @@ pub enum DeviceEvent {
/// repeat or the initial keypress. An application may emulate this by, for /// repeat or the initial keypress. An application may emulate this by, for
/// example keeping a Map/Set of pressed keys and determining whether a keypress /// example keeping a Map/Set of pressed keys and determining whether a keypress
/// corresponds to an already pressed key. /// corresponds to an already pressed key.
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RawKeyEvent { pub struct RawKeyEvent {
pub physical_key: keyboard::PhysicalKey, pub physical_key: keyboard::PhysicalKey,
@ -669,7 +675,8 @@ pub struct KeyEvent {
} }
/// Describes keyboard modifiers event. /// Describes keyboard modifiers event.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Modifiers { pub struct Modifiers {
pub(crate) state: ModifiersState, pub(crate) state: ModifiersState,
@ -871,6 +878,7 @@ pub struct Touch {
/// Describes the force of a touch event /// Describes the force of a touch event
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Force { pub enum Force {
/// On iOS, the force is calibrated so that the same number corresponds to /// On iOS, the force is calibrated so that the same number corresponds to
/// roughly the same amount of pressure on the screen regardless of the /// roughly the same amount of pressure on the screen regardless of the
@ -1020,6 +1028,8 @@ impl PartialEq for InnerSizeWriter {
} }
} }
impl Eq for InnerSizeWriter {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::{BTreeSet, HashSet}; use std::collections::{BTreeSet, HashSet};

View file

@ -52,7 +52,7 @@ pub struct EventLoop {
/// easier. But note that constructing multiple event loops is not supported. /// easier. But note that constructing multiple event loops is not supported.
/// ///
/// This can be created using [`EventLoop::builder`]. /// This can be created using [`EventLoop::builder`].
#[derive(Default)] #[derive(Default, PartialEq, Eq, Hash)]
pub struct EventLoopBuilder { pub struct EventLoopBuilder {
pub(crate) platform_specific: platform_impl::PlatformSpecificEventLoopAttributes, pub(crate) platform_specific: platform_impl::PlatformSpecificEventLoopAttributes,
} }
@ -115,9 +115,15 @@ impl EventLoopBuilder {
} }
} }
impl fmt::Debug for EventLoopBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EventLoopBuilder").finish_non_exhaustive()
}
}
impl fmt::Debug for EventLoop { impl fmt::Debug for EventLoop {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("EventLoop { .. }") f.debug_struct("EventLoop").finish_non_exhaustive()
} }
} }
@ -129,7 +135,7 @@ impl fmt::Debug for EventLoop {
/// ///
/// [`Wait`]: Self::Wait /// [`Wait`]: Self::Wait
/// [`about_to_wait`]: crate::application::ApplicationHandler::about_to_wait /// [`about_to_wait`]: crate::application::ApplicationHandler::about_to_wait
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
pub enum ControlFlow { pub enum ControlFlow {
/// When the current loop iteration finishes, immediately begin a new iteration regardless of /// When the current loop iteration finishes, immediately begin a new iteration regardless of
/// whether or not new events are available to process. /// whether or not new events are available to process.
@ -419,7 +425,7 @@ pub trait ActiveEventLoop {
/// ///
/// - A zero-sized type that is likely optimized out. /// - A zero-sized type that is likely optimized out.
/// - A reference-counted pointer to the underlying type. /// - A reference-counted pointer to the underlying type.
#[derive(Clone)] #[derive(Clone, PartialEq, Eq)]
pub struct OwnedDisplayHandle { pub struct OwnedDisplayHandle {
#[cfg_attr(not(feature = "rwh_06"), allow(dead_code))] #[cfg_attr(not(feature = "rwh_06"), allow(dead_code))]
pub(crate) platform: platform_impl::OwnedDisplayHandle, pub(crate) platform: platform_impl::OwnedDisplayHandle,
@ -474,12 +480,13 @@ impl EventLoopProxy {
impl fmt::Debug for EventLoopProxy { impl fmt::Debug for EventLoopProxy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("EventLoopProxy { .. }") f.debug_struct("ActiveEventLoop").finish_non_exhaustive()
} }
} }
/// Control when device events are captured. /// Control when device events are captured.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum DeviceEvents { pub enum DeviceEvents {
/// Report device events regardless of window focus. /// Report device events regardless of window focus.
Always, Always,
@ -499,7 +506,7 @@ pub enum DeviceEvents {
/// containing [`AsyncRequestSerial`] and some closure associated with it. /// containing [`AsyncRequestSerial`] and some closure associated with it.
/// Then once event is arriving the working list is being traversed and a job /// Then once event is arriving the working list is being traversed and a job
/// executed and removed from the list. /// executed and removed from the list.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AsyncRequestSerial { pub struct AsyncRequestSerial {
serial: usize, serial: usize,
} }

View file

@ -50,7 +50,7 @@ impl fmt::Display for BadIcon {
impl Error for BadIcon {} impl Error for BadIcon {}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct RgbaIcon { pub(crate) struct RgbaIcon {
pub(crate) rgba: Vec<u8>, pub(crate) rgba: Vec<u8>,
pub(crate) width: u32, pub(crate) width: u32,
@ -58,7 +58,7 @@ pub(crate) struct RgbaIcon {
} }
/// For platforms which don't have window icons (e.g. Web) /// For platforms which don't have window icons (e.g. Web)
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct NoIcon; pub(crate) struct NoIcon;
#[allow(dead_code)] // These are not used on every platform #[allow(dead_code)] // These are not used on every platform
@ -94,7 +94,7 @@ mod constructors {
} }
/// An icon used for the window titlebar, taskbar, etc. /// An icon used for the window titlebar, taskbar, etc.
#[derive(Clone)] #[derive(Clone, Eq, Hash, PartialEq)]
pub struct Icon { pub struct Icon {
pub(crate) inner: PlatformIcon, pub(crate) inner: PlatformIcon,
} }

View file

@ -1628,7 +1628,7 @@ impl Key {
/// ///
/// [`location`]: ../event/struct.KeyEvent.html#structfield.location /// [`location`]: ../event/struct.KeyEvent.html#structfield.location
/// [`KeyEvent`]: crate::event::KeyEvent /// [`KeyEvent`]: crate::event::KeyEvent
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum KeyLocation { pub enum KeyLocation {
/// The key is in its "normal" location on the keyboard. /// The key is in its "normal" location on the keyboard.
@ -1700,6 +1700,7 @@ bitflags! {
/// ///
/// Each flag represents a modifier and is set if this modifier is active. /// Each flag represents a modifier and is set if this modifier is active.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ModifiersState: u32 { pub struct ModifiersState: u32 {
/// The "shift" key. /// The "shift" key.
const SHIFT = 0b100; const SHIFT = 0b100;
@ -1735,7 +1736,8 @@ impl ModifiersState {
} }
/// The state of the particular modifiers key. /// The state of the particular modifiers key.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ModifiersKeyState { pub enum ModifiersKeyState {
/// The particular key is pressed. /// The particular key is pressed.
Pressed, Pressed,
@ -1754,6 +1756,7 @@ pub enum ModifiersKeyState {
// on macOS due to their AltGr/Option situation. // on macOS due to their AltGr/Option situation.
bitflags! { bitflags! {
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub(crate) struct ModifiersKeys: u8 { pub(crate) struct ModifiersKeys: u8 {
const LSHIFT = 0b0000_0001; const LSHIFT = 0b0000_0001;
const RSHIFT = 0b0000_0010; const RSHIFT = 0b0000_0010;
@ -1765,51 +1768,3 @@ bitflags! {
const RSUPER = 0b1000_0000; const RSUPER = 0b1000_0000;
} }
} }
#[cfg(feature = "serde")]
mod modifiers_serde {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::ModifiersState;
#[derive(Default, Serialize, Deserialize)]
#[serde(default)]
#[serde(rename = "ModifiersState")]
pub struct ModifiersStateSerialize {
pub shift_key: bool,
pub control_key: bool,
pub alt_key: bool,
pub super_key: bool,
}
impl Serialize for ModifiersState {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = ModifiersStateSerialize {
shift_key: self.shift_key(),
control_key: self.control_key(),
alt_key: self.alt_key(),
super_key: self.super_key(),
};
s.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for ModifiersState {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let ModifiersStateSerialize { shift_key, control_key, alt_key, super_key } =
ModifiersStateSerialize::deserialize(deserializer)?;
let mut m = ModifiersState::empty();
m.set(ModifiersState::SHIFT, shift_key);
m.set(ModifiersState::CONTROL, control_key);
m.set(ModifiersState::ALT, alt_key);
m.set(ModifiersState::SUPER, super_key);
Ok(m)
}
}
}

View file

@ -116,7 +116,7 @@ impl std::fmt::Display for VideoModeHandle {
/// to check. /// to check.
/// ///
/// [`Window`]: crate::window::Window /// [`Window`]: crate::window::Window
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MonitorHandle { pub struct MonitorHandle {
pub(crate) inner: platform_impl::MonitorHandle, pub(crate) inner: platform_impl::MonitorHandle,
} }

View file

@ -66,6 +66,9 @@
use std::os::raw::c_void; use std::os::raw::c_void;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::monitor::{MonitorHandle, VideoModeHandle}; use crate::monitor::{MonitorHandle, VideoModeHandle};
use crate::window::{Window, WindowAttributes}; use crate::window::{Window, WindowAttributes};
@ -355,6 +358,7 @@ impl MonitorHandleExtIOS for MonitorHandle {
/// Valid orientations for a particular [`Window`]. /// Valid orientations for a particular [`Window`].
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ValidOrientations { pub enum ValidOrientations {
/// Excludes `PortraitUpsideDown` on iphone /// Excludes `PortraitUpsideDown` on iphone
#[default] #[default]
@ -371,6 +375,7 @@ bitflags::bitflags! {
/// ///
/// [edges]: https://developer.apple.com/documentation/uikit/uirectedge?language=objc /// [edges]: https://developer.apple.com/documentation/uikit/uirectedge?language=objc
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ScreenEdge: u8 { pub struct ScreenEdge: u8 {
const NONE = 0; const NONE = 0;
const TOP = 1 << 0; const TOP = 1 << 0;
@ -382,7 +387,8 @@ bitflags::bitflags! {
} }
} }
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum StatusBarStyle { pub enum StatusBarStyle {
#[default] #[default]
Default, Default,

View file

@ -170,6 +170,7 @@ impl WindowExtMacOS for Window {
/// Corresponds to `NSApplicationActivationPolicy`. /// Corresponds to `NSApplicationActivationPolicy`.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ActivationPolicy { pub enum ActivationPolicy {
/// Corresponds to `NSApplicationActivationPolicyRegular`. /// Corresponds to `NSApplicationActivationPolicyRegular`.
#[default] #[default]
@ -432,7 +433,7 @@ impl ActiveEventLoopExtMacOS for &dyn ActiveEventLoop {
/// Option as alt behavior. /// Option as alt behavior.
/// ///
/// The default is `None`. /// The default is `None`.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum OptionAsAlt { pub enum OptionAsAlt {
/// The left `Option` key is treated as `Alt`. /// The left `Option` key is treated as `Alt`.

View file

@ -117,6 +117,7 @@ impl EventLoopExtPumpEvents for EventLoop {
} }
/// The return status for `pump_events` /// The return status for `pump_events`
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum PumpStatus { pub enum PumpStatus {
/// Continue running external loop. /// Continue running external loop.
Continue, Continue,

View file

@ -50,6 +50,8 @@ use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::Duration; use std::time::Duration;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(web_platform)] #[cfg(web_platform)]
use web_sys::HtmlCanvasElement; use web_sys::HtmlCanvasElement;
@ -429,7 +431,8 @@ impl ActiveEventLoopExtWeb for &dyn ActiveEventLoop {
} }
/// Strategy used for [`ControlFlow::Poll`][crate::event_loop::ControlFlow::Poll]. /// Strategy used for [`ControlFlow::Poll`][crate::event_loop::ControlFlow::Poll].
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum PollStrategy { pub enum PollStrategy {
/// Uses [`Window.requestIdleCallback()`] to queue the next event loop. If not available /// Uses [`Window.requestIdleCallback()`] to queue the next event loop. If not available
/// this will fallback to [`setTimeout()`]. /// this will fallback to [`setTimeout()`].
@ -455,7 +458,8 @@ pub enum PollStrategy {
} }
/// Strategy used for [`ControlFlow::WaitUntil`][crate::event_loop::ControlFlow::WaitUntil]. /// Strategy used for [`ControlFlow::WaitUntil`][crate::event_loop::ControlFlow::WaitUntil].
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum WaitUntilStrategy { pub enum WaitUntilStrategy {
/// Uses the [Prioritized Task Scheduling API] to queue the next event loop. If not available /// Uses the [Prioritized Task Scheduling API] to queue the next event loop. If not available
/// this will fallback to [`setTimeout()`]. /// this will fallback to [`setTimeout()`].
@ -524,7 +528,8 @@ impl CustomCursorExtWeb for CustomCursor {
} }
/// An error produced when using [`CustomCursor::from_animation`] with invalid arguments. /// An error produced when using [`CustomCursor::from_animation`] with invalid arguments.
#[derive(Debug, Clone)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum BadAnimation { pub enum BadAnimation {
/// Produced when no cursors were supplied. /// Produced when no cursors were supplied.
Empty, Empty,
@ -557,7 +562,8 @@ impl Future for CustomCursorFuture {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum CustomCursorError { pub enum CustomCursorError {
Blob, Blob,
Decode(String), Decode(String),

View file

@ -6,6 +6,9 @@ use std::borrow::Borrow;
use std::ffi::c_void; use std::ffi::c_void;
use std::path::Path; use std::path::Path;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::dpi::PhysicalSize; use crate::dpi::PhysicalSize;
use crate::event::{DeviceId, FingerId}; use crate::event::{DeviceId, FingerId};
use crate::event_loop::EventLoopBuilder; use crate::event_loop::EventLoopBuilder;
@ -25,6 +28,7 @@ pub type HMONITOR = isize;
/// ///
/// [`DWM_SYSTEMBACKDROP_TYPE docs`]: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_systembackdrop_type /// [`DWM_SYSTEMBACKDROP_TYPE docs`]: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_systembackdrop_type
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum BackdropType { pub enum BackdropType {
/// Corresponds to `DWMSBT_AUTO`. /// Corresponds to `DWMSBT_AUTO`.
/// ///
@ -54,6 +58,7 @@ pub enum BackdropType {
/// Describes a color used by Windows /// Describes a color used by Windows
#[repr(transparent)] #[repr(transparent)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Color(u32); pub struct Color(u32);
impl Color { impl Color {
@ -82,6 +87,7 @@ impl Default for Color {
/// [`DWM_WINDOW_CORNER_PREFERENCE docs`]: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_window_corner_preference /// [`DWM_WINDOW_CORNER_PREFERENCE docs`]: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_window_corner_preference
#[repr(i32)] #[repr(i32)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum CornerPreference { pub enum CornerPreference {
/// Corresponds to `DWMWCP_DEFAULT`. /// Corresponds to `DWMWCP_DEFAULT`.
/// ///
@ -108,7 +114,7 @@ pub enum CornerPreference {
/// A wrapper around a [`Window`] that ignores thread-specific window handle limitations. /// A wrapper around a [`Window`] that ignores thread-specific window handle limitations.
/// ///
/// See [`WindowBorrowExtWindows::any_thread`] for more information. /// See [`WindowBorrowExtWindows::any_thread`] for more information.
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct AnyThread<W>(W); pub struct AnyThread<W>(W);
impl<W: Borrow<Window>> AnyThread<W> { impl<W: Borrow<Window>> AnyThread<W> {

View file

@ -112,7 +112,7 @@ pub struct EventLoop {
combining_accent: Option<char>, combining_accent: Option<char>,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct PlatformSpecificEventLoopAttributes { pub(crate) struct PlatformSpecificEventLoopAttributes {
pub(crate) android_app: Option<AndroidApp>, pub(crate) android_app: Option<AndroidApp>,
pub(crate) ignore_volume_keys: bool, pub(crate) ignore_volume_keys: bool,
@ -662,7 +662,7 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop {
} }
} }
#[derive(Clone)] #[derive(Clone, PartialEq, Eq)]
pub(crate) struct OwnedDisplayHandle; pub(crate) struct OwnedDisplayHandle;
impl OwnedDisplayHandle { impl OwnedDisplayHandle {

View file

@ -375,7 +375,7 @@ impl EventLoop {
} }
} }
#[derive(Clone)] #[derive(Clone, PartialEq, Eq)]
pub(crate) struct OwnedDisplayHandle; pub(crate) struct OwnedDisplayHandle;
impl OwnedDisplayHandle { impl OwnedDisplayHandle {

View file

@ -42,7 +42,7 @@ use crate::window::{
WindowAttributes, WindowButtons, WindowId as RootWindowId, WindowLevel, WindowAttributes, WindowButtons, WindowId as RootWindowId, WindowLevel,
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub struct PlatformSpecificWindowAttributes { pub struct PlatformSpecificWindowAttributes {
pub movable_by_window_background: bool, pub movable_by_window_background: bool,
pub titlebar_transparent: bool, pub titlebar_transparent: bool,

View file

@ -112,7 +112,7 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop {
} }
} }
#[derive(Clone)] #[derive(Clone, PartialEq, Eq)]
pub(crate) struct OwnedDisplayHandle; pub(crate) struct OwnedDisplayHandle;
impl OwnedDisplayHandle { impl OwnedDisplayHandle {

View file

@ -702,7 +702,7 @@ impl From<&AnyObject> for WindowId {
} }
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct PlatformSpecificWindowAttributes { pub struct PlatformSpecificWindowAttributes {
pub scale_factor: Option<f64>, pub scale_factor: Option<f64>,
pub valid_orientations: ValidOrientations, pub valid_orientations: ValidOrientations,

View file

@ -67,7 +67,7 @@ impl ApplicationName {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub struct PlatformSpecificWindowAttributes { pub struct PlatformSpecificWindowAttributes {
pub name: Option<ApplicationName>, pub name: Option<ApplicationName>,
pub activation_token: Option<ActivationToken>, pub activation_token: Option<ActivationToken>,
@ -75,7 +75,7 @@ pub struct PlatformSpecificWindowAttributes {
pub x11: X11WindowAttributes, pub x11: X11WindowAttributes,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
#[cfg(x11_platform)] #[cfg(x11_platform)]
pub struct X11WindowAttributes { pub struct X11WindowAttributes {
pub visual_id: Option<x11rb::protocol::xproto::Visualid>, pub visual_id: Option<x11rb::protocol::xproto::Visualid>,
@ -194,7 +194,7 @@ impl FingerId {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum MonitorHandle { pub enum MonitorHandle {
#[cfg(x11_platform)] #[cfg(x11_platform)]
X(x11::MonitorHandle), X(x11::MonitorHandle),
@ -850,6 +850,21 @@ impl OwnedDisplayHandle {
} }
} }
impl PartialEq for OwnedDisplayHandle {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
#[cfg(x11_platform)]
(Self::X(this), Self::X(other)) => Arc::as_ptr(this).eq(&Arc::as_ptr(other)),
#[cfg(wayland_platform)]
(Self::Wayland(this), Self::Wayland(other)) => this.eq(other),
#[cfg(all(x11_platform, wayland_platform))]
_ => false,
}
}
}
impl Eq for OwnedDisplayHandle {}
/// Returns the minimum `Option<Duration>`, taking into account that `None` /// Returns the minimum `Option<Duration>`, taking into account that `None`
/// equates to an infinite timeout, not a zero timeout (so can't just use /// equates to an infinite timeout, not a zero timeout (so can't just use
/// `Option::min`) /// `Option::min`)

View file

@ -796,7 +796,7 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop {
} }
} }
#[derive(Clone)] #[derive(Clone, PartialEq, Eq)]
pub(crate) struct OwnedDisplayHandle; pub(crate) struct OwnedDisplayHandle;
impl OwnedDisplayHandle { impl OwnedDisplayHandle {

View file

@ -27,7 +27,7 @@ use super::ActiveEventLoop;
use crate::cursor::{BadImage, Cursor, CursorImage, CustomCursor as RootCustomCursor}; use crate::cursor::{BadImage, Cursor, CursorImage, CustomCursor as RootCustomCursor};
use crate::platform::web::CustomCursorError; use crate::platform::web::CustomCursorError;
#[derive(Debug)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(crate) enum CustomCursorSource { pub(crate) enum CustomCursorSource {
Image(CursorImage), Image(CursorImage),
Url { url: String, hotspot_x: u16, hotspot_y: u16 }, Url { url: String, hotspot_x: u16, hotspot_y: u16 },

View file

@ -711,7 +711,7 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop {
} }
} }
#[derive(Clone)] #[derive(Clone, PartialEq, Eq)]
pub(crate) struct OwnedDisplayHandle; pub(crate) struct OwnedDisplayHandle;
impl OwnedDisplayHandle { impl OwnedDisplayHandle {

View file

@ -457,6 +457,18 @@ pub struct PlatformSpecificWindowAttributes {
pub(crate) append: bool, pub(crate) append: bool,
} }
impl PartialEq for PlatformSpecificWindowAttributes {
fn eq(&self, other: &Self) -> bool {
(match (&self.canvas, &other.canvas) {
(Some(this), Some(other)) => Arc::ptr_eq(this, other),
(None, None) => true,
_ => false,
}) && self.prevent_default.eq(&other.prevent_default)
&& self.focusable.eq(&other.focusable)
&& self.append.eq(&other.append)
}
}
impl PlatformSpecificWindowAttributes { impl PlatformSpecificWindowAttributes {
pub(crate) fn set_canvas(&mut self, canvas: Option<backend::RawCanvasType>) { pub(crate) fn set_canvas(&mut self, canvas: Option<backend::RawCanvasType>) {
let Some(canvas) = canvas else { let Some(canvas) = canvas else {

View file

@ -143,6 +143,28 @@ impl Default for PlatformSpecificEventLoopAttributes {
} }
} }
impl PartialEq for PlatformSpecificEventLoopAttributes {
fn eq(&self, other: &Self) -> bool {
self.any_thread.eq(&other.any_thread)
&& self.dpi_aware.eq(&other.dpi_aware)
&& match (&self.msg_hook, &other.msg_hook) {
(Some(this), Some(other)) => std::ptr::eq(&this, &other),
(None, None) => true,
_ => false,
}
}
}
impl Eq for PlatformSpecificEventLoopAttributes {}
impl std::hash::Hash for PlatformSpecificEventLoopAttributes {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.any_thread.hash(state);
self.dpi_aware.hash(state);
std::ptr::hash(&self.msg_hook, state);
}
}
pub struct ActiveEventLoop { pub struct ActiveEventLoop {
thread_id: u32, thread_id: u32,
thread_msg_target: HWND, thread_msg_target: HWND,
@ -565,7 +587,7 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop {
} }
} }
#[derive(Clone)] #[derive(Clone, PartialEq, Eq)]
pub(crate) struct OwnedDisplayHandle; pub(crate) struct OwnedDisplayHandle;
impl OwnedDisplayHandle { impl OwnedDisplayHandle {

View file

@ -63,12 +63,12 @@ pub enum IconType {
Big = ICON_BIG as isize, Big = ICON_BIG as isize,
} }
#[derive(Debug)] #[derive(Debug, PartialEq, Eq, Hash)]
struct RaiiIcon { struct RaiiIcon {
handle: HICON, handle: HICON,
} }
#[derive(Clone)] #[derive(Clone, PartialEq, Eq, Hash)]
pub struct WinIcon { pub struct WinIcon {
inner: Arc<RaiiIcon>, inner: Arc<RaiiIcon>,
} }

View file

@ -17,7 +17,7 @@ use crate::keyboard::Key;
use crate::platform::windows::{BackdropType, Color, CornerPreference}; use crate::platform::windows::{BackdropType, Color, CornerPreference};
use crate::platform_impl::Fullscreen; use crate::platform_impl::Fullscreen;
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub struct PlatformSpecificWindowAttributes { pub struct PlatformSpecificWindowAttributes {
pub owner: Option<HWND>, pub owner: Option<HWND>,
pub menu: Option<HMENU>, pub menu: Option<HMENU>,

View file

@ -36,8 +36,8 @@ pub struct Window {
} }
impl fmt::Debug for Window { impl fmt::Debug for Window {
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmtr.pad("Window { .. }") f.debug_struct("Window").finish_non_exhaustive()
} }
} }
@ -58,6 +58,20 @@ impl Drop for Window {
} }
} }
impl PartialEq for Window {
fn eq(&self, other: &Self) -> bool {
self.id().eq(&other.id())
}
}
impl Eq for Window {}
impl std::hash::Hash for Window {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id().hash(state);
}
}
/// Identifier of a window. Unique for each window. /// Identifier of a window. Unique for each window.
/// ///
/// Can be obtained with [`window.id()`][`Window::id`]. /// Can be obtained with [`window.id()`][`Window::id`].
@ -99,7 +113,7 @@ impl From<u64> for WindowId {
} }
/// Attributes used when creating a window. /// Attributes used when creating a window.
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
pub struct WindowAttributes { pub struct WindowAttributes {
pub inner_size: Option<Size>, pub inner_size: Option<Size>,
pub min_inner_size: Option<Size>, pub min_inner_size: Option<Size>,
@ -165,7 +179,7 @@ impl Default for WindowAttributes {
/// ///
/// The user has to account for that when using [`WindowAttributes::with_parent_window()`], /// The user has to account for that when using [`WindowAttributes::with_parent_window()`],
/// which is `unsafe`. /// which is `unsafe`.
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
pub(crate) struct SendSyncRawWindowHandle(pub(crate) rwh_06::RawWindowHandle); pub(crate) struct SendSyncRawWindowHandle(pub(crate) rwh_06::RawWindowHandle);
@ -1685,6 +1699,7 @@ pub enum CursorGrabMode {
/// Defines the orientation that a window resize will be performed. /// Defines the orientation that a window resize will be performed.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ResizeDirection { pub enum ResizeDirection {
East, East,
North, North,
@ -1713,7 +1728,7 @@ impl From<ResizeDirection> for CursorIcon {
} }
/// Fullscreen modes. /// Fullscreen modes.
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Fullscreen { pub enum Fullscreen {
Exclusive(VideoModeHandle), Exclusive(VideoModeHandle),
@ -1722,7 +1737,7 @@ pub enum Fullscreen {
} }
/// The theme variant to use. /// The theme variant to use.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Theme { pub enum Theme {
/// Use the light variant. /// Use the light variant.
@ -1739,7 +1754,8 @@ pub enum Theme {
/// ///
/// [`Critical`]: Self::Critical /// [`Critical`]: Self::Critical
/// [`Informational`]: Self::Informational /// [`Informational`]: Self::Informational
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum UserAttentionType { pub enum UserAttentionType {
/// ## Platform-specific /// ## Platform-specific
/// ///
@ -1773,7 +1789,8 @@ bitflags::bitflags! {
/// ## Platform-specific /// ## Platform-specific
/// ///
/// - **iOS / Android / Web / Wayland:** Unsupported. /// - **iOS / Android / Web / Wayland:** Unsupported.
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] #[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum WindowLevel { pub enum WindowLevel {
/// The window will always be below normal windows. /// The window will always be below normal windows.
/// ///
@ -1796,8 +1813,9 @@ pub enum WindowLevel {
/// ## Platform-specific /// ## Platform-specific
/// ///
/// - **iOS / Android / Web / Windows / X11 / macOS / Orbital:** Unsupported. /// - **iOS / Android / Web / Windows / X11 / macOS / Orbital:** Unsupported.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[non_exhaustive] #[non_exhaustive]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ImePurpose { pub enum ImePurpose {
/// No special hints for the IME (default). /// No special hints for the IME (default).
Normal, Normal,
@ -1818,7 +1836,7 @@ impl Default for ImePurpose {
/// An opaque token used to activate the [`Window`]. /// An opaque token used to activate the [`Window`].
/// ///
/// [`Window`]: crate::window::Window /// [`Window`]: crate::window::Window
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct ActivationToken { pub struct ActivationToken {
pub(crate) _token: String, pub(crate) _token: String,
} }