#[cfg(not(feature = "std"))]
use alloc::string::{String, ToString};
use alloc::{
boxed::Box,
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
vec::Vec,
};
use core::{
cmp::Ordering,
ffi::c_void,
hash::{Hash, Hasher},
ops,
sync::atomic::{AtomicI64, AtomicUsize, Ordering as AtomicOrdering},
};
use azul_css::{
css::CssPath,
props::{
basic::{ColorU, FloatValue, LayoutPoint, LayoutRect, LayoutSize},
property::CssProperty,
},
AzString, LayoutDebugMessage, OptionF32, OptionI32, OptionString, OptionU32, U8Vec,
};
use rust_fontconfig::FcFontCache;
use crate::{
callbacks::{LayoutCallback, LayoutCallbackType, Update},
dom::{DomId, DomNodeId, NodeHierarchy},
geom::{
LogicalPosition, LogicalRect, LogicalSize, OptionLogicalSize, PhysicalPositionI32,
PhysicalSize,
},
gl::OptionGlContextPtr,
hit_test::{ExternalScrollId, OverflowingScrollNode},
id::{NodeDataContainer, NodeId},
refany::OptionRefAny,
resources::{
DpiScaleFactor, Epoch, GlTextureCache, IdNamespace, ImageCache, ImageMask, ImageRef,
RendererResources, ResourceUpdate,
},
selection::SelectionState,
styled_dom::NodeHierarchyItemId,
task::{Instant, ThreadId, TimerId},
FastBTreeSet, OrderedMap,
};
pub const DEFAULT_TITLE: &str = "Azul App";
static LAST_WINDOW_ID: AtomicI64 = AtomicI64::new(0);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct WindowId {
pub id: i64,
}
impl Default for WindowId {
fn default() -> Self {
Self::new()
}
}
impl WindowId {
pub fn new() -> Self {
Self {
id: LAST_WINDOW_ID.fetch_add(1, AtomicOrdering::SeqCst),
}
}
}
static LAST_ICON_KEY: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct IconKey {
icon_id: usize,
}
impl Default for IconKey {
fn default() -> Self {
Self::new()
}
}
impl IconKey {
pub fn new() -> Self {
Self {
icon_id: LAST_ICON_KEY.fetch_add(1, AtomicOrdering::SeqCst),
}
}
}
#[repr(C)]
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
pub struct RendererOptions {
pub vsync: Vsync,
pub srgb: Srgb,
pub hw_accel: HwAcceleration,
}
impl_option!(
RendererOptions,
OptionRendererOptions,
[PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash]
);
impl Default for RendererOptions {
fn default() -> Self {
Self {
vsync: Vsync::Enabled,
srgb: Srgb::Disabled,
hw_accel: HwAcceleration::DontCare,
}
}
}
impl RendererOptions {
#[must_use]
pub const fn new(vsync: Vsync, srgb: Srgb, hw_accel: HwAcceleration) -> Self {
Self {
vsync,
srgb,
hw_accel,
}
}
}
#[repr(C)]
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
pub enum Vsync {
Enabled,
Disabled,
DontCare,
}
impl Vsync {
#[must_use]
pub const fn is_enabled(&self) -> bool {
matches!(self, Self::Enabled)
}
}
#[repr(C)]
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
pub enum Srgb {
Enabled,
Disabled,
DontCare,
}
impl Srgb {
#[must_use]
pub const fn is_enabled(&self) -> bool {
matches!(self, Self::Enabled)
}
}
#[repr(C)]
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
pub enum HwAcceleration {
Enabled,
Disabled,
DontCare,
}
impl HwAcceleration {
#[must_use]
pub const fn is_enabled(&self) -> bool {
matches!(self, Self::Enabled)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C, u8)]
pub enum RawWindowHandle {
IOS(IOSHandle),
MacOS(MacOSHandle),
Xlib(XlibHandle),
Xcb(XcbHandle),
Wayland(WaylandHandle),
Windows(WindowsHandle),
Web(WebHandle),
Android(AndroidHandle),
Unsupported,
}
unsafe impl Send for RawWindowHandle {}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct IOSHandle {
pub ui_window: *mut c_void,
pub ui_view: *mut c_void,
pub ui_view_controller: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct MacOSHandle {
pub ns_window: *mut c_void,
pub ns_view: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct XlibHandle {
pub window: u64,
pub display: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct XcbHandle {
pub window: u32,
pub connection: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct WaylandHandle {
pub surface: *mut c_void,
pub display: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct WindowsHandle {
pub hwnd: *mut c_void,
pub hinstance: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct WebHandle {
pub id: u32,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct AndroidHandle {
pub a_native_window: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
#[derive(Default)]
pub enum MouseCursorType {
#[default]
Default,
Crosshair,
Hand,
Arrow,
Move,
Text,
Wait,
Help,
Progress,
NotAllowed,
ContextMenu,
Cell,
VerticalText,
Alias,
Copy,
NoDrop,
Grab,
Grabbing,
AllScroll,
ZoomIn,
ZoomOut,
EResize,
NResize,
NeResize,
NwResize,
SResize,
SeResize,
SwResize,
WResize,
EwResize,
NsResize,
NeswResize,
NwseResize,
ColResize,
RowResize,
}
pub type ScanCode = u32;
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct KeyLocks {
pub caps_lock: bool,
pub num_lock: bool,
pub scroll_lock: bool,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum PhysicalKey {
Unidentified,
KeyA, KeyB, KeyC, KeyD, KeyE, KeyF, KeyG, KeyH, KeyI, KeyJ, KeyK, KeyL, KeyM,
KeyN, KeyO, KeyP, KeyQ, KeyR, KeyS, KeyT, KeyU, KeyV, KeyW, KeyX, KeyY, KeyZ,
Digit0, Digit1, Digit2, Digit3, Digit4, Digit5, Digit6, Digit7, Digit8, Digit9,
Backquote, Minus, Equal, BracketLeft, BracketRight, Backslash,
Semicolon, Quote, Comma, Period, Slash,
Enter, Tab, Space, Backspace, Escape, CapsLock,
ShiftLeft, ShiftRight, ControlLeft, ControlRight,
AltLeft, AltRight, MetaLeft, MetaRight, ContextMenu,
Insert, Delete, Home, End, PageUp, PageDown,
ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,
PrintScreen, ScrollLock, Pause,
NumLock, NumpadDivide, NumpadMultiply, NumpadSubtract, NumpadAdd,
NumpadEnter, NumpadDecimal, NumpadComma, NumpadEqual,
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4,
Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
IntlBackslash, IntlRo, IntlYen, Lang1, Lang2, Convert, NonConvert, KanaMode,
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct KeyboardState {
pub current_virtual_keycode: OptionVirtualKeyCode,
pub pressed_virtual_keycodes: VirtualKeyCodeVec,
pub pressed_scancodes: ScanCodeVec,
pub modifiers: crate::events::KeyModifiers,
pub locks: KeyLocks,
pub is_repeat: bool,
pub current_physical_key: OptionPhysicalKey,
}
impl KeyboardState {
#[must_use]
pub fn shift_down(&self) -> bool {
self.is_key_down(VirtualKeyCode::LShift) || self.is_key_down(VirtualKeyCode::RShift)
}
#[must_use]
pub fn ctrl_down(&self) -> bool {
self.is_key_down(VirtualKeyCode::LControl) || self.is_key_down(VirtualKeyCode::RControl)
}
#[must_use]
pub fn alt_down(&self) -> bool {
self.is_key_down(VirtualKeyCode::LAlt) || self.is_key_down(VirtualKeyCode::RAlt)
}
#[must_use]
pub fn super_down(&self) -> bool {
self.is_key_down(VirtualKeyCode::LWin) || self.is_key_down(VirtualKeyCode::RWin)
}
#[must_use]
pub fn primary_down(&self) -> bool {
if cfg!(target_os = "macos") {
self.super_down()
} else {
self.ctrl_down()
}
}
#[must_use]
pub fn is_key_down(&self, key: VirtualKeyCode) -> bool {
self.pressed_virtual_keycodes.iter().any(|k| *k == key)
}
#[must_use]
pub fn derived_modifiers(&self) -> crate::events::KeyModifiers {
crate::events::KeyModifiers {
shift: self.shift_down(),
ctrl: self.ctrl_down(),
alt: self.alt_down(),
meta: self.super_down(),
}
}
pub fn sync_modifiers(&mut self) {
self.modifiers = self.derived_modifiers();
}
#[must_use]
pub fn matches_accelerator(&self, chord: &[AcceleratorKey]) -> bool {
chord.iter().all(|a| a.matches(self))
}
}
impl_option!(
KeyboardState,
OptionKeyboardState,
copy = false,
[Debug, Clone, PartialEq, Eq]
);
impl_option!(
u32,
OptionChar,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_option!(
VirtualKeyCode,
OptionVirtualKeyCode,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_option!(
PhysicalKey,
OptionPhysicalKey,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_vec!(
VirtualKeyCode,
VirtualKeyCodeVec,
VirtualKeyCodeVecDestructor,
VirtualKeyCodeVecDestructorType,
VirtualKeyCodeVecSlice,
OptionVirtualKeyCode
);
impl_vec_debug!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_partialord!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_ord!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_clone!(
VirtualKeyCode,
VirtualKeyCodeVec,
VirtualKeyCodeVecDestructor
);
impl_vec_partialeq!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_eq!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_hash!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_mut!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_as_hashmap!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec!(
ScanCode,
ScanCodeVec,
ScanCodeVecDestructor,
ScanCodeVecDestructorType,
ScanCodeVecSlice,
OptionU32
);
impl_vec_debug!(ScanCode, ScanCodeVec);
impl_vec_partialord!(ScanCode, ScanCodeVec);
impl_vec_ord!(ScanCode, ScanCodeVec);
impl_vec_clone!(ScanCode, ScanCodeVec, ScanCodeVecDestructor);
impl_vec_partialeq!(ScanCode, ScanCodeVec);
impl_vec_eq!(ScanCode, ScanCodeVec);
impl_vec_hash!(ScanCode, ScanCodeVec);
impl_vec_mut!(ScanCode, ScanCodeVec);
impl_vec_as_hashmap!(ScanCode, ScanCodeVec);
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq)]
#[repr(C)]
pub struct MouseState {
pub pointer_device_id: u64,
pub cursor_position: CursorPosition,
pub mouse_cursor_type: OptionMouseCursorType,
pub pointer_source: crate::events::PointerSource,
pub is_cursor_locked: bool,
pub left_down: bool,
pub right_down: bool,
pub middle_down: bool,
pub other_down: u8,
}
impl MouseState {
#[must_use]
pub const fn back_down(&self) -> bool {
self.other_down & crate::events::MOUSE_OTHER_MASK_BACK != 0
}
#[must_use]
pub const fn forward_down(&self) -> bool {
self.other_down & crate::events::MOUSE_OTHER_MASK_FORWARD != 0
}
#[must_use]
pub const fn matches(&self, context: &ContextMenuMouseButton) -> bool {
use self::ContextMenuMouseButton::{Left, Middle, Right};
match context {
Left => self.left_down,
Right => self.right_down,
Middle => self.middle_down,
}
}
}
impl_option!(
MouseState,
OptionMouseState,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd]
);
impl_option!(
MouseCursorType,
OptionMouseCursorType,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl Default for MouseState {
fn default() -> Self {
Self {
mouse_cursor_type: Some(MouseCursorType::Default).into(),
cursor_position: CursorPosition::default(),
is_cursor_locked: false,
left_down: false,
right_down: false,
middle_down: false,
other_down: 0,
pointer_source: crate::events::PointerSource::Unknown,
pointer_device_id: 0,
}
}
}
pub const PRIMARY_POINTER_SEAT: u64 = 0;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct PointerSeat {
pub seat_id: u64,
pub state: MouseState,
}
impl_option!(
PointerSeat,
OptionPointerSeat,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd]
);
impl_vec!(
PointerSeat,
PointerSeatVec,
PointerSeatVecDestructor,
PointerSeatVecDestructorType,
PointerSeatVecSlice,
OptionPointerSeat
);
impl_vec_debug!(PointerSeat, PointerSeatVec);
impl_vec_clone!(PointerSeat, PointerSeatVec, PointerSeatVecDestructor);
impl_vec_partialeq!(PointerSeat, PointerSeatVec);
impl_vec_mut!(PointerSeat, PointerSeatVec);
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct KeyboardSeat {
pub seat_id: u64,
pub state: KeyboardState,
}
impl_option!(
KeyboardSeat,
OptionKeyboardSeat,
copy = false,
[Debug, Clone, PartialEq, Eq]
);
impl_vec!(
KeyboardSeat,
KeyboardSeatVec,
KeyboardSeatVecDestructor,
KeyboardSeatVecDestructorType,
KeyboardSeatVecSlice,
OptionKeyboardSeat
);
impl_vec_debug!(KeyboardSeat, KeyboardSeatVec);
impl_vec_clone!(KeyboardSeat, KeyboardSeatVec, KeyboardSeatVecDestructor);
impl_vec_partialeq!(KeyboardSeat, KeyboardSeatVec);
impl_vec_mut!(KeyboardSeat, KeyboardSeatVec);
#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
#[repr(C)]
pub struct VirtualKeyCodeCombo {
pub keys: VirtualKeyCodeVec,
}
impl_option!(
VirtualKeyCodeCombo,
OptionVirtualKeyCodeCombo,
copy = false,
[Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord]
);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
#[repr(C)]
#[derive(Default)]
pub enum ContextMenuMouseButton {
#[default]
Right,
Middle,
Left,
}
impl MouseState {
#[must_use]
pub const fn mouse_down(&self) -> bool {
self.right_down || self.left_down || self.middle_down
}
#[must_use]
pub const fn button_state(&self) -> crate::events::MouseButtonState {
crate::events::MouseButtonState {
left_down: self.left_down,
right_down: self.right_down,
middle_down: self.middle_down,
}
}
}
impl From<&MouseState> for crate::events::MouseButtonState {
fn from(s: &MouseState) -> Self {
s.button_state()
}
}
impl crate::events::MouseButtonState {
#[must_use]
pub const fn any_down(&self) -> bool {
self.left_down || self.right_down || self.middle_down
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct ScrollResult {
pub scrolled_nodes: usize,
pub remaining_delta: LogicalPosition,
pub hit_scrollbar: bool,
}
#[must_use]
pub fn process_system_scroll(delta: LogicalPosition, hit_scrollbar: bool) -> ScrollResult {
let consumed = delta.x != 0.0 || delta.y != 0.0;
ScrollResult {
scrolled_nodes: usize::from(consumed),
remaining_delta: LogicalPosition::zero(),
hit_scrollbar,
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd)]
#[repr(C, u8)]
#[derive(Default)]
pub enum CursorPosition {
OutOfWindow(LogicalPosition),
#[default]
Uninitialized,
InWindow(LogicalPosition),
}
impl CursorPosition {
#[must_use]
pub const fn get_position(&self) -> Option<LogicalPosition> {
match self {
Self::InWindow(logical_pos) => Some(*logical_pos),
Self::OutOfWindow(_) | Self::Uninitialized => None,
}
}
#[must_use]
pub const fn is_inside_window(&self) -> bool {
self.get_position().is_some()
}
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(C)]
pub struct DebugState {
pub show_hit_test_areas: bool,
pub profiler_dbg: bool,
pub render_target_dbg: bool,
pub texture_cache_dbg: bool,
pub gpu_time_queries: bool,
pub gpu_sample_queries: bool,
pub disable_batching: bool,
pub epochs: bool,
pub echo_driver_messages: bool,
pub show_overdraw: bool,
pub gpu_cache_dbg: bool,
pub texture_cache_dbg_clear_evicted: bool,
pub picture_caching_dbg: bool,
pub primitive_dbg: bool,
pub zoom_dbg: bool,
pub small_screen: bool,
pub disable_opaque_pass: bool,
pub disable_alpha_pass: bool,
pub disable_clip_masks: bool,
pub disable_text_prims: bool,
pub disable_gradient_prims: bool,
pub obscure_images: bool,
pub glyph_flashing: bool,
pub smart_profiler: bool,
pub invalidation_dbg: bool,
pub tile_cache_logging_dbg: bool,
pub profiler_capture: bool,
pub force_picture_invalidation: bool,
}
impl DebugState {
#[cfg(feature = "std")]
#[must_use]
pub fn from_az_overlay_env() -> Self {
std::env::var("AZ_OVERLAY")
.map_or_else(|_| Self::default(), |v| Self::from_overlay_spec(v.as_str()))
}
#[cfg(not(feature = "std"))]
#[must_use]
pub fn from_az_overlay_env() -> Self {
Self::default()
}
#[must_use]
pub fn from_overlay_spec(spec: &str) -> Self {
let mut s = Self::default();
for raw in spec.split(',') {
let verb = raw.trim().to_ascii_lowercase();
if verb.is_empty() {
continue;
}
match verb.as_str() {
"hit-test" | "hittest" => s.show_hit_test_areas = true,
"profiler" => s.profiler_dbg = true,
"smart-profiler" => s.smart_profiler = true,
"overdraw" => s.show_overdraw = true,
"render-targets" => s.render_target_dbg = true,
"texture-cache" => s.texture_cache_dbg = true,
"gpu-cache" => s.gpu_cache_dbg = true,
"picture-caching" => s.picture_caching_dbg = true,
"primitives" => s.primitive_dbg = true,
"invalidation" => s.invalidation_dbg = true,
"epochs" => s.epochs = true,
"zoom" => s.zoom_dbg = true,
"glyph-flashing" => s.glyph_flashing = true,
"obscure-images" => s.obscure_images = true,
"gpu-time" => s.gpu_time_queries = true,
"gpu-samples" => s.gpu_sample_queries = true,
"echo-driver" => s.echo_driver_messages = true,
"no-batching" => s.disable_batching = true,
"no-opaque-pass" => s.disable_opaque_pass = true,
"no-alpha-pass" => s.disable_alpha_pass = true,
"no-clip-masks" => s.disable_clip_masks = true,
"no-text" => s.disable_text_prims = true,
"no-gradients" => s.disable_gradient_prims = true,
"all" => {
s.show_hit_test_areas = true;
s.profiler_dbg = true;
s.show_overdraw = true;
s.primitive_dbg = true;
}
other => {
#[cfg(feature = "std")]
eprintln!(
"[azul] AZ_OVERLAY: unknown verb {other:?}. Known: hit-test, profiler, \
smart-profiler, overdraw, render-targets, texture-cache, gpu-cache, \
picture-caching, primitives, invalidation, epochs, zoom, glyph-flashing, \
obscure-images, gpu-time, gpu-samples, echo-driver, no-batching, \
no-opaque-pass, no-alpha-pass, no-clip-masks, no-text, no-gradients, all"
);
}
}
}
s
}
}
#[derive(Debug, Default, Clone, PartialEq)]
#[repr(C)]
pub struct TouchState {
pub num_touches: usize,
pub touch_points: TouchPointVec,
pub coalesced_points: TouchPointVec,
pub predicted_points: TouchPointVec,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum TouchToolType {
Unknown,
Finger,
Stylus,
Eraser,
Palm,
Mouse,
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct TouchPoint {
pub id: u64,
pub seat_id: u64,
pub position: LogicalPosition,
pub force: f32,
pub major: f32,
pub minor: f32,
pub orientation_rad: f32,
pub tool_type: TouchToolType,
}
#[must_use]
pub const fn touch_point_key(seat_id: u64, id: u64) -> u64 {
if seat_id == PRIMARY_POINTER_SEAT {
id
} else {
0x8000_0000_0000_0000 | (seat_id.rotate_left(32) ^ id)
}
}
impl_option!(
TouchPoint,
OptionTouchPoint,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
impl_vec!(
TouchPoint,
TouchPointVec,
TouchPointVecDestructor,
TouchPointVecDestructorType,
TouchPointVecSlice,
OptionTouchPoint
);
impl_vec_debug!(TouchPoint, TouchPointVec);
impl_vec_clone!(TouchPoint, TouchPointVec, TouchPointVecDestructor);
impl_vec_partialeq!(TouchPoint, TouchPointVec);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Ord, Eq)]
#[repr(C)]
#[derive(Default)]
pub enum WindowTheme {
DarkMode,
#[default]
LightMode,
}
impl_option!(
WindowTheme,
OptionWindowTheme,
[Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[repr(C)]
pub struct MonitorId {
pub index: usize,
pub hash: u64,
}
impl MonitorId {
pub const PRIMARY: Self = Self { index: 0, hash: 0 };
#[must_use]
pub const fn new(index: usize) -> Self {
Self { index, hash: 0 }
}
#[must_use]
pub const fn from_index_and_hash(index: usize, hash: u64) -> Self {
Self { index, hash }
}
#[must_use]
pub fn from_properties(
index: usize,
name: &str,
position: LayoutPoint,
size: LayoutSize,
) -> Self {
use core::hash::{Hash, Hasher};
struct FnvHasher(u64);
impl Hasher for FnvHasher {
fn write(&mut self, bytes: &[u8]) {
const FNV_PRIME: u64 = 0x0100_0000_01b3;
for &byte in bytes {
self.0 ^= u64::from(byte);
self.0 = self.0.wrapping_mul(FNV_PRIME);
}
}
fn finish(&self) -> u64 {
self.0
}
}
const FNV_OFFSET_BASIS: u64 = 0xcbf2_9ce4_8422_2325;
let mut hasher = FnvHasher(FNV_OFFSET_BASIS);
name.hash(&mut hasher);
(position.x as i64).hash(&mut hasher);
(position.y as i64).hash(&mut hasher);
(size.width as i64).hash(&mut hasher);
(size.height as i64).hash(&mut hasher);
Self {
index,
hash: hasher.finish(),
}
}
}
impl_option!(
MonitorId,
OptionMonitorId,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
#[derive(Debug, PartialEq, PartialOrd, Clone)]
#[repr(C)]
pub struct Monitor {
pub monitor_id: MonitorId,
pub monitor_name: OptionString,
pub size: LayoutSize,
pub position: LayoutPoint,
pub scale_factor: f64,
pub work_area: LayoutRect,
pub video_modes: VideoModeVec,
pub is_primary_monitor: bool,
}
impl_option!(
Monitor,
OptionMonitor,
copy = false,
[Debug, PartialEq, PartialOrd, Clone]
);
impl_vec!(
Monitor,
MonitorVec,
MonitorVecDestructor,
MonitorVecDestructorType,
MonitorVecSlice,
OptionMonitor
);
impl_vec_debug!(Monitor, MonitorVec);
impl_vec_clone!(Monitor, MonitorVec, MonitorVecDestructor);
impl_vec_partialeq!(Monitor, MonitorVec);
impl_vec_partialord!(Monitor, MonitorVec);
impl Hash for Monitor {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.monitor_id.hash(state);
}
}
impl Default for Monitor {
fn default() -> Self {
Self {
monitor_id: MonitorId::PRIMARY,
monitor_name: OptionString::None,
size: LayoutSize::zero(),
position: LayoutPoint::zero(),
scale_factor: 1.0,
work_area: LayoutRect::zero(),
video_modes: Vec::new().into(),
is_primary_monitor: false,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct VideoMode {
pub size: LayoutSize,
pub bit_depth: u16,
pub refresh_rate: u16,
}
impl_option!(
VideoMode,
OptionVideoMode,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_vec!(
VideoMode,
VideoModeVec,
VideoModeVecDestructor,
VideoModeVecDestructorType,
VideoModeVecSlice,
OptionVideoMode
);
impl_vec_clone!(VideoMode, VideoModeVec, VideoModeVecDestructor);
impl_vec_debug!(VideoMode, VideoModeVec);
impl_vec_partialeq!(VideoMode, VideoModeVec);
impl_vec_partialord!(VideoMode, VideoModeVec);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C, u8)]
#[derive(Default)]
pub enum WindowPosition {
#[default]
Uninitialized,
Initialized(PhysicalPositionI32),
RelativeToParentWindow(PhysicalPositionI32),
}
#[allow(variant_size_differences)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C, u8)]
#[derive(Default)]
pub enum ImePosition {
#[default]
Uninitialized,
Initialized(LogicalRect),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub struct WindowFlags {
pub frame: WindowFrame,
pub decorations: WindowDecorations,
pub background_material: WindowBackgroundMaterial,
pub window_type: WindowType,
pub close_requested: bool,
pub is_visible: bool,
pub is_always_on_top: bool,
pub is_resizable: bool,
pub has_focus: bool,
pub smooth_scroll_enabled: bool,
pub autotab_enabled: bool,
pub has_decorations: bool,
pub use_native_menus: bool,
pub use_native_context_menus: bool,
pub is_top_level: bool,
pub prevent_system_sleep: bool,
pub fullscreen_mode: FullScreenMode,
pub extend_into_safe_area: bool,
}
impl_option!(
WindowFlags,
OptionWindowFlags,
copy = false,
[Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub enum WindowType {
Normal,
Menu,
Tooltip,
Dialog,
}
impl Default for WindowType {
fn default() -> Self {
Self::Normal
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub enum WindowFrame {
Normal,
Minimized,
Maximized,
Fullscreen,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub enum WindowDecorations {
Normal,
NoTitle,
NoTitleAutoInject,
NoControls,
None,
}
impl Default for WindowDecorations {
fn default() -> Self {
Self::Normal
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub enum WindowBackgroundMaterial {
Opaque,
Transparent,
Sidebar,
Menu,
HUD,
Titlebar,
MicaAlt,
}
impl Default for WindowBackgroundMaterial {
fn default() -> Self {
Self::Opaque
}
}
impl Default for WindowFlags {
fn default() -> Self {
Self {
frame: WindowFrame::Normal,
decorations: WindowDecorations::Normal,
background_material: WindowBackgroundMaterial::Opaque,
window_type: WindowType::Normal,
close_requested: false,
is_visible: true,
is_always_on_top: false,
is_resizable: true,
has_focus: true,
smooth_scroll_enabled: true,
autotab_enabled: true,
has_decorations: false,
use_native_menus: cfg!(any(target_os = "windows", target_os = "macos")),
use_native_context_menus: cfg!(any(target_os = "windows", target_os = "macos")),
is_top_level: false,
prevent_system_sleep: false,
fullscreen_mode: FullScreenMode::FastFullScreen,
extend_into_safe_area: false,
}
}
}
impl WindowFlags {
#[inline]
#[must_use]
pub fn is_menu_window(&self) -> bool {
self.window_type == WindowType::Menu
}
#[inline]
#[must_use]
pub fn is_tooltip_window(&self) -> bool {
self.window_type == WindowType::Tooltip
}
#[inline]
#[must_use]
pub fn is_dialog_window(&self) -> bool {
self.window_type == WindowType::Dialog
}
#[inline]
#[must_use]
pub const fn window_has_focus(&self) -> bool {
self.has_focus
}
#[inline]
#[must_use]
pub const fn is_close_requested(&self) -> bool {
self.close_requested
}
#[inline]
#[must_use]
pub const fn has_csd(&self) -> bool {
self.has_decorations
}
#[inline]
#[must_use]
pub const fn use_native_menus(&self) -> bool {
self.use_native_menus
}
#[inline]
#[must_use]
pub const fn use_native_context_menus(&self) -> bool {
self.use_native_context_menus
}
}
#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct PlatformSpecificOptions {
pub windows_options: WindowsWindowOptions,
pub linux_options: LinuxWindowOptions,
pub mac_options: MacWindowOptions,
pub wasm_options: WasmWindowOptions,
}
unsafe impl Sync for PlatformSpecificOptions {}
#[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Send for PlatformSpecificOptions {}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct WindowsWindowOptions {
pub allow_drag_and_drop: bool,
pub no_redirection_bitmap: bool,
pub window_icon: OptionWindowIcon,
pub taskbar_icon: OptionTaskBarIcon,
}
impl Default for WindowsWindowOptions {
fn default() -> Self {
Self {
allow_drag_and_drop: true,
no_redirection_bitmap: false,
window_icon: OptionWindowIcon::None,
taskbar_icon: OptionTaskBarIcon::None,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
#[derive(Default)]
pub enum XWindowType {
Desktop,
Dock,
Toolbar,
Menu,
Utility,
Splash,
Dialog,
DropdownMenu,
PopupMenu,
Tooltip,
Notification,
Combo,
Dnd,
#[default]
Normal,
}
impl_option!(
XWindowType,
OptionXWindowType,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
#[repr(C)]
#[derive(Default)]
pub enum UserAttentionType {
#[default]
None,
Critical,
Informational,
}
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
#[repr(C)]
pub struct LinuxDecorationsState {
pub is_dragging_titlebar: bool,
pub close_button_hover: bool,
pub maximize_button_hover: bool,
pub minimize_button_hover: bool,
}
impl_option!(
LinuxDecorationsState,
OptionLinuxDecorationsState,
[Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
);
#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct LinuxWindowOptions {
pub wayland_theme: OptionWaylandTheme,
pub window_icon: OptionWindowIcon,
pub x11_gtk_theme_variant: OptionString,
pub wayland_app_id: OptionString,
pub x11_wm_classes: StringPairVec,
pub x11_window_types: XWindowTypeVec,
pub x11_visual: OptionX11Visual,
pub x11_resize_increments: OptionLogicalSize,
pub x11_base_size: OptionLogicalSize,
pub x11_screen: OptionI32,
pub request_user_attention: UserAttentionType,
pub x11_decorations_state: OptionLinuxDecorationsState,
pub x11_override_redirect: bool,
}
pub type X11Visual = *const c_void;
impl_option!(
X11Visual,
OptionX11Visual,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct AzStringPair {
pub key: AzString,
pub value: AzString,
}
impl_option!(
AzStringPair,
OptionStringPair,
copy = false,
[Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
);
impl_vec!(
AzStringPair,
StringPairVec,
StringPairVecDestructor,
StringPairVecDestructorType,
StringPairVecSlice,
OptionStringPair
);
impl_vec_mut!(AzStringPair, StringPairVec);
impl_vec_debug!(AzStringPair, StringPairVec);
impl_vec_partialord!(AzStringPair, StringPairVec);
impl_vec_ord!(AzStringPair, StringPairVec);
impl_vec_clone!(AzStringPair, StringPairVec, StringPairVecDestructor);
impl_vec_partialeq!(AzStringPair, StringPairVec);
impl_vec_eq!(AzStringPair, StringPairVec);
impl_vec_hash!(AzStringPair, StringPairVec);
impl_option!(
StringPairVec,
OptionStringPairVec,
copy = false,
[Debug, Clone, PartialOrd, PartialEq, Ord, Eq, Hash]
);
impl StringPairVec {
#[must_use]
pub fn get_key(&self, search_key: &str) -> Option<&AzString> {
self.as_ref().iter().find_map(|v| {
if v.key.as_str() == search_key {
Some(&v.value)
} else {
None
}
})
}
pub fn get_key_mut(&mut self, search_key: &str) -> Option<&mut AzStringPair> {
self.as_mut()
.iter_mut()
.find(|v| v.key.as_str() == search_key)
}
pub fn insert_kv<I: Into<AzString>>(&mut self, key: I, value: I) {
let key = key.into();
let value = value.into();
match self.get_key_mut(key.as_str()) {
None => {}
Some(s) => {
s.value = value;
return;
}
}
self.push(AzStringPair { key, value });
}
}
impl_vec!(
XWindowType,
XWindowTypeVec,
XWindowTypeVecDestructor,
XWindowTypeVecDestructorType,
XWindowTypeVecSlice,
OptionXWindowType
);
impl_vec_debug!(XWindowType, XWindowTypeVec);
impl_vec_partialord!(XWindowType, XWindowTypeVec);
impl_vec_ord!(XWindowType, XWindowTypeVec);
impl_vec_clone!(XWindowType, XWindowTypeVec, XWindowTypeVecDestructor);
impl_vec_partialeq!(XWindowType, XWindowTypeVec);
impl_vec_eq!(XWindowType, XWindowTypeVec);
impl_vec_hash!(XWindowType, XWindowTypeVec);
impl_option!(
WaylandTheme,
OptionWaylandTheme,
copy = false,
[Debug, Clone, PartialEq, PartialOrd]
);
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
#[allow(clippy::pub_underscore_fields)]
pub struct MacWindowOptions {
pub _reserved: u8,
}
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
#[allow(clippy::pub_underscore_fields)]
pub struct WasmWindowOptions {
pub _reserved: u8,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
#[derive(Default)]
pub enum FullScreenMode {
SlowFullScreen,
#[default]
FastFullScreen,
SlowWindowed,
FastWindowed,
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct WaylandTheme {
pub title_bar_active_background_color: ColorU,
pub title_bar_active_separator_color: ColorU,
pub title_bar_active_text_color: ColorU,
pub title_bar_inactive_background_color: ColorU,
pub title_bar_inactive_separator_color: ColorU,
pub title_bar_inactive_text_color: ColorU,
pub maximize_idle_foreground_inactive_color: ColorU,
pub minimize_idle_foreground_inactive_color: ColorU,
pub close_idle_foreground_inactive_color: ColorU,
pub maximize_hovered_foreground_inactive_color: ColorU,
pub minimize_hovered_foreground_inactive_color: ColorU,
pub close_hovered_foreground_inactive_color: ColorU,
pub maximize_disabled_foreground_inactive_color: ColorU,
pub minimize_disabled_foreground_inactive_color: ColorU,
pub close_disabled_foreground_inactive_color: ColorU,
pub maximize_idle_background_inactive_color: ColorU,
pub minimize_idle_background_inactive_color: ColorU,
pub close_idle_background_inactive_color: ColorU,
pub maximize_hovered_background_inactive_color: ColorU,
pub minimize_hovered_background_inactive_color: ColorU,
pub close_hovered_background_inactive_color: ColorU,
pub maximize_disabled_background_inactive_color: ColorU,
pub minimize_disabled_background_inactive_color: ColorU,
pub close_disabled_background_inactive_color: ColorU,
pub maximize_idle_foreground_active_color: ColorU,
pub minimize_idle_foreground_active_color: ColorU,
pub close_idle_foreground_active_color: ColorU,
pub maximize_hovered_foreground_active_color: ColorU,
pub minimize_hovered_foreground_active_color: ColorU,
pub close_hovered_foreground_active_color: ColorU,
pub maximize_disabled_foreground_active_color: ColorU,
pub minimize_disabled_foreground_active_color: ColorU,
pub close_disabled_foreground_active_color: ColorU,
pub maximize_idle_background_active_color: ColorU,
pub minimize_idle_background_active_color: ColorU,
pub close_idle_background_active_color: ColorU,
pub maximize_hovered_background_active_color: ColorU,
pub minimize_hovered_background_active_color: ColorU,
pub close_hovered_background_active_color: ColorU,
pub maximize_disabled_background_active_color: ColorU,
pub minimize_disabled_background_active_color: ColorU,
pub close_disabled_background_active_color: ColorU,
pub title_bar_font: AzString,
pub title_bar_font_size: f32,
}
pub const CSS_BREAKPOINTS: &[f32] = &[320.0, 480.0, 640.0, 768.0, 1024.0, 1280.0, 1440.0, 1920.0];
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct WindowSize {
pub dimensions: LogicalSize,
pub dpi: u32,
pub min_dimensions: OptionLogicalSize,
pub max_dimensions: OptionLogicalSize,
}
impl WindowSize {
#[allow(clippy::cast_possible_truncation)] #[must_use]
pub fn get_layout_size(&self) -> LayoutSize {
LayoutSize::new(
libm::roundf(self.dimensions.width) as isize,
libm::roundf(self.dimensions.height) as isize,
)
}
#[must_use]
pub const fn get_logical_size(&self) -> LogicalSize {
self.dimensions
}
#[must_use]
pub fn get_physical_size(&self) -> PhysicalSize<u32> {
self.dimensions
.to_physical(self.get_hidpi_factor().inner.get())
}
#[allow(clippy::cast_precision_loss)] #[must_use]
pub fn get_hidpi_factor(&self) -> DpiScaleFactor {
let dpi = if self.dpi == 0 { 96 } else { self.dpi };
DpiScaleFactor {
inner: FloatValue::new(dpi as f32 / 96.0),
}
}
}
impl Default for WindowSize {
fn default() -> Self {
Self {
dimensions: LogicalSize::new(640.0, 480.0),
dpi: 96,
min_dimensions: None.into(),
max_dimensions: None.into(),
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum RendererType {
Hardware,
Software,
}
impl_option!(
RendererType,
OptionRendererType,
[Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
);
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum UpdateFocusWarning {
FocusInvalidDomId(DomId),
FocusInvalidNodeId(NodeHierarchyItemId),
CouldNotFindFocusNode(CssPath),
}
impl ::core::fmt::Display for UpdateFocusWarning {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
use self::UpdateFocusWarning::{
CouldNotFindFocusNode, FocusInvalidDomId, FocusInvalidNodeId,
};
match self {
FocusInvalidDomId(dom_id) => write!(f, "Focusing on DOM with invalid ID: {dom_id:?}"),
FocusInvalidNodeId(node_id) => {
write!(f, "Focusing on node with invalid ID: {node_id}")
}
CouldNotFindFocusNode(css_path) => {
write!(f, "Could not find focus node for path: {css_path}")
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C, u8)]
pub enum AcceleratorKey {
Ctrl,
Alt,
Shift,
Key(VirtualKeyCode),
}
impl AcceleratorKey {
#[must_use]
pub fn matches(&self, keyboard_state: &KeyboardState) -> bool {
use self::AcceleratorKey::{Alt, Ctrl, Key, Shift};
match self {
Ctrl => keyboard_state.ctrl_down(),
Alt => keyboard_state.alt_down(),
Shift => keyboard_state.shift_down(),
Key(k) => keyboard_state.is_key_down(*k),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum VirtualKeyCode {
Key1,
Key2,
Key3,
Key4,
Key5,
Key6,
Key7,
Key8,
Key9,
Key0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
Escape,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
Snapshot,
Scroll,
Pause,
Insert,
Home,
Delete,
End,
PageDown,
PageUp,
Left,
Up,
Right,
Down,
Back,
Return,
Space,
Compose,
Caret,
Numlock,
Numpad0,
Numpad1,
Numpad2,
Numpad3,
Numpad4,
Numpad5,
Numpad6,
Numpad7,
Numpad8,
Numpad9,
NumpadAdd,
NumpadDivide,
NumpadDecimal,
NumpadComma,
NumpadEnter,
NumpadEquals,
NumpadMultiply,
NumpadSubtract,
AbntC1,
AbntC2,
Apostrophe,
Apps,
Asterisk,
At,
Ax,
Backslash,
Calculator,
Capital,
Colon,
Comma,
Convert,
Equals,
Grave,
Kana,
Kanji,
LAlt,
LBracket,
LControl,
LShift,
LWin,
Mail,
MediaSelect,
MediaStop,
Minus,
Mute,
MyComputer,
NavigateForward,
NavigateBackward,
NextTrack,
NoConvert,
OEM102,
Period,
PlayPause,
Plus,
Power,
PrevTrack,
RAlt,
RBracket,
RControl,
RShift,
RWin,
Semicolon,
Slash,
Sleep,
Stop,
Sysrq,
Tab,
Underline,
Unlabeled,
VolumeDown,
VolumeUp,
Wake,
WebBack,
WebFavorites,
WebForward,
WebHome,
WebRefresh,
WebSearch,
WebStop,
Yen,
Copy,
Paste,
Cut,
}
impl VirtualKeyCode {
#[must_use]
#[allow(clippy::too_many_lines)] pub const fn from_u32(v: u32) -> Option<Self> {
match v {
0 => Some(Self::Key1),
1 => Some(Self::Key2),
2 => Some(Self::Key3),
3 => Some(Self::Key4),
4 => Some(Self::Key5),
5 => Some(Self::Key6),
6 => Some(Self::Key7),
7 => Some(Self::Key8),
8 => Some(Self::Key9),
9 => Some(Self::Key0),
10 => Some(Self::A),
11 => Some(Self::B),
12 => Some(Self::C),
13 => Some(Self::D),
14 => Some(Self::E),
15 => Some(Self::F),
16 => Some(Self::G),
17 => Some(Self::H),
18 => Some(Self::I),
19 => Some(Self::J),
20 => Some(Self::K),
21 => Some(Self::L),
22 => Some(Self::M),
23 => Some(Self::N),
24 => Some(Self::O),
25 => Some(Self::P),
26 => Some(Self::Q),
27 => Some(Self::R),
28 => Some(Self::S),
29 => Some(Self::T),
30 => Some(Self::U),
31 => Some(Self::V),
32 => Some(Self::W),
33 => Some(Self::X),
34 => Some(Self::Y),
35 => Some(Self::Z),
36 => Some(Self::Escape),
37 => Some(Self::F1),
38 => Some(Self::F2),
39 => Some(Self::F3),
40 => Some(Self::F4),
41 => Some(Self::F5),
42 => Some(Self::F6),
43 => Some(Self::F7),
44 => Some(Self::F8),
45 => Some(Self::F9),
46 => Some(Self::F10),
47 => Some(Self::F11),
48 => Some(Self::F12),
49 => Some(Self::F13),
50 => Some(Self::F14),
51 => Some(Self::F15),
52 => Some(Self::F16),
53 => Some(Self::F17),
54 => Some(Self::F18),
55 => Some(Self::F19),
56 => Some(Self::F20),
57 => Some(Self::F21),
58 => Some(Self::F22),
59 => Some(Self::F23),
60 => Some(Self::F24),
61 => Some(Self::Snapshot),
62 => Some(Self::Scroll),
63 => Some(Self::Pause),
64 => Some(Self::Insert),
65 => Some(Self::Home),
66 => Some(Self::Delete),
67 => Some(Self::End),
68 => Some(Self::PageDown),
69 => Some(Self::PageUp),
70 => Some(Self::Left),
71 => Some(Self::Up),
72 => Some(Self::Right),
73 => Some(Self::Down),
74 => Some(Self::Back),
75 => Some(Self::Return),
76 => Some(Self::Space),
77 => Some(Self::Compose),
78 => Some(Self::Caret),
79 => Some(Self::Numlock),
80 => Some(Self::Numpad0),
81 => Some(Self::Numpad1),
82 => Some(Self::Numpad2),
83 => Some(Self::Numpad3),
84 => Some(Self::Numpad4),
85 => Some(Self::Numpad5),
86 => Some(Self::Numpad6),
87 => Some(Self::Numpad7),
88 => Some(Self::Numpad8),
89 => Some(Self::Numpad9),
90 => Some(Self::NumpadAdd),
91 => Some(Self::NumpadDivide),
92 => Some(Self::NumpadDecimal),
93 => Some(Self::NumpadComma),
94 => Some(Self::NumpadEnter),
95 => Some(Self::NumpadEquals),
96 => Some(Self::NumpadMultiply),
97 => Some(Self::NumpadSubtract),
98 => Some(Self::AbntC1),
99 => Some(Self::AbntC2),
100 => Some(Self::Apostrophe),
101 => Some(Self::Apps),
102 => Some(Self::Asterisk),
103 => Some(Self::At),
104 => Some(Self::Ax),
105 => Some(Self::Backslash),
106 => Some(Self::Calculator),
107 => Some(Self::Capital),
108 => Some(Self::Colon),
109 => Some(Self::Comma),
110 => Some(Self::Convert),
111 => Some(Self::Equals),
112 => Some(Self::Grave),
113 => Some(Self::Kana),
114 => Some(Self::Kanji),
115 => Some(Self::LAlt),
116 => Some(Self::LBracket),
117 => Some(Self::LControl),
118 => Some(Self::LShift),
119 => Some(Self::LWin),
120 => Some(Self::Mail),
121 => Some(Self::MediaSelect),
122 => Some(Self::MediaStop),
123 => Some(Self::Minus),
124 => Some(Self::Mute),
125 => Some(Self::MyComputer),
126 => Some(Self::NavigateForward),
127 => Some(Self::NavigateBackward),
128 => Some(Self::NextTrack),
129 => Some(Self::NoConvert),
130 => Some(Self::OEM102),
131 => Some(Self::Period),
132 => Some(Self::PlayPause),
133 => Some(Self::Plus),
134 => Some(Self::Power),
135 => Some(Self::PrevTrack),
136 => Some(Self::RAlt),
137 => Some(Self::RBracket),
138 => Some(Self::RControl),
139 => Some(Self::RShift),
140 => Some(Self::RWin),
141 => Some(Self::Semicolon),
142 => Some(Self::Slash),
143 => Some(Self::Sleep),
144 => Some(Self::Stop),
145 => Some(Self::Sysrq),
146 => Some(Self::Tab),
147 => Some(Self::Underline),
148 => Some(Self::Unlabeled),
149 => Some(Self::VolumeDown),
150 => Some(Self::VolumeUp),
151 => Some(Self::Wake),
152 => Some(Self::WebBack),
153 => Some(Self::WebFavorites),
154 => Some(Self::WebForward),
155 => Some(Self::WebHome),
156 => Some(Self::WebRefresh),
157 => Some(Self::WebSearch),
158 => Some(Self::WebStop),
159 => Some(Self::Yen),
160 => Some(Self::Copy),
161 => Some(Self::Paste),
162 => Some(Self::Cut),
_ => None,
}
}
#[must_use]
pub const fn get_lowercase(&self) -> Option<char> {
use self::VirtualKeyCode::{
Asterisk, At, Caret, Key0, Key1, Key2, Key3, Key4, Key5, Key6, Key7, Key8, Key9, Minus,
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8,
Numpad9, Period, Semicolon, Slash, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
R, S, T, U, V, W, X, Y, Z,
};
match self {
A => Some('a'),
B => Some('b'),
C => Some('c'),
D => Some('d'),
E => Some('e'),
F => Some('f'),
G => Some('g'),
H => Some('h'),
I => Some('i'),
J => Some('j'),
K => Some('k'),
L => Some('l'),
M => Some('m'),
N => Some('n'),
O => Some('o'),
P => Some('p'),
Q => Some('q'),
R => Some('r'),
S => Some('s'),
T => Some('t'),
U => Some('u'),
V => Some('v'),
W => Some('w'),
X => Some('x'),
Y => Some('y'),
Z => Some('z'),
Key0 | Numpad0 => Some('0'),
Key1 | Numpad1 => Some('1'),
Key2 | Numpad2 => Some('2'),
Key3 | Numpad3 => Some('3'),
Key4 | Numpad4 => Some('4'),
Key5 | Numpad5 => Some('5'),
Key6 | Numpad6 => Some('6'),
Key7 | Numpad7 => Some('7'),
Key8 | Numpad8 => Some('8'),
Key9 | Numpad9 => Some('9'),
Minus => Some('-'),
Asterisk => Some('*'),
At => Some('@'),
Period => Some('.'),
Semicolon => Some(';'),
Slash => Some('/'),
Caret => Some('^'),
_ => None,
}
}
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct SmallWindowIconBytes {
pub key: IconKey,
pub rgba_bytes: U8Vec,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct LargeWindowIconBytes {
pub key: IconKey,
pub rgba_bytes: U8Vec,
}
#[derive(Debug, Clone)]
#[repr(C, u8)]
pub enum WindowIcon {
Small(SmallWindowIconBytes),
Large(LargeWindowIconBytes),
}
impl_option!(
WindowIcon,
OptionWindowIcon,
copy = false,
[Debug, Clone, PartialOrd, PartialEq, Eq, Hash, Ord]
);
impl WindowIcon {
#[must_use]
pub const fn get_key(&self) -> IconKey {
match &self {
Self::Small(SmallWindowIconBytes { key, .. })
| Self::Large(LargeWindowIconBytes { key, .. }) => *key,
}
}
}
impl PartialEq for WindowIcon {
fn eq(&self, rhs: &Self) -> bool {
self.get_key() == rhs.get_key()
}
}
impl PartialOrd for WindowIcon {
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
Some((self.get_key()).cmp(&rhs.get_key()))
}
}
impl Eq for WindowIcon {}
impl Ord for WindowIcon {
fn cmp(&self, rhs: &Self) -> Ordering {
(self.get_key()).cmp(&rhs.get_key())
}
}
impl Hash for WindowIcon {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.get_key().hash(state);
}
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TaskBarIcon {
pub key: IconKey,
pub rgba_bytes: U8Vec,
}
impl_option!(
TaskBarIcon,
OptionTaskBarIcon,
copy = false,
[Debug, Clone, PartialOrd, PartialEq, Eq, Hash, Ord]
);
impl PartialEq for TaskBarIcon {
fn eq(&self, rhs: &Self) -> bool {
self.key == rhs.key
}
}
impl PartialOrd for TaskBarIcon {
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
Some((self.key).cmp(&rhs.key))
}
}
impl Eq for TaskBarIcon {}
impl Ord for TaskBarIcon {
fn cmp(&self, rhs: &Self) -> Ordering {
(self.key).cmp(&rhs.key)
}
}
impl Hash for TaskBarIcon {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.key.hash(state);
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum SysDialogType {
ReportProblem,
UpdateVersion,
TelemetryConsent,
GpuCheck,
}
#[cfg(test)]
#[path = "window_test.rs"]
mod window_test;