1#[cfg(not(feature = "std"))]
19use alloc::string::{String, ToString};
20use alloc::{
21 boxed::Box,
22 collections::{btree_map::BTreeMap, btree_set::BTreeSet},
23 vec::Vec,
24};
25use core::{
26 cmp::Ordering,
27 ffi::c_void,
28 hash::{Hash, Hasher},
29 ops,
30 sync::atomic::{AtomicI64, AtomicUsize, Ordering as AtomicOrdering},
31};
32
33use azul_css::{
34 css::CssPath,
35 props::{
36 basic::{ColorU, FloatValue, LayoutPoint, LayoutRect, LayoutSize},
37 property::CssProperty,
38 },
39 AzString, LayoutDebugMessage, OptionF32, OptionI32, OptionString, OptionU32, U8Vec,
40};
41use rust_fontconfig::FcFontCache;
42
43use crate::{
44 callbacks::{LayoutCallback, LayoutCallbackType, Update},
45 dom::{DomId, DomNodeId, NodeHierarchy},
46 geom::{
47 LogicalPosition, LogicalRect, LogicalSize, OptionLogicalSize, PhysicalPositionI32,
48 PhysicalSize,
49 },
50 gl::OptionGlContextPtr,
51 hit_test::{ExternalScrollId, OverflowingScrollNode},
52 id::{NodeDataContainer, NodeId},
53 refany::OptionRefAny,
54 resources::{
55 DpiScaleFactor, Epoch, GlTextureCache, IdNamespace, ImageCache, ImageMask, ImageRef,
56 RendererResources, ResourceUpdate,
57 },
58 selection::SelectionState,
59 styled_dom::NodeHierarchyItemId,
60 task::{Instant, ThreadId, TimerId},
61 FastBTreeSet, OrderedMap,
62};
63
64pub const DEFAULT_TITLE: &str = "Azul App";
65
66static LAST_WINDOW_ID: AtomicI64 = AtomicI64::new(0);
67
68#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
70#[repr(transparent)]
71pub struct WindowId {
72 pub id: i64,
73}
74
75impl Default for WindowId {
76 fn default() -> Self {
77 Self::new()
78 }
79}
80
81impl WindowId {
82 pub fn new() -> Self {
83 Self {
84 id: LAST_WINDOW_ID.fetch_add(1, AtomicOrdering::SeqCst),
85 }
86 }
87}
88
89static LAST_ICON_KEY: AtomicUsize = AtomicUsize::new(0);
90
91#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
95#[repr(C)]
96pub struct IconKey {
97 icon_id: usize,
98}
99
100impl Default for IconKey {
101 fn default() -> Self {
102 Self::new()
103 }
104}
105
106impl IconKey {
107 pub fn new() -> Self {
108 Self {
109 icon_id: LAST_ICON_KEY.fetch_add(1, AtomicOrdering::SeqCst),
110 }
111 }
112}
113
114#[repr(C)]
115#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
116pub struct RendererOptions {
117 pub vsync: Vsync,
118 pub srgb: Srgb,
119 pub hw_accel: HwAcceleration,
120}
121
122impl_option!(
123 RendererOptions,
124 OptionRendererOptions,
125 [PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash]
126);
127
128impl Default for RendererOptions {
129 fn default() -> Self {
130 Self {
131 vsync: Vsync::Enabled,
132 srgb: Srgb::Disabled,
133 hw_accel: HwAcceleration::DontCare,
138 }
139 }
140}
141
142impl RendererOptions {
143 #[must_use]
144 pub const fn new(vsync: Vsync, srgb: Srgb, hw_accel: HwAcceleration) -> Self {
145 Self {
146 vsync,
147 srgb,
148 hw_accel,
149 }
150 }
151}
152
153#[repr(C)]
154#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
155pub enum Vsync {
156 Enabled,
157 Disabled,
158 DontCare,
159}
160
161impl Vsync {
162 #[must_use]
163 pub const fn is_enabled(&self) -> bool {
164 matches!(self, Self::Enabled)
165 }
166}
167
168#[repr(C)]
169#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
170pub enum Srgb {
171 Enabled,
172 Disabled,
173 DontCare,
174}
175impl Srgb {
176 #[must_use]
177 pub const fn is_enabled(&self) -> bool {
178 matches!(self, Self::Enabled)
179 }
180}
181
182#[repr(C)]
183#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
184pub enum HwAcceleration {
185 Enabled,
186 Disabled,
187 DontCare,
188}
189impl HwAcceleration {
190 #[must_use]
191 pub const fn is_enabled(&self) -> bool {
192 matches!(self, Self::Enabled)
193 }
194}
195
196#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
197#[repr(C, u8)]
198pub enum RawWindowHandle {
199 IOS(IOSHandle),
200 MacOS(MacOSHandle),
201 Xlib(XlibHandle),
202 Xcb(XcbHandle),
203 Wayland(WaylandHandle),
204 Windows(WindowsHandle),
205 Web(WebHandle),
206 Android(AndroidHandle),
207 Unsupported,
208}
209
210unsafe impl Send for RawWindowHandle {}
214
215#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
216#[repr(C)]
217pub struct IOSHandle {
218 pub ui_window: *mut c_void,
219 pub ui_view: *mut c_void,
220 pub ui_view_controller: *mut c_void,
221}
222
223#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
224#[repr(C)]
225pub struct MacOSHandle {
226 pub ns_window: *mut c_void,
227 pub ns_view: *mut c_void,
228}
229
230#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
231#[repr(C)]
232pub struct XlibHandle {
233 pub window: u64,
235 pub display: *mut c_void,
236}
237
238#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
239#[repr(C)]
240pub struct XcbHandle {
241 pub window: u32,
243 pub connection: *mut c_void,
245}
246
247#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
248#[repr(C)]
249pub struct WaylandHandle {
250 pub surface: *mut c_void,
252 pub display: *mut c_void,
254}
255
256#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
257#[repr(C)]
258pub struct WindowsHandle {
259 pub hwnd: *mut c_void,
261 pub hinstance: *mut c_void,
263}
264
265#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
266#[repr(C)]
267pub struct WebHandle {
268 pub id: u32,
274}
275
276#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
277#[repr(C)]
278pub struct AndroidHandle {
279 pub a_native_window: *mut c_void,
281}
282
283#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
284#[repr(C)]
285#[derive(Default)]
286pub enum MouseCursorType {
287 #[default]
288 Default,
289 Crosshair,
290 Hand,
291 Arrow,
292 Move,
293 Text,
294 Wait,
295 Help,
296 Progress,
297 NotAllowed,
298 ContextMenu,
299 Cell,
300 VerticalText,
301 Alias,
302 Copy,
303 NoDrop,
304 Grab,
305 Grabbing,
306 AllScroll,
307 ZoomIn,
308 ZoomOut,
309 EResize,
310 NResize,
311 NeResize,
312 NwResize,
313 SResize,
314 SeResize,
315 SwResize,
316 WResize,
317 EwResize,
318 NsResize,
319 NeswResize,
320 NwseResize,
321 ColResize,
322 RowResize,
323}
324
325pub type ScanCode = u32;
327
328#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
334#[repr(C)]
335pub struct KeyLocks {
336 pub caps_lock: bool,
337 pub num_lock: bool,
338 pub scroll_lock: bool,
339}
340
341#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
358#[repr(C)]
359pub enum PhysicalKey {
360 Unidentified,
362 KeyA, KeyB, KeyC, KeyD, KeyE, KeyF, KeyG, KeyH, KeyI, KeyJ, KeyK, KeyL, KeyM,
368 KeyN, KeyO, KeyP, KeyQ, KeyR, KeyS, KeyT, KeyU, KeyV, KeyW, KeyX, KeyY, KeyZ,
369 Digit0, Digit1, Digit2, Digit3, Digit4, Digit5, Digit6, Digit7, Digit8, Digit9,
371 Backquote, Minus, Equal, BracketLeft, BracketRight, Backslash,
373 Semicolon, Quote, Comma, Period, Slash,
374 Enter, Tab, Space, Backspace, Escape, CapsLock,
376 ShiftLeft, ShiftRight, ControlLeft, ControlRight,
380 AltLeft, AltRight, MetaLeft, MetaRight, ContextMenu,
381 Insert, Delete, Home, End, PageUp, PageDown,
383 ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
384 F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
386 F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,
387 PrintScreen, ScrollLock, Pause,
389 NumLock, NumpadDivide, NumpadMultiply, NumpadSubtract, NumpadAdd,
392 NumpadEnter, NumpadDecimal, NumpadComma, NumpadEqual,
393 Numpad0, Numpad1, Numpad2, Numpad3, Numpad4,
394 Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
395 IntlBackslash, IntlRo, IntlYen, Lang1, Lang2, Convert, NonConvert, KanaMode,
397}
398
399#[derive(Default, Debug, Clone, PartialEq, Eq)]
401#[repr(C)]
402pub struct KeyboardState {
403 pub current_virtual_keycode: OptionVirtualKeyCode,
409 pub pressed_virtual_keycodes: VirtualKeyCodeVec,
420 pub pressed_scancodes: ScanCodeVec,
426 pub modifiers: crate::events::KeyModifiers,
433 pub locks: KeyLocks,
439 pub is_repeat: bool,
445 pub current_physical_key: OptionPhysicalKey,
447}
448
449impl KeyboardState {
450 #[must_use]
451 pub fn shift_down(&self) -> bool {
452 self.is_key_down(VirtualKeyCode::LShift) || self.is_key_down(VirtualKeyCode::RShift)
453 }
454 #[must_use]
455 pub fn ctrl_down(&self) -> bool {
456 self.is_key_down(VirtualKeyCode::LControl) || self.is_key_down(VirtualKeyCode::RControl)
457 }
458 #[must_use]
459 pub fn alt_down(&self) -> bool {
460 self.is_key_down(VirtualKeyCode::LAlt) || self.is_key_down(VirtualKeyCode::RAlt)
461 }
462 #[must_use]
463 pub fn super_down(&self) -> bool {
464 self.is_key_down(VirtualKeyCode::LWin) || self.is_key_down(VirtualKeyCode::RWin)
465 }
466 #[must_use]
472 pub fn primary_down(&self) -> bool {
473 if cfg!(target_os = "macos") {
474 self.super_down()
475 } else {
476 self.ctrl_down()
477 }
478 }
479 #[must_use]
480 pub fn is_key_down(&self, key: VirtualKeyCode) -> bool {
481 self.pressed_virtual_keycodes.iter().any(|k| *k == key)
482 }
483
484 #[must_use]
491 pub fn derived_modifiers(&self) -> crate::events::KeyModifiers {
492 crate::events::KeyModifiers {
493 shift: self.shift_down(),
494 ctrl: self.ctrl_down(),
495 alt: self.alt_down(),
496 meta: self.super_down(),
497 }
498 }
499
500 pub fn sync_modifiers(&mut self) {
510 self.modifiers = self.derived_modifiers();
511 }
512
513 #[must_use]
519 pub fn matches_accelerator(&self, chord: &[AcceleratorKey]) -> bool {
520 chord.iter().all(|a| a.matches(self))
521 }
522}
523
524impl_option!(
525 KeyboardState,
526 OptionKeyboardState,
527 copy = false,
528 [Debug, Clone, PartialEq, Eq]
529);
530
531impl_option!(
533 u32,
534 OptionChar,
535 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
536);
537impl_option!(
538 VirtualKeyCode,
539 OptionVirtualKeyCode,
540 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
541);
542impl_option!(
543 PhysicalKey,
544 OptionPhysicalKey,
545 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
546);
547
548impl_vec!(
549 VirtualKeyCode,
550 VirtualKeyCodeVec,
551 VirtualKeyCodeVecDestructor,
552 VirtualKeyCodeVecDestructorType,
553 VirtualKeyCodeVecSlice,
554 OptionVirtualKeyCode
555);
556impl_vec_debug!(VirtualKeyCode, VirtualKeyCodeVec);
557impl_vec_partialord!(VirtualKeyCode, VirtualKeyCodeVec);
558impl_vec_ord!(VirtualKeyCode, VirtualKeyCodeVec);
559impl_vec_clone!(
560 VirtualKeyCode,
561 VirtualKeyCodeVec,
562 VirtualKeyCodeVecDestructor
563);
564impl_vec_partialeq!(VirtualKeyCode, VirtualKeyCodeVec);
565impl_vec_eq!(VirtualKeyCode, VirtualKeyCodeVec);
566impl_vec_hash!(VirtualKeyCode, VirtualKeyCodeVec);
567impl_vec_mut!(VirtualKeyCode, VirtualKeyCodeVec);
568
569impl_vec_as_hashmap!(VirtualKeyCode, VirtualKeyCodeVec);
570
571impl_vec!(
572 ScanCode,
573 ScanCodeVec,
574 ScanCodeVecDestructor,
575 ScanCodeVecDestructorType,
576 ScanCodeVecSlice,
577 OptionU32
578);
579impl_vec_debug!(ScanCode, ScanCodeVec);
580impl_vec_partialord!(ScanCode, ScanCodeVec);
581impl_vec_ord!(ScanCode, ScanCodeVec);
582impl_vec_clone!(ScanCode, ScanCodeVec, ScanCodeVecDestructor);
583impl_vec_partialeq!(ScanCode, ScanCodeVec);
584impl_vec_eq!(ScanCode, ScanCodeVec);
585impl_vec_hash!(ScanCode, ScanCodeVec);
586impl_vec_mut!(ScanCode, ScanCodeVec);
587
588impl_vec_as_hashmap!(ScanCode, ScanCodeVec);
589
590#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq)]
592#[repr(C)]
593pub struct MouseState {
594 pub pointer_device_id: u64,
601 pub cursor_position: CursorPosition,
604 pub mouse_cursor_type: OptionMouseCursorType,
606 pub pointer_source: crate::events::PointerSource,
612 pub is_cursor_locked: bool,
615 pub left_down: bool,
617 pub right_down: bool,
619 pub middle_down: bool,
621 pub other_down: u8,
630}
631
632
633impl MouseState {
634 #[must_use]
636 pub const fn back_down(&self) -> bool {
637 self.other_down & crate::events::MOUSE_OTHER_MASK_BACK != 0
638 }
639
640 #[must_use]
642 pub const fn forward_down(&self) -> bool {
643 self.other_down & crate::events::MOUSE_OTHER_MASK_FORWARD != 0
644 }
645
646 #[must_use]
647 pub const fn matches(&self, context: &ContextMenuMouseButton) -> bool {
648 use self::ContextMenuMouseButton::{Left, Middle, Right};
649 match context {
650 Left => self.left_down,
651 Right => self.right_down,
652 Middle => self.middle_down,
653 }
654 }
655}
656
657impl_option!(
658 MouseState,
659 OptionMouseState,
660 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd]
661);
662
663impl_option!(
664 MouseCursorType,
665 OptionMouseCursorType,
666 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
667);
668
669impl Default for MouseState {
670 fn default() -> Self {
671 Self {
672 mouse_cursor_type: Some(MouseCursorType::Default).into(),
673 cursor_position: CursorPosition::default(),
674 is_cursor_locked: false,
675 left_down: false,
676 right_down: false,
677 middle_down: false,
678 other_down: 0,
679 pointer_source: crate::events::PointerSource::Unknown,
680 pointer_device_id: 0,
681 }
682 }
683}
684
685pub const PRIMARY_POINTER_SEAT: u64 = 0;
688
689#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd)]
707#[repr(C)]
708pub struct PointerSeat {
709 pub seat_id: u64,
712 pub state: MouseState,
714}
715
716impl_option!(
717 PointerSeat,
718 OptionPointerSeat,
719 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd]
720);
721
722impl_vec!(
723 PointerSeat,
724 PointerSeatVec,
725 PointerSeatVecDestructor,
726 PointerSeatVecDestructorType,
727 PointerSeatVecSlice,
728 OptionPointerSeat
729);
730impl_vec_debug!(PointerSeat, PointerSeatVec);
731impl_vec_clone!(PointerSeat, PointerSeatVec, PointerSeatVecDestructor);
732impl_vec_partialeq!(PointerSeat, PointerSeatVec);
733impl_vec_mut!(PointerSeat, PointerSeatVec);
734
735#[derive(Debug, Clone, PartialEq, Eq)]
745#[repr(C)]
746pub struct KeyboardSeat {
747 pub seat_id: u64,
750 pub state: KeyboardState,
752}
753
754impl_option!(
755 KeyboardSeat,
756 OptionKeyboardSeat,
757 copy = false,
758 [Debug, Clone, PartialEq, Eq]
759);
760
761impl_vec!(
762 KeyboardSeat,
763 KeyboardSeatVec,
764 KeyboardSeatVecDestructor,
765 KeyboardSeatVecDestructorType,
766 KeyboardSeatVecSlice,
767 OptionKeyboardSeat
768);
769impl_vec_debug!(KeyboardSeat, KeyboardSeatVec);
770impl_vec_clone!(KeyboardSeat, KeyboardSeatVec, KeyboardSeatVecDestructor);
771impl_vec_partialeq!(KeyboardSeat, KeyboardSeatVec);
772impl_vec_mut!(KeyboardSeat, KeyboardSeatVec);
773
774#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
775#[repr(C)]
776pub struct VirtualKeyCodeCombo {
777 pub keys: VirtualKeyCodeVec,
778}
779
780impl_option!(
781 VirtualKeyCodeCombo,
782 OptionVirtualKeyCodeCombo,
783 copy = false,
784 [Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord]
785);
786
787#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
788#[repr(C)]
789#[derive(Default)]
790pub enum ContextMenuMouseButton {
791 #[default]
792 Right,
793 Middle,
794 Left,
795}
796
797impl MouseState {
798 #[must_use]
800 pub const fn mouse_down(&self) -> bool {
801 self.right_down || self.left_down || self.middle_down
802 }
803
804 #[must_use]
806 pub const fn button_state(&self) -> crate::events::MouseButtonState {
807 crate::events::MouseButtonState {
808 left_down: self.left_down,
809 right_down: self.right_down,
810 middle_down: self.middle_down,
811 }
812 }
813}
814
815impl From<&MouseState> for crate::events::MouseButtonState {
816 fn from(s: &MouseState) -> Self {
817 s.button_state()
818 }
819}
820
821impl crate::events::MouseButtonState {
822 #[must_use]
824 pub const fn any_down(&self) -> bool {
825 self.left_down || self.right_down || self.middle_down
826 }
827}
828
829#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd)]
836#[repr(C)]
837pub struct ScrollResult {
838 pub scrolled_nodes: usize,
840 pub remaining_delta: LogicalPosition,
842 pub hit_scrollbar: bool,
844}
845
846#[must_use]
855pub fn process_system_scroll(delta: LogicalPosition, hit_scrollbar: bool) -> ScrollResult {
856 let consumed = delta.x != 0.0 || delta.y != 0.0;
857 ScrollResult {
858 scrolled_nodes: usize::from(consumed),
859 remaining_delta: LogicalPosition::zero(),
860 hit_scrollbar,
861 }
862}
863
864#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd)]
865#[repr(C, u8)]
866#[derive(Default)]
867pub enum CursorPosition {
868 OutOfWindow(LogicalPosition),
869 #[default]
870 Uninitialized,
871 InWindow(LogicalPosition),
872}
873
874impl CursorPosition {
875 #[must_use]
876 pub const fn get_position(&self) -> Option<LogicalPosition> {
877 match self {
878 Self::InWindow(logical_pos) => Some(*logical_pos),
879 Self::OutOfWindow(_) | Self::Uninitialized => None,
880 }
881 }
882
883 #[must_use]
884 pub const fn is_inside_window(&self) -> bool {
885 self.get_position().is_some()
886 }
887}
888
889#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
897#[repr(C)]
898pub struct DebugState {
899 pub show_hit_test_areas: bool,
906 pub profiler_dbg: bool,
907 pub render_target_dbg: bool,
908 pub texture_cache_dbg: bool,
909 pub gpu_time_queries: bool,
910 pub gpu_sample_queries: bool,
911 pub disable_batching: bool,
912 pub epochs: bool,
913 pub echo_driver_messages: bool,
914 pub show_overdraw: bool,
915 pub gpu_cache_dbg: bool,
916 pub texture_cache_dbg_clear_evicted: bool,
917 pub picture_caching_dbg: bool,
918 pub primitive_dbg: bool,
919 pub zoom_dbg: bool,
920 pub small_screen: bool,
921 pub disable_opaque_pass: bool,
922 pub disable_alpha_pass: bool,
923 pub disable_clip_masks: bool,
924 pub disable_text_prims: bool,
925 pub disable_gradient_prims: bool,
926 pub obscure_images: bool,
927 pub glyph_flashing: bool,
928 pub smart_profiler: bool,
929 pub invalidation_dbg: bool,
930 pub tile_cache_logging_dbg: bool,
931 pub profiler_capture: bool,
932 pub force_picture_invalidation: bool,
933}
934
935impl DebugState {
936 #[cfg(feature = "std")]
963 #[must_use]
964 pub fn from_az_overlay_env() -> Self {
965 std::env::var("AZ_OVERLAY")
966 .map_or_else(|_| Self::default(), |v| Self::from_overlay_spec(v.as_str()))
967 }
968
969 #[cfg(not(feature = "std"))]
971 #[must_use]
972 pub fn from_az_overlay_env() -> Self {
973 Self::default()
974 }
975
976 #[must_use]
979 pub fn from_overlay_spec(spec: &str) -> Self {
980 let mut s = Self::default();
981 for raw in spec.split(',') {
982 let verb = raw.trim().to_ascii_lowercase();
983 if verb.is_empty() {
984 continue;
985 }
986 match verb.as_str() {
987 "hit-test" | "hittest" => s.show_hit_test_areas = true,
989 "profiler" => s.profiler_dbg = true,
992 "smart-profiler" => s.smart_profiler = true,
993 "overdraw" => s.show_overdraw = true,
994 "render-targets" => s.render_target_dbg = true,
995 "texture-cache" => s.texture_cache_dbg = true,
996 "gpu-cache" => s.gpu_cache_dbg = true,
997 "picture-caching" => s.picture_caching_dbg = true,
998 "primitives" => s.primitive_dbg = true,
999 "invalidation" => s.invalidation_dbg = true,
1000 "epochs" => s.epochs = true,
1001 "zoom" => s.zoom_dbg = true,
1002 "glyph-flashing" => s.glyph_flashing = true,
1003 "obscure-images" => s.obscure_images = true,
1004 "gpu-time" => s.gpu_time_queries = true,
1005 "gpu-samples" => s.gpu_sample_queries = true,
1006 "echo-driver" => s.echo_driver_messages = true,
1007 "no-batching" => s.disable_batching = true,
1010 "no-opaque-pass" => s.disable_opaque_pass = true,
1011 "no-alpha-pass" => s.disable_alpha_pass = true,
1012 "no-clip-masks" => s.disable_clip_masks = true,
1013 "no-text" => s.disable_text_prims = true,
1014 "no-gradients" => s.disable_gradient_prims = true,
1015 "all" => {
1016 s.show_hit_test_areas = true;
1017 s.profiler_dbg = true;
1018 s.show_overdraw = true;
1019 s.primitive_dbg = true;
1020 }
1021 other => {
1022 #[cfg(feature = "std")]
1024 eprintln!(
1025 "[azul] AZ_OVERLAY: unknown verb {other:?}. Known: hit-test, profiler, \
1026 smart-profiler, overdraw, render-targets, texture-cache, gpu-cache, \
1027 picture-caching, primitives, invalidation, epochs, zoom, glyph-flashing, \
1028 obscure-images, gpu-time, gpu-samples, echo-driver, no-batching, \
1029 no-opaque-pass, no-alpha-pass, no-clip-masks, no-text, no-gradients, all"
1030 );
1031 }
1032 }
1033 }
1034 s
1035 }
1036}
1037
1038#[derive(Debug, Default, Clone, PartialEq)]
1039#[repr(C)]
1040pub struct TouchState {
1041 pub num_touches: usize,
1043 pub touch_points: TouchPointVec,
1046 pub coalesced_points: TouchPointVec,
1059 pub predicted_points: TouchPointVec,
1069}
1070
1071#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1079#[repr(C)]
1080pub enum TouchToolType {
1081 Unknown,
1083 Finger,
1085 Stylus,
1087 Eraser,
1089 Palm,
1091 Mouse,
1094}
1095
1096#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
1098#[repr(C)]
1099pub struct TouchPoint {
1100 pub id: u64,
1102 pub seat_id: u64,
1108 pub position: LogicalPosition,
1110 pub force: f32,
1113 pub major: f32,
1121 pub minor: f32,
1123 pub orientation_rad: f32,
1127 pub tool_type: TouchToolType,
1129}
1130
1131#[must_use]
1136pub const fn touch_point_key(seat_id: u64, id: u64) -> u64 {
1137 if seat_id == PRIMARY_POINTER_SEAT {
1138 id
1139 } else {
1140 0x8000_0000_0000_0000 | (seat_id.rotate_left(32) ^ id)
1141 }
1142}
1143
1144impl_option!(
1145 TouchPoint,
1146 OptionTouchPoint,
1147 [Debug, Copy, Clone, PartialEq, PartialOrd]
1148);
1149
1150impl_vec!(
1151 TouchPoint,
1152 TouchPointVec,
1153 TouchPointVecDestructor,
1154 TouchPointVecDestructorType,
1155 TouchPointVecSlice,
1156 OptionTouchPoint
1157);
1158impl_vec_debug!(TouchPoint, TouchPointVec);
1159impl_vec_clone!(TouchPoint, TouchPointVec, TouchPointVecDestructor);
1160impl_vec_partialeq!(TouchPoint, TouchPointVec);
1161
1162#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Ord, Eq)]
1164#[repr(C)]
1165#[derive(Default)]
1166pub enum WindowTheme {
1167 DarkMode,
1168 #[default]
1169 LightMode,
1170}
1171
1172impl_option!(
1173 WindowTheme,
1174 OptionWindowTheme,
1175 [Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
1176);
1177
1178#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
1189#[repr(C)]
1190pub struct MonitorId {
1191 pub index: usize,
1193 pub hash: u64,
1195}
1196
1197impl MonitorId {
1198 pub const PRIMARY: Self = Self { index: 0, hash: 0 };
1200
1201 #[must_use]
1203 pub const fn new(index: usize) -> Self {
1204 Self { index, hash: 0 }
1205 }
1206
1207 #[must_use]
1209 pub const fn from_index_and_hash(index: usize, hash: u64) -> Self {
1210 Self { index, hash }
1211 }
1212
1213 #[must_use]
1219 pub fn from_properties(
1220 index: usize,
1221 name: &str,
1222 position: LayoutPoint,
1223 size: LayoutSize,
1224 ) -> Self {
1225 use core::hash::{Hash, Hasher};
1226
1227 struct FnvHasher(u64);
1229
1230 impl Hasher for FnvHasher {
1231 fn write(&mut self, bytes: &[u8]) {
1232 const FNV_PRIME: u64 = 0x0100_0000_01b3;
1233 for &byte in bytes {
1234 self.0 ^= u64::from(byte);
1235 self.0 = self.0.wrapping_mul(FNV_PRIME);
1236 }
1237 }
1238
1239 fn finish(&self) -> u64 {
1240 self.0
1241 }
1242 }
1243
1244 const FNV_OFFSET_BASIS: u64 = 0xcbf2_9ce4_8422_2325;
1245 let mut hasher = FnvHasher(FNV_OFFSET_BASIS);
1246
1247 name.hash(&mut hasher);
1249 (position.x as i64).hash(&mut hasher);
1250 (position.y as i64).hash(&mut hasher);
1251 (size.width as i64).hash(&mut hasher);
1252 (size.height as i64).hash(&mut hasher);
1253
1254 Self {
1255 index,
1256 hash: hasher.finish(),
1257 }
1258 }
1259}
1260
1261impl_option!(
1262 MonitorId,
1263 OptionMonitorId,
1264 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
1265);
1266
1267#[derive(Debug, PartialEq, PartialOrd, Clone)]
1269#[repr(C)]
1270pub struct Monitor {
1271 pub monitor_id: MonitorId,
1273 pub monitor_name: OptionString,
1275 pub size: LayoutSize,
1277 pub position: LayoutPoint,
1279 pub scale_factor: f64,
1281 pub work_area: LayoutRect,
1283 pub video_modes: VideoModeVec,
1285 pub is_primary_monitor: bool,
1287}
1288
1289impl_option!(
1290 Monitor,
1291 OptionMonitor,
1292 copy = false,
1293 [Debug, PartialEq, PartialOrd, Clone]
1294);
1295
1296impl_vec!(
1297 Monitor,
1298 MonitorVec,
1299 MonitorVecDestructor,
1300 MonitorVecDestructorType,
1301 MonitorVecSlice,
1302 OptionMonitor
1303);
1304impl_vec_debug!(Monitor, MonitorVec);
1305impl_vec_clone!(Monitor, MonitorVec, MonitorVecDestructor);
1306impl_vec_partialeq!(Monitor, MonitorVec);
1307impl_vec_partialord!(Monitor, MonitorVec);
1308
1309impl Hash for Monitor {
1310 fn hash<H>(&self, state: &mut H)
1311 where
1312 H: Hasher,
1313 {
1314 self.monitor_id.hash(state);
1315 }
1316}
1317
1318impl Default for Monitor {
1319 fn default() -> Self {
1320 Self {
1321 monitor_id: MonitorId::PRIMARY,
1322 monitor_name: OptionString::None,
1323 size: LayoutSize::zero(),
1324 position: LayoutPoint::zero(),
1325 scale_factor: 1.0,
1326 work_area: LayoutRect::zero(),
1327 video_modes: Vec::new().into(),
1328 is_primary_monitor: false,
1329 }
1330 }
1331}
1332#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1333#[repr(C)]
1334pub struct VideoMode {
1335 pub size: LayoutSize,
1336 pub bit_depth: u16,
1337 pub refresh_rate: u16,
1338}
1339
1340impl_option!(
1341 VideoMode,
1342 OptionVideoMode,
1343 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
1344);
1345
1346impl_vec!(
1347 VideoMode,
1348 VideoModeVec,
1349 VideoModeVecDestructor,
1350 VideoModeVecDestructorType,
1351 VideoModeVecSlice,
1352 OptionVideoMode
1353);
1354impl_vec_clone!(VideoMode, VideoModeVec, VideoModeVecDestructor);
1355impl_vec_debug!(VideoMode, VideoModeVec);
1356impl_vec_partialeq!(VideoMode, VideoModeVec);
1357impl_vec_partialord!(VideoMode, VideoModeVec);
1358
1359#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1361#[repr(C, u8)]
1362#[derive(Default)]
1363pub enum WindowPosition {
1364 #[default]
1365 Uninitialized,
1366 Initialized(PhysicalPositionI32),
1369 RelativeToParentWindow(PhysicalPositionI32),
1377}
1378#[allow(variant_size_differences)]
1379#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1381#[repr(C, u8)]
1382#[derive(Default)]
1384pub enum ImePosition {
1385 #[default]
1386 Uninitialized,
1387 Initialized(LogicalRect),
1388}
1389
1390#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
1391#[repr(C)]
1392pub struct WindowFlags {
1393 pub frame: WindowFrame,
1395 pub decorations: WindowDecorations,
1397 pub background_material: WindowBackgroundMaterial,
1399 pub window_type: WindowType,
1401 pub close_requested: bool,
1404 pub is_visible: bool,
1406 pub is_always_on_top: bool,
1408 pub is_resizable: bool,
1410 pub has_focus: bool,
1412 pub smooth_scroll_enabled: bool,
1414 pub autotab_enabled: bool,
1416 pub has_decorations: bool,
1419 pub use_native_menus: bool,
1422 pub use_native_context_menus: bool,
1425 pub is_top_level: bool,
1429 pub prevent_system_sleep: bool,
1433 pub fullscreen_mode: FullScreenMode,
1442 pub extend_into_safe_area: bool,
1453}
1454
1455impl_option!(
1456 WindowFlags,
1457 OptionWindowFlags,
1458 copy = false,
1459 [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
1460);
1461
1462#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
1464#[repr(C)]
1465pub enum WindowType {
1466 Normal,
1468 Menu,
1470 Tooltip,
1472 Dialog,
1474}
1475
1476impl Default for WindowType {
1477 fn default() -> Self {
1478 Self::Normal
1479 }
1480}
1481
1482#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
1484#[repr(C)]
1485pub enum WindowFrame {
1486 Normal,
1487 Minimized,
1488 Maximized,
1489 Fullscreen,
1490}
1491
1492#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
1494#[repr(C)]
1495pub enum WindowDecorations {
1496 Normal,
1498 NoTitle,
1501 NoTitleAutoInject,
1509 NoControls,
1511 None,
1513}
1514
1515impl Default for WindowDecorations {
1516 fn default() -> Self {
1517 Self::Normal
1518 }
1519}
1520
1521#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
1534#[repr(C)]
1535pub enum WindowBackgroundMaterial {
1536 Opaque,
1538 Transparent,
1540 Sidebar,
1542 Menu,
1544 HUD,
1546 Titlebar,
1548 MicaAlt,
1550}
1551
1552impl Default for WindowBackgroundMaterial {
1553 fn default() -> Self {
1554 Self::Opaque
1555 }
1556}
1557
1558impl Default for WindowFlags {
1559 fn default() -> Self {
1560 Self {
1561 frame: WindowFrame::Normal,
1562 decorations: WindowDecorations::Normal,
1563 background_material: WindowBackgroundMaterial::Opaque,
1564 window_type: WindowType::Normal,
1565 close_requested: false,
1566 is_visible: true,
1567 is_always_on_top: false,
1568 is_resizable: true,
1569 has_focus: true,
1570 smooth_scroll_enabled: true,
1571 autotab_enabled: true,
1572 has_decorations: false,
1573 use_native_menus: cfg!(any(target_os = "windows", target_os = "macos")),
1576 use_native_context_menus: cfg!(any(target_os = "windows", target_os = "macos")),
1577 is_top_level: false,
1578 prevent_system_sleep: false,
1579 fullscreen_mode: FullScreenMode::FastFullScreen,
1580 extend_into_safe_area: false,
1581 }
1582 }
1583}
1584
1585impl WindowFlags {
1586 #[inline]
1588 #[must_use]
1589 pub fn is_menu_window(&self) -> bool {
1590 self.window_type == WindowType::Menu
1591 }
1592
1593 #[inline]
1595 #[must_use]
1596 pub fn is_tooltip_window(&self) -> bool {
1597 self.window_type == WindowType::Tooltip
1598 }
1599
1600 #[inline]
1602 #[must_use]
1603 pub fn is_dialog_window(&self) -> bool {
1604 self.window_type == WindowType::Dialog
1605 }
1606
1607 #[inline]
1609 #[must_use]
1610 pub const fn window_has_focus(&self) -> bool {
1611 self.has_focus
1612 }
1613
1614 #[inline]
1616 #[must_use]
1617 pub const fn is_close_requested(&self) -> bool {
1618 self.close_requested
1619 }
1620
1621 #[inline]
1623 #[must_use]
1624 pub const fn has_csd(&self) -> bool {
1625 self.has_decorations
1626 }
1627
1628 #[inline]
1630 #[must_use]
1631 pub const fn use_native_menus(&self) -> bool {
1632 self.use_native_menus
1633 }
1634
1635 #[inline]
1637 #[must_use]
1638 pub const fn use_native_context_menus(&self) -> bool {
1639 self.use_native_context_menus
1640 }
1641}
1642
1643#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
1645#[repr(C)]
1646pub struct PlatformSpecificOptions {
1647 pub windows_options: WindowsWindowOptions,
1648 pub linux_options: LinuxWindowOptions,
1649 pub mac_options: MacWindowOptions,
1650 pub wasm_options: WasmWindowOptions,
1651}
1652
1653unsafe impl Sync for PlatformSpecificOptions {}
1656#[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Send for PlatformSpecificOptions {}
1658
1659#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
1660#[repr(C)]
1661pub struct WindowsWindowOptions {
1662 pub allow_drag_and_drop: bool,
1664 pub no_redirection_bitmap: bool,
1666 pub window_icon: OptionWindowIcon,
1668 pub taskbar_icon: OptionTaskBarIcon,
1672 }
1677
1678impl Default for WindowsWindowOptions {
1679 fn default() -> Self {
1680 Self {
1681 allow_drag_and_drop: true,
1682 no_redirection_bitmap: false,
1683 window_icon: OptionWindowIcon::None,
1684 taskbar_icon: OptionTaskBarIcon::None,
1685 }
1686 }
1687}
1688
1689#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1692#[repr(C)]
1693#[derive(Default)]
1694pub enum XWindowType {
1695 Desktop,
1699 Dock,
1702 Toolbar,
1704 Menu,
1706 Utility,
1708 Splash,
1710 Dialog,
1712 DropdownMenu,
1715 PopupMenu,
1718 Tooltip,
1721 Notification,
1724 Combo,
1727 Dnd,
1730 #[default]
1732 Normal,
1733}
1734
1735impl_option!(
1736 XWindowType,
1737 OptionXWindowType,
1738 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
1739);
1740
1741#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
1742#[repr(C)]
1743#[derive(Default)]
1744pub enum UserAttentionType {
1745 #[default]
1746 None,
1747 Critical,
1748 Informational,
1749}
1750
1751#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
1753#[repr(C)]
1754pub struct LinuxDecorationsState {
1755 pub is_dragging_titlebar: bool,
1756 pub close_button_hover: bool,
1757 pub maximize_button_hover: bool,
1758 pub minimize_button_hover: bool,
1759}
1760
1761impl_option!(
1762 LinuxDecorationsState,
1763 OptionLinuxDecorationsState,
1764 [Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
1765);
1766
1767#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
1768#[repr(C)]
1769pub struct LinuxWindowOptions {
1770 pub wayland_theme: OptionWaylandTheme,
1771 pub window_icon: OptionWindowIcon,
1772 pub x11_gtk_theme_variant: OptionString,
1775 pub wayland_app_id: OptionString,
1782 pub x11_wm_classes: StringPairVec,
1785 pub x11_window_types: XWindowTypeVec,
1788 pub x11_visual: OptionX11Visual,
1790 pub x11_resize_increments: OptionLogicalSize,
1793 pub x11_base_size: OptionLogicalSize,
1796 pub x11_screen: OptionI32,
1798 pub request_user_attention: UserAttentionType,
1799 pub x11_decorations_state: OptionLinuxDecorationsState,
1801 pub x11_override_redirect: bool,
1804}
1805
1806pub type X11Visual = *const c_void;
1807impl_option!(
1808 X11Visual,
1809 OptionX11Visual,
1810 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
1811);
1812
1813#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1815#[repr(C)]
1816pub struct AzStringPair {
1817 pub key: AzString,
1818 pub value: AzString,
1819}
1820
1821impl_option!(
1822 AzStringPair,
1823 OptionStringPair,
1824 copy = false,
1825 [Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
1826);
1827
1828impl_vec!(
1829 AzStringPair,
1830 StringPairVec,
1831 StringPairVecDestructor,
1832 StringPairVecDestructorType,
1833 StringPairVecSlice,
1834 OptionStringPair
1835);
1836impl_vec_mut!(AzStringPair, StringPairVec);
1837impl_vec_debug!(AzStringPair, StringPairVec);
1838impl_vec_partialord!(AzStringPair, StringPairVec);
1839impl_vec_ord!(AzStringPair, StringPairVec);
1840impl_vec_clone!(AzStringPair, StringPairVec, StringPairVecDestructor);
1841impl_vec_partialeq!(AzStringPair, StringPairVec);
1842impl_vec_eq!(AzStringPair, StringPairVec);
1843impl_vec_hash!(AzStringPair, StringPairVec);
1844
1845impl_option!(
1846 StringPairVec,
1847 OptionStringPairVec,
1848 copy = false,
1849 [Debug, Clone, PartialOrd, PartialEq, Ord, Eq, Hash]
1850);
1851
1852impl StringPairVec {
1853 #[must_use]
1854 pub fn get_key(&self, search_key: &str) -> Option<&AzString> {
1855 self.as_ref().iter().find_map(|v| {
1856 if v.key.as_str() == search_key {
1857 Some(&v.value)
1858 } else {
1859 None
1860 }
1861 })
1862 }
1863 pub fn get_key_mut(&mut self, search_key: &str) -> Option<&mut AzStringPair> {
1864 self.as_mut()
1865 .iter_mut()
1866 .find(|v| v.key.as_str() == search_key)
1867 }
1868 pub fn insert_kv<I: Into<AzString>>(&mut self, key: I, value: I) {
1869 let key = key.into();
1870 let value = value.into();
1871 match self.get_key_mut(key.as_str()) {
1872 None => {}
1873 Some(s) => {
1874 s.value = value;
1875 return;
1876 }
1877 }
1878 self.push(AzStringPair { key, value });
1879 }
1880}
1881
1882impl_vec!(
1883 XWindowType,
1884 XWindowTypeVec,
1885 XWindowTypeVecDestructor,
1886 XWindowTypeVecDestructorType,
1887 XWindowTypeVecSlice,
1888 OptionXWindowType
1889);
1890impl_vec_debug!(XWindowType, XWindowTypeVec);
1891impl_vec_partialord!(XWindowType, XWindowTypeVec);
1892impl_vec_ord!(XWindowType, XWindowTypeVec);
1893impl_vec_clone!(XWindowType, XWindowTypeVec, XWindowTypeVecDestructor);
1894impl_vec_partialeq!(XWindowType, XWindowTypeVec);
1895impl_vec_eq!(XWindowType, XWindowTypeVec);
1896impl_vec_hash!(XWindowType, XWindowTypeVec);
1897
1898impl_option!(
1899 WaylandTheme,
1900 OptionWaylandTheme,
1901 copy = false,
1902 [Debug, Clone, PartialEq, PartialOrd]
1903);
1904
1905#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1907#[repr(C)]
1908#[allow(clippy::pub_underscore_fields)]
1910pub struct MacWindowOptions {
1911 pub _reserved: u8,
1913}
1914
1915#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1917#[repr(C)]
1918#[allow(clippy::pub_underscore_fields)]
1920pub struct WasmWindowOptions {
1921 pub _reserved: u8,
1923}
1924
1925#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1926#[repr(C)]
1927#[derive(Default)]
1928pub enum FullScreenMode {
1929 SlowFullScreen,
1932 #[default]
1935 FastFullScreen,
1936 SlowWindowed,
1939 FastWindowed,
1942}
1943
1944#[derive(Debug, Clone, PartialEq, PartialOrd)]
1947#[repr(C)]
1948pub struct WaylandTheme {
1949 pub title_bar_active_background_color: ColorU,
1950 pub title_bar_active_separator_color: ColorU,
1951 pub title_bar_active_text_color: ColorU,
1952 pub title_bar_inactive_background_color: ColorU,
1953 pub title_bar_inactive_separator_color: ColorU,
1954 pub title_bar_inactive_text_color: ColorU,
1955 pub maximize_idle_foreground_inactive_color: ColorU,
1956 pub minimize_idle_foreground_inactive_color: ColorU,
1957 pub close_idle_foreground_inactive_color: ColorU,
1958 pub maximize_hovered_foreground_inactive_color: ColorU,
1959 pub minimize_hovered_foreground_inactive_color: ColorU,
1960 pub close_hovered_foreground_inactive_color: ColorU,
1961 pub maximize_disabled_foreground_inactive_color: ColorU,
1962 pub minimize_disabled_foreground_inactive_color: ColorU,
1963 pub close_disabled_foreground_inactive_color: ColorU,
1964 pub maximize_idle_background_inactive_color: ColorU,
1965 pub minimize_idle_background_inactive_color: ColorU,
1966 pub close_idle_background_inactive_color: ColorU,
1967 pub maximize_hovered_background_inactive_color: ColorU,
1968 pub minimize_hovered_background_inactive_color: ColorU,
1969 pub close_hovered_background_inactive_color: ColorU,
1970 pub maximize_disabled_background_inactive_color: ColorU,
1971 pub minimize_disabled_background_inactive_color: ColorU,
1972 pub close_disabled_background_inactive_color: ColorU,
1973 pub maximize_idle_foreground_active_color: ColorU,
1974 pub minimize_idle_foreground_active_color: ColorU,
1975 pub close_idle_foreground_active_color: ColorU,
1976 pub maximize_hovered_foreground_active_color: ColorU,
1977 pub minimize_hovered_foreground_active_color: ColorU,
1978 pub close_hovered_foreground_active_color: ColorU,
1979 pub maximize_disabled_foreground_active_color: ColorU,
1980 pub minimize_disabled_foreground_active_color: ColorU,
1981 pub close_disabled_foreground_active_color: ColorU,
1982 pub maximize_idle_background_active_color: ColorU,
1983 pub minimize_idle_background_active_color: ColorU,
1984 pub close_idle_background_active_color: ColorU,
1985 pub maximize_hovered_background_active_color: ColorU,
1986 pub minimize_hovered_background_active_color: ColorU,
1987 pub close_hovered_background_active_color: ColorU,
1988 pub maximize_disabled_background_active_color: ColorU,
1989 pub minimize_disabled_background_active_color: ColorU,
1990 pub close_disabled_background_active_color: ColorU,
1991 pub title_bar_font: AzString,
1992 pub title_bar_font_size: f32,
1993}
1994
1995pub const CSS_BREAKPOINTS: &[f32] = &[320.0, 480.0, 640.0, 768.0, 1024.0, 1280.0, 1440.0, 1920.0];
2006
2007#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd)]
2008#[repr(C)]
2009pub struct WindowSize {
2010 pub dimensions: LogicalSize,
2013 pub dpi: u32,
2015 pub min_dimensions: OptionLogicalSize,
2017 pub max_dimensions: OptionLogicalSize,
2019}
2020
2021impl WindowSize {
2022 #[allow(clippy::cast_possible_truncation)] #[must_use]
2024 pub fn get_layout_size(&self) -> LayoutSize {
2025 LayoutSize::new(
2026 libm::roundf(self.dimensions.width) as isize,
2027 libm::roundf(self.dimensions.height) as isize,
2028 )
2029 }
2030
2031 #[must_use]
2033 pub const fn get_logical_size(&self) -> LogicalSize {
2034 self.dimensions
2035 }
2036
2037 #[must_use]
2038 pub fn get_physical_size(&self) -> PhysicalSize<u32> {
2039 self.dimensions
2040 .to_physical(self.get_hidpi_factor().inner.get())
2041 }
2042
2043 #[allow(clippy::cast_precision_loss)] #[must_use]
2045 pub fn get_hidpi_factor(&self) -> DpiScaleFactor {
2046 let dpi = if self.dpi == 0 { 96 } else { self.dpi };
2051 DpiScaleFactor {
2052 inner: FloatValue::new(dpi as f32 / 96.0),
2053 }
2054 }
2055}
2056
2057impl Default for WindowSize {
2058 fn default() -> Self {
2059 Self {
2060 dimensions: LogicalSize::new(640.0, 480.0),
2061 dpi: 96,
2062 min_dimensions: None.into(),
2063 max_dimensions: None.into(),
2064 }
2065 }
2066}
2067
2068#[repr(C)]
2069#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
2070pub enum RendererType {
2071 Hardware,
2073 Software,
2075}
2076
2077impl_option!(
2078 RendererType,
2079 OptionRendererType,
2080 [Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
2081);
2082
2083#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
2084pub enum UpdateFocusWarning {
2085 FocusInvalidDomId(DomId),
2086 FocusInvalidNodeId(NodeHierarchyItemId),
2087 CouldNotFindFocusNode(CssPath),
2088}
2089
2090impl ::core::fmt::Display for UpdateFocusWarning {
2091 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
2092 use self::UpdateFocusWarning::{
2093 CouldNotFindFocusNode, FocusInvalidDomId, FocusInvalidNodeId,
2094 };
2095 match self {
2096 FocusInvalidDomId(dom_id) => write!(f, "Focusing on DOM with invalid ID: {dom_id:?}"),
2097 FocusInvalidNodeId(node_id) => {
2098 write!(f, "Focusing on node with invalid ID: {node_id}")
2099 }
2100 CouldNotFindFocusNode(css_path) => {
2101 write!(f, "Could not find focus node for path: {css_path}")
2102 }
2103 }
2104 }
2105}
2106
2107#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2109#[repr(C, u8)]
2110pub enum AcceleratorKey {
2111 Ctrl,
2112 Alt,
2113 Shift,
2114 Key(VirtualKeyCode),
2115}
2116
2117impl AcceleratorKey {
2118 #[must_use]
2122 pub fn matches(&self, keyboard_state: &KeyboardState) -> bool {
2123 use self::AcceleratorKey::{Alt, Ctrl, Key, Shift};
2124 match self {
2125 Ctrl => keyboard_state.ctrl_down(),
2126 Alt => keyboard_state.alt_down(),
2127 Shift => keyboard_state.shift_down(),
2128 Key(k) => keyboard_state.is_key_down(*k),
2129 }
2130 }
2131}
2132
2133#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2135#[repr(C)]
2136pub enum VirtualKeyCode {
2137 Key1,
2138 Key2,
2139 Key3,
2140 Key4,
2141 Key5,
2142 Key6,
2143 Key7,
2144 Key8,
2145 Key9,
2146 Key0,
2147 A,
2148 B,
2149 C,
2150 D,
2151 E,
2152 F,
2153 G,
2154 H,
2155 I,
2156 J,
2157 K,
2158 L,
2159 M,
2160 N,
2161 O,
2162 P,
2163 Q,
2164 R,
2165 S,
2166 T,
2167 U,
2168 V,
2169 W,
2170 X,
2171 Y,
2172 Z,
2173 Escape,
2174 F1,
2175 F2,
2176 F3,
2177 F4,
2178 F5,
2179 F6,
2180 F7,
2181 F8,
2182 F9,
2183 F10,
2184 F11,
2185 F12,
2186 F13,
2187 F14,
2188 F15,
2189 F16,
2190 F17,
2191 F18,
2192 F19,
2193 F20,
2194 F21,
2195 F22,
2196 F23,
2197 F24,
2198 Snapshot,
2199 Scroll,
2200 Pause,
2201 Insert,
2202 Home,
2203 Delete,
2204 End,
2205 PageDown,
2206 PageUp,
2207 Left,
2208 Up,
2209 Right,
2210 Down,
2211 Back,
2212 Return,
2213 Space,
2214 Compose,
2215 Caret,
2216 Numlock,
2217 Numpad0,
2218 Numpad1,
2219 Numpad2,
2220 Numpad3,
2221 Numpad4,
2222 Numpad5,
2223 Numpad6,
2224 Numpad7,
2225 Numpad8,
2226 Numpad9,
2227 NumpadAdd,
2228 NumpadDivide,
2229 NumpadDecimal,
2230 NumpadComma,
2231 NumpadEnter,
2232 NumpadEquals,
2233 NumpadMultiply,
2234 NumpadSubtract,
2235 AbntC1,
2236 AbntC2,
2237 Apostrophe,
2238 Apps,
2239 Asterisk,
2240 At,
2241 Ax,
2242 Backslash,
2243 Calculator,
2244 Capital,
2245 Colon,
2246 Comma,
2247 Convert,
2248 Equals,
2249 Grave,
2250 Kana,
2251 Kanji,
2252 LAlt,
2253 LBracket,
2254 LControl,
2255 LShift,
2256 LWin,
2257 Mail,
2258 MediaSelect,
2259 MediaStop,
2260 Minus,
2261 Mute,
2262 MyComputer,
2263 NavigateForward,
2264 NavigateBackward,
2265 NextTrack,
2266 NoConvert,
2267 OEM102,
2268 Period,
2269 PlayPause,
2270 Plus,
2271 Power,
2272 PrevTrack,
2273 RAlt,
2274 RBracket,
2275 RControl,
2276 RShift,
2277 RWin,
2278 Semicolon,
2279 Slash,
2280 Sleep,
2281 Stop,
2282 Sysrq,
2283 Tab,
2284 Underline,
2285 Unlabeled,
2286 VolumeDown,
2287 VolumeUp,
2288 Wake,
2289 WebBack,
2290 WebFavorites,
2291 WebForward,
2292 WebHome,
2293 WebRefresh,
2294 WebSearch,
2295 WebStop,
2296 Yen,
2297 Copy,
2298 Paste,
2299 Cut,
2300}
2301
2302impl VirtualKeyCode {
2303 #[must_use]
2311 #[allow(clippy::too_many_lines)] pub const fn from_u32(v: u32) -> Option<Self> {
2313 match v {
2314 0 => Some(Self::Key1),
2315 1 => Some(Self::Key2),
2316 2 => Some(Self::Key3),
2317 3 => Some(Self::Key4),
2318 4 => Some(Self::Key5),
2319 5 => Some(Self::Key6),
2320 6 => Some(Self::Key7),
2321 7 => Some(Self::Key8),
2322 8 => Some(Self::Key9),
2323 9 => Some(Self::Key0),
2324 10 => Some(Self::A),
2325 11 => Some(Self::B),
2326 12 => Some(Self::C),
2327 13 => Some(Self::D),
2328 14 => Some(Self::E),
2329 15 => Some(Self::F),
2330 16 => Some(Self::G),
2331 17 => Some(Self::H),
2332 18 => Some(Self::I),
2333 19 => Some(Self::J),
2334 20 => Some(Self::K),
2335 21 => Some(Self::L),
2336 22 => Some(Self::M),
2337 23 => Some(Self::N),
2338 24 => Some(Self::O),
2339 25 => Some(Self::P),
2340 26 => Some(Self::Q),
2341 27 => Some(Self::R),
2342 28 => Some(Self::S),
2343 29 => Some(Self::T),
2344 30 => Some(Self::U),
2345 31 => Some(Self::V),
2346 32 => Some(Self::W),
2347 33 => Some(Self::X),
2348 34 => Some(Self::Y),
2349 35 => Some(Self::Z),
2350 36 => Some(Self::Escape),
2351 37 => Some(Self::F1),
2352 38 => Some(Self::F2),
2353 39 => Some(Self::F3),
2354 40 => Some(Self::F4),
2355 41 => Some(Self::F5),
2356 42 => Some(Self::F6),
2357 43 => Some(Self::F7),
2358 44 => Some(Self::F8),
2359 45 => Some(Self::F9),
2360 46 => Some(Self::F10),
2361 47 => Some(Self::F11),
2362 48 => Some(Self::F12),
2363 49 => Some(Self::F13),
2364 50 => Some(Self::F14),
2365 51 => Some(Self::F15),
2366 52 => Some(Self::F16),
2367 53 => Some(Self::F17),
2368 54 => Some(Self::F18),
2369 55 => Some(Self::F19),
2370 56 => Some(Self::F20),
2371 57 => Some(Self::F21),
2372 58 => Some(Self::F22),
2373 59 => Some(Self::F23),
2374 60 => Some(Self::F24),
2375 61 => Some(Self::Snapshot),
2376 62 => Some(Self::Scroll),
2377 63 => Some(Self::Pause),
2378 64 => Some(Self::Insert),
2379 65 => Some(Self::Home),
2380 66 => Some(Self::Delete),
2381 67 => Some(Self::End),
2382 68 => Some(Self::PageDown),
2383 69 => Some(Self::PageUp),
2384 70 => Some(Self::Left),
2385 71 => Some(Self::Up),
2386 72 => Some(Self::Right),
2387 73 => Some(Self::Down),
2388 74 => Some(Self::Back),
2389 75 => Some(Self::Return),
2390 76 => Some(Self::Space),
2391 77 => Some(Self::Compose),
2392 78 => Some(Self::Caret),
2393 79 => Some(Self::Numlock),
2394 80 => Some(Self::Numpad0),
2395 81 => Some(Self::Numpad1),
2396 82 => Some(Self::Numpad2),
2397 83 => Some(Self::Numpad3),
2398 84 => Some(Self::Numpad4),
2399 85 => Some(Self::Numpad5),
2400 86 => Some(Self::Numpad6),
2401 87 => Some(Self::Numpad7),
2402 88 => Some(Self::Numpad8),
2403 89 => Some(Self::Numpad9),
2404 90 => Some(Self::NumpadAdd),
2405 91 => Some(Self::NumpadDivide),
2406 92 => Some(Self::NumpadDecimal),
2407 93 => Some(Self::NumpadComma),
2408 94 => Some(Self::NumpadEnter),
2409 95 => Some(Self::NumpadEquals),
2410 96 => Some(Self::NumpadMultiply),
2411 97 => Some(Self::NumpadSubtract),
2412 98 => Some(Self::AbntC1),
2413 99 => Some(Self::AbntC2),
2414 100 => Some(Self::Apostrophe),
2415 101 => Some(Self::Apps),
2416 102 => Some(Self::Asterisk),
2417 103 => Some(Self::At),
2418 104 => Some(Self::Ax),
2419 105 => Some(Self::Backslash),
2420 106 => Some(Self::Calculator),
2421 107 => Some(Self::Capital),
2422 108 => Some(Self::Colon),
2423 109 => Some(Self::Comma),
2424 110 => Some(Self::Convert),
2425 111 => Some(Self::Equals),
2426 112 => Some(Self::Grave),
2427 113 => Some(Self::Kana),
2428 114 => Some(Self::Kanji),
2429 115 => Some(Self::LAlt),
2430 116 => Some(Self::LBracket),
2431 117 => Some(Self::LControl),
2432 118 => Some(Self::LShift),
2433 119 => Some(Self::LWin),
2434 120 => Some(Self::Mail),
2435 121 => Some(Self::MediaSelect),
2436 122 => Some(Self::MediaStop),
2437 123 => Some(Self::Minus),
2438 124 => Some(Self::Mute),
2439 125 => Some(Self::MyComputer),
2440 126 => Some(Self::NavigateForward),
2441 127 => Some(Self::NavigateBackward),
2442 128 => Some(Self::NextTrack),
2443 129 => Some(Self::NoConvert),
2444 130 => Some(Self::OEM102),
2445 131 => Some(Self::Period),
2446 132 => Some(Self::PlayPause),
2447 133 => Some(Self::Plus),
2448 134 => Some(Self::Power),
2449 135 => Some(Self::PrevTrack),
2450 136 => Some(Self::RAlt),
2451 137 => Some(Self::RBracket),
2452 138 => Some(Self::RControl),
2453 139 => Some(Self::RShift),
2454 140 => Some(Self::RWin),
2455 141 => Some(Self::Semicolon),
2456 142 => Some(Self::Slash),
2457 143 => Some(Self::Sleep),
2458 144 => Some(Self::Stop),
2459 145 => Some(Self::Sysrq),
2460 146 => Some(Self::Tab),
2461 147 => Some(Self::Underline),
2462 148 => Some(Self::Unlabeled),
2463 149 => Some(Self::VolumeDown),
2464 150 => Some(Self::VolumeUp),
2465 151 => Some(Self::Wake),
2466 152 => Some(Self::WebBack),
2467 153 => Some(Self::WebFavorites),
2468 154 => Some(Self::WebForward),
2469 155 => Some(Self::WebHome),
2470 156 => Some(Self::WebRefresh),
2471 157 => Some(Self::WebSearch),
2472 158 => Some(Self::WebStop),
2473 159 => Some(Self::Yen),
2474 160 => Some(Self::Copy),
2475 161 => Some(Self::Paste),
2476 162 => Some(Self::Cut),
2477 _ => None,
2478 }
2479 }
2480
2481 #[must_use]
2482 pub const fn get_lowercase(&self) -> Option<char> {
2483 use self::VirtualKeyCode::{
2484 Asterisk, At, Caret, Key0, Key1, Key2, Key3, Key4, Key5, Key6, Key7, Key8, Key9, Minus,
2485 Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8,
2486 Numpad9, Period, Semicolon, Slash, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
2487 R, S, T, U, V, W, X, Y, Z,
2488 };
2489 match self {
2490 A => Some('a'),
2491 B => Some('b'),
2492 C => Some('c'),
2493 D => Some('d'),
2494 E => Some('e'),
2495 F => Some('f'),
2496 G => Some('g'),
2497 H => Some('h'),
2498 I => Some('i'),
2499 J => Some('j'),
2500 K => Some('k'),
2501 L => Some('l'),
2502 M => Some('m'),
2503 N => Some('n'),
2504 O => Some('o'),
2505 P => Some('p'),
2506 Q => Some('q'),
2507 R => Some('r'),
2508 S => Some('s'),
2509 T => Some('t'),
2510 U => Some('u'),
2511 V => Some('v'),
2512 W => Some('w'),
2513 X => Some('x'),
2514 Y => Some('y'),
2515 Z => Some('z'),
2516 Key0 | Numpad0 => Some('0'),
2517 Key1 | Numpad1 => Some('1'),
2518 Key2 | Numpad2 => Some('2'),
2519 Key3 | Numpad3 => Some('3'),
2520 Key4 | Numpad4 => Some('4'),
2521 Key5 | Numpad5 => Some('5'),
2522 Key6 | Numpad6 => Some('6'),
2523 Key7 | Numpad7 => Some('7'),
2524 Key8 | Numpad8 => Some('8'),
2525 Key9 | Numpad9 => Some('9'),
2526 Minus => Some('-'),
2527 Asterisk => Some('*'),
2528 At => Some('@'),
2529 Period => Some('.'),
2530 Semicolon => Some(';'),
2531 Slash => Some('/'),
2532 Caret => Some('^'),
2533 _ => None,
2534 }
2535 }
2536}
2537
2538#[derive(Debug, Clone)]
2540#[repr(C)]
2541pub struct SmallWindowIconBytes {
2542 pub key: IconKey,
2543 pub rgba_bytes: U8Vec,
2544}
2545
2546#[derive(Debug, Clone)]
2548#[repr(C)]
2549pub struct LargeWindowIconBytes {
2550 pub key: IconKey,
2551 pub rgba_bytes: U8Vec,
2552}
2553
2554#[derive(Debug, Clone)]
2556#[repr(C, u8)]
2557pub enum WindowIcon {
2558 Small(SmallWindowIconBytes),
2559 Large(LargeWindowIconBytes),
2561}
2562
2563impl_option!(
2564 WindowIcon,
2565 OptionWindowIcon,
2566 copy = false,
2567 [Debug, Clone, PartialOrd, PartialEq, Eq, Hash, Ord]
2568);
2569
2570impl WindowIcon {
2571 #[must_use]
2572 pub const fn get_key(&self) -> IconKey {
2573 match &self {
2574 Self::Small(SmallWindowIconBytes { key, .. })
2575 | Self::Large(LargeWindowIconBytes { key, .. }) => *key,
2576 }
2577 }
2578}
2579impl PartialEq for WindowIcon {
2582 fn eq(&self, rhs: &Self) -> bool {
2583 self.get_key() == rhs.get_key()
2584 }
2585}
2586
2587impl PartialOrd for WindowIcon {
2588 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
2589 Some((self.get_key()).cmp(&rhs.get_key()))
2590 }
2591}
2592
2593impl Eq for WindowIcon {}
2594
2595impl Ord for WindowIcon {
2596 fn cmp(&self, rhs: &Self) -> Ordering {
2597 (self.get_key()).cmp(&rhs.get_key())
2598 }
2599}
2600
2601impl Hash for WindowIcon {
2602 fn hash<H>(&self, state: &mut H)
2603 where
2604 H: Hasher,
2605 {
2606 self.get_key().hash(state);
2607 }
2608}
2609
2610#[derive(Debug, Clone)]
2612#[repr(C)]
2613pub struct TaskBarIcon {
2614 pub key: IconKey,
2615 pub rgba_bytes: U8Vec,
2616}
2617
2618impl_option!(
2619 TaskBarIcon,
2620 OptionTaskBarIcon,
2621 copy = false,
2622 [Debug, Clone, PartialOrd, PartialEq, Eq, Hash, Ord]
2623);
2624
2625impl PartialEq for TaskBarIcon {
2626 fn eq(&self, rhs: &Self) -> bool {
2627 self.key == rhs.key
2628 }
2629}
2630
2631impl PartialOrd for TaskBarIcon {
2632 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
2633 Some((self.key).cmp(&rhs.key))
2634 }
2635}
2636
2637impl Eq for TaskBarIcon {}
2638
2639impl Ord for TaskBarIcon {
2640 fn cmp(&self, rhs: &Self) -> Ordering {
2641 (self.key).cmp(&rhs.key)
2642 }
2643}
2644
2645impl Hash for TaskBarIcon {
2646 fn hash<H>(&self, state: &mut H)
2647 where
2648 H: Hasher,
2649 {
2650 self.key.hash(state);
2651 }
2652}
2653
2654#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2661#[repr(C)]
2662pub enum SysDialogType {
2663 ReportProblem,
2667 UpdateVersion,
2672 TelemetryConsent,
2677 GpuCheck,
2681}
2682
2683#[cfg(test)]
2684#[path = "window_test.rs"]
2685mod window_test;