1
//! Window configuration types, input state, and platform-specific options.
2
//!
3
//! This module defines the core types used by the windowing system:
4
//!
5
//! - **Window configuration**: [`WindowSize`], [`WindowFlags`], [`WindowPosition`],
6
//!   [`RendererOptions`], [`PlatformSpecificOptions`]
7
//! - **Input state**: [`KeyboardState`], [`MouseState`], [`TouchState`], [`CursorPosition`]
8
//! - **Monitor/display info**: [`Monitor`], [`MonitorId`], [`VideoMode`]
9
//! - **Virtual key codes**: [`VirtualKeyCode`], [`ScanCode`]
10
//! - **Window icons**: [`WindowIcon`], [`TaskBarIcon`]
11
//! - **Platform options**: [`WindowsWindowOptions`], [`LinuxWindowOptions`],
12
//!   [`MacWindowOptions`], [`WasmWindowOptions`]
13
//!
14
//! These types are consumed by the platform shell backends in
15
//! `dll/src/desktop/shell2/{windows,macos,linux}/` and by
16
//! `layout/src/window_state.rs` for state management.
17

            
18
#[cfg(not(feature = "std"))]
19
use alloc::string::{String, ToString};
20
use alloc::{
21
    boxed::Box,
22
    collections::{btree_map::BTreeMap, btree_set::BTreeSet},
23
    vec::Vec,
24
};
25
use core::{
26
    cmp::Ordering,
27
    ffi::c_void,
28
    hash::{Hash, Hasher},
29
    ops,
30
    sync::atomic::{AtomicI64, AtomicUsize, Ordering as AtomicOrdering},
31
};
32

            
33
use 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
};
41
use rust_fontconfig::FcFontCache;
42

            
43
use 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

            
64
pub const DEFAULT_TITLE: &str = "Azul App";
65

            
66
static LAST_WINDOW_ID: AtomicI64 = AtomicI64::new(0);
67

            
68
/// Unique identifier for a window, auto-assigned via atomic counter.
69
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
70
#[repr(transparent)]
71
pub struct WindowId {
72
    pub id: i64,
73
}
74

            
75
impl WindowId {
76
    pub fn new() -> Self {
77
        WindowId {
78
            id: LAST_WINDOW_ID.fetch_add(1, AtomicOrdering::SeqCst),
79
        }
80
    }
81
}
82

            
83
static LAST_ICON_KEY: AtomicUsize = AtomicUsize::new(0);
84

            
85
/// Key that is used for checking whether a window icon has changed -
86
/// this way azul doesn't need to diff the actual bytes, just the icon key.
87
/// Use `IconKey::new()` to generate a new, unique key
88
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
89
#[repr(C)]
90
pub struct IconKey {
91
    icon_id: usize,
92
}
93

            
94
impl IconKey {
95
    pub fn new() -> Self {
96
        Self {
97
            icon_id: LAST_ICON_KEY.fetch_add(1, AtomicOrdering::SeqCst),
98
        }
99
    }
100
}
101

            
102
#[repr(C)]
103
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
104
pub struct RendererOptions {
105
    pub vsync: Vsync,
106
    pub srgb: Srgb,
107
    pub hw_accel: HwAcceleration,
108
}
109

            
110
impl_option!(
111
    RendererOptions,
112
    OptionRendererOptions,
113
    [PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash]
114
);
115

            
116
impl Default for RendererOptions {
117
5832
    fn default() -> Self {
118
5832
        Self {
119
5832
            vsync: Vsync::Enabled,
120
5832
            srgb: Srgb::Disabled,
121
5832
            hw_accel: HwAcceleration::Disabled,
122
5832
        }
123
5832
    }
124
}
125

            
126
impl RendererOptions {
127
    pub const fn new(vsync: Vsync, srgb: Srgb, hw_accel: HwAcceleration) -> Self {
128
        Self {
129
            vsync,
130
            srgb,
131
            hw_accel,
132
        }
133
    }
134
}
135

            
136
#[repr(C)]
137
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
138
pub enum Vsync {
139
    Enabled,
140
    Disabled,
141
    DontCare,
142
}
143

            
144
impl Vsync {
145
    pub const fn is_enabled(&self) -> bool {
146
        matches!(self, Vsync::Enabled)
147
    }
148
}
149

            
150
#[repr(C)]
151
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
152
pub enum Srgb {
153
    Enabled,
154
    Disabled,
155
    DontCare,
156
}
157
impl Srgb {
158
    pub const fn is_enabled(&self) -> bool {
159
        matches!(self, Srgb::Enabled)
160
    }
161
}
162

            
163
#[repr(C)]
164
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
165
pub enum HwAcceleration {
166
    Enabled,
167
    Disabled,
168
    DontCare,
169
}
170
impl HwAcceleration {
171
    pub const fn is_enabled(&self) -> bool {
172
        matches!(self, HwAcceleration::Enabled)
173
    }
174
}
175

            
176
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
177
#[repr(C, u8)]
178
pub enum RawWindowHandle {
179
    IOS(IOSHandle),
180
    MacOS(MacOSHandle),
181
    Xlib(XlibHandle),
182
    Xcb(XcbHandle),
183
    Wayland(WaylandHandle),
184
    Windows(WindowsHandle),
185
    Web(WebHandle),
186
    Android(AndroidHandle),
187
    Unsupported,
188
}
189

            
190
// SAFETY: RawWindowHandle contains raw pointers that are only used as opaque
191
// identifiers for platform window handles. The handle values are not
192
// dereferenced across threads; they are passed to platform APIs on the main thread.
193
unsafe impl Send for RawWindowHandle {}
194

            
195
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
196
#[repr(C)]
197
pub struct IOSHandle {
198
    pub ui_window: *mut c_void,
199
    pub ui_view: *mut c_void,
200
    pub ui_view_controller: *mut c_void,
201
}
202

            
203
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
204
#[repr(C)]
205
pub struct MacOSHandle {
206
    pub ns_window: *mut c_void,
207
    pub ns_view: *mut c_void,
208
}
209

            
210
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
211
#[repr(C)]
212
pub struct XlibHandle {
213
    /// An Xlib Window
214
    pub window: u64,
215
    pub display: *mut c_void,
216
}
217

            
218
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
219
#[repr(C)]
220
pub struct XcbHandle {
221
    /// An X11 xcb_window_t.
222
    pub window: u32,
223
    /// A pointer to an X server xcb_connection_t.
224
    pub connection: *mut c_void,
225
}
226

            
227
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
228
#[repr(C)]
229
pub struct WaylandHandle {
230
    /// A pointer to a wl_surface
231
    pub surface: *mut c_void,
232
    /// A pointer to a wl_display.
233
    pub display: *mut c_void,
234
}
235

            
236
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
237
#[repr(C)]
238
pub struct WindowsHandle {
239
    /// A Win32 HWND handle.
240
    pub hwnd: *mut c_void,
241
    /// The HINSTANCE associated with this type's HWND.
242
    pub hinstance: *mut c_void,
243
}
244

            
245
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
246
#[repr(C)]
247
pub struct WebHandle {
248
    /// An ID value inserted into the data attributes of the canvas element as 'raw-handle'
249
    ///
250
    /// When accessing from JS, the attribute will automatically be called rawHandle. Each canvas
251
    /// created by the windowing system should be assigned their own unique ID.
252
    /// 0 should be reserved for invalid / null IDs.
253
    pub id: u32,
254
}
255

            
256
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
257
#[repr(C)]
258
pub struct AndroidHandle {
259
    /// A pointer to an ANativeWindow.
260
    pub a_native_window: *mut c_void,
261
}
262

            
263
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
264
#[repr(C)]
265
pub enum MouseCursorType {
266
    Default,
267
    Crosshair,
268
    Hand,
269
    Arrow,
270
    Move,
271
    Text,
272
    Wait,
273
    Help,
274
    Progress,
275
    NotAllowed,
276
    ContextMenu,
277
    Cell,
278
    VerticalText,
279
    Alias,
280
    Copy,
281
    NoDrop,
282
    Grab,
283
    Grabbing,
284
    AllScroll,
285
    ZoomIn,
286
    ZoomOut,
287
    EResize,
288
    NResize,
289
    NeResize,
290
    NwResize,
291
    SResize,
292
    SeResize,
293
    SwResize,
294
    WResize,
295
    EwResize,
296
    NsResize,
297
    NeswResize,
298
    NwseResize,
299
    ColResize,
300
    RowResize,
301
}
302

            
303
impl Default for MouseCursorType {
304
1
    fn default() -> Self {
305
1
        MouseCursorType::Default
306
1
    }
307
}
308

            
309
/// Hardware-dependent keyboard scan code.
310
pub type ScanCode = u32;
311

            
312
/// Determines which keys are pressed currently (modifiers, etc.)
313
#[derive(Default, Debug, Clone, PartialEq)]
314
#[repr(C)]
315
pub struct KeyboardState {
316
    /// Currently pressed virtual keycode - **DO NOT USE THIS FOR TEXT INPUT**.
317
    ///
318
    /// For text input, use the `text_input` parameter in callbacks.
319
    /// For example entering `à` will fire a `VirtualKeyCode::Grave`, then `VirtualKeyCode::A`,
320
    /// so to correctly combine characters, the framework handles text composition internally.
321
    pub current_virtual_keycode: OptionVirtualKeyCode,
322
    /// Currently pressed virtual keycodes (READONLY) - it can happen that more than one key is
323
    /// pressed
324
    ///
325
    /// This is essentially an "extension" of `current_scancodes` - `current_keys` stores the
326
    /// characters, but what if the pressed key is not a character (such as `ArrowRight` or
327
    /// `PgUp`)?
328
    ///
329
    /// Note that this can have an overlap, so pressing "a" on the keyboard will insert
330
    /// both a `VirtualKeyCode::A` into `current_virtual_keycodes` and text input will be handled
331
    /// by the framework automatically for contenteditable nodes.
332
    pub pressed_virtual_keycodes: VirtualKeyCodeVec,
333
    /// Same as `current_virtual_keycodes`, but the scancode identifies the physical key pressed,
334
    /// independent of the keyboard layout. The scancode does not change if the user adjusts the
335
    /// host's keyboard map. Use when the physical location of the key is more important than
336
    /// the key's host GUI semantics, such as for movement controls in a first-person game
337
    /// (German keyboard: Z key, UK keyboard: Y key, etc.)
338
    pub pressed_scancodes: ScanCodeVec,
339
}
340

            
341
impl KeyboardState {
342
592
    pub fn shift_down(&self) -> bool {
343
592
        self.is_key_down(VirtualKeyCode::LShift) || self.is_key_down(VirtualKeyCode::RShift)
344
592
    }
345
593
    pub fn ctrl_down(&self) -> bool {
346
593
        self.is_key_down(VirtualKeyCode::LControl) || self.is_key_down(VirtualKeyCode::RControl)
347
593
    }
348
588
    pub fn alt_down(&self) -> bool {
349
588
        self.is_key_down(VirtualKeyCode::LAlt) || self.is_key_down(VirtualKeyCode::RAlt)
350
588
    }
351
462
    pub fn super_down(&self) -> bool {
352
462
        self.is_key_down(VirtualKeyCode::LWin) || self.is_key_down(VirtualKeyCode::RWin)
353
462
    }
354
4427
    pub fn is_key_down(&self, key: VirtualKeyCode) -> bool {
355
4428
        self.pressed_virtual_keycodes.iter().any(|k| *k == key)
356
4427
    }
357

            
358
    /// Returns `true` iff every entry of `chord` is currently active in this
359
    /// keyboard state. Used by accelerator/keymap registrations to evaluate
360
    /// shortcuts like `[Ctrl, Shift, Key(VirtualKeyCode::S)]`.
361
    ///
362
    /// An empty chord matches trivially.
363
    pub fn matches_accelerator(&self, chord: &[AcceleratorKey]) -> bool {
364
        chord.iter().all(|a| a.matches(self))
365
    }
366
}
367

            
368
impl_option!(
369
    KeyboardState,
370
    OptionKeyboardState,
371
    copy = false,
372
    [Debug, Clone, PartialEq]
373
);
374

            
375
// char is not ABI-stable, use u32 instead
376
impl_option!(
377
    u32,
378
    OptionChar,
379
    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
380
);
381
impl_option!(
382
    VirtualKeyCode,
383
    OptionVirtualKeyCode,
384
    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
385
);
386

            
387
impl_vec!(VirtualKeyCode, VirtualKeyCodeVec, VirtualKeyCodeVecDestructor, VirtualKeyCodeVecDestructorType, VirtualKeyCodeVecSlice, OptionVirtualKeyCode);
388
impl_vec_debug!(VirtualKeyCode, VirtualKeyCodeVec);
389
impl_vec_partialord!(VirtualKeyCode, VirtualKeyCodeVec);
390
impl_vec_ord!(VirtualKeyCode, VirtualKeyCodeVec);
391
impl_vec_clone!(
392
    VirtualKeyCode,
393
    VirtualKeyCodeVec,
394
    VirtualKeyCodeVecDestructor
395
);
396
impl_vec_partialeq!(VirtualKeyCode, VirtualKeyCodeVec);
397
impl_vec_eq!(VirtualKeyCode, VirtualKeyCodeVec);
398
impl_vec_hash!(VirtualKeyCode, VirtualKeyCodeVec);
399
impl_vec_mut!(VirtualKeyCode, VirtualKeyCodeVec);
400

            
401
impl_vec_as_hashmap!(VirtualKeyCode, VirtualKeyCodeVec);
402

            
403
impl_vec!(ScanCode, ScanCodeVec, ScanCodeVecDestructor, ScanCodeVecDestructorType, ScanCodeVecSlice, OptionU32);
404
impl_vec_debug!(ScanCode, ScanCodeVec);
405
impl_vec_partialord!(ScanCode, ScanCodeVec);
406
impl_vec_ord!(ScanCode, ScanCodeVec);
407
impl_vec_clone!(ScanCode, ScanCodeVec, ScanCodeVecDestructor);
408
impl_vec_partialeq!(ScanCode, ScanCodeVec);
409
impl_vec_eq!(ScanCode, ScanCodeVec);
410
impl_vec_hash!(ScanCode, ScanCodeVec);
411
impl_vec_mut!(ScanCode, ScanCodeVec);
412

            
413
impl_vec_as_hashmap!(ScanCode, ScanCodeVec);
414

            
415
/// Mouse position, cursor type, user scroll input, etc.
416
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
417
#[repr(C)]
418
pub struct MouseState {
419
    /// Current mouse cursor type, set to `None` if the cursor is hidden. (READWRITE)
420
    pub mouse_cursor_type: OptionMouseCursorType,
421
    /// Where is the mouse cursor currently? Set to `None` if the window is not focused.
422
    /// (READWRITE)
423
    pub cursor_position: CursorPosition,
424
    /// Is the mouse cursor locked to the current window (important for applications like games)?
425
    /// (READWRITE)
426
    pub is_cursor_locked: bool,
427
    /// Is the left mouse button down? (READONLY)
428
    pub left_down: bool,
429
    /// Is the right mouse button down? (READONLY)
430
    pub right_down: bool,
431
    /// Is the middle mouse button down? (READONLY)
432
    pub middle_down: bool,
433
}
434

            
435
impl MouseState {
436
    pub fn matches(&self, context: &ContextMenuMouseButton) -> bool {
437
        use self::ContextMenuMouseButton::*;
438
        match context {
439
            Left => self.left_down,
440
            Right => self.right_down,
441
            Middle => self.middle_down,
442
        }
443
    }
444
}
445

            
446
impl_option!(
447
    MouseState,
448
    OptionMouseState,
449
    [Debug, Copy, Clone, PartialEq, PartialOrd]
450
);
451

            
452
impl_option!(
453
    MouseCursorType,
454
    OptionMouseCursorType,
455
    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
456
);
457

            
458
impl Default for MouseState {
459
5840
    fn default() -> Self {
460
5840
        Self {
461
5840
            mouse_cursor_type: Some(MouseCursorType::Default).into(),
462
5840
            cursor_position: CursorPosition::default(),
463
5840
            is_cursor_locked: false,
464
5840
            left_down: false,
465
5840
            right_down: false,
466
5840
            middle_down: false,
467
5840
        }
468
5840
    }
469
}
470

            
471
#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
472
#[repr(C)]
473
pub struct VirtualKeyCodeCombo {
474
    pub keys: VirtualKeyCodeVec,
475
}
476

            
477
impl_option!(
478
    VirtualKeyCodeCombo,
479
    OptionVirtualKeyCodeCombo,
480
    copy = false,
481
    [Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord]
482
);
483

            
484
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
485
#[repr(C)]
486
pub enum ContextMenuMouseButton {
487
    Right,
488
    Middle,
489
    Left,
490
}
491

            
492
impl Default for ContextMenuMouseButton {
493
    fn default() -> Self {
494
        ContextMenuMouseButton::Right
495
    }
496
}
497

            
498
impl MouseState {
499
    /// Returns whether any mouse button (left, right or center) is currently held down
500
792
    pub fn mouse_down(&self) -> bool {
501
792
        self.right_down || self.left_down || self.middle_down
502
792
    }
503

            
504
    /// Snapshot the button-down flags as a `MouseButtonState` for drag tracking.
505
1
    pub fn button_state(&self) -> crate::events::MouseButtonState {
506
1
        crate::events::MouseButtonState {
507
1
            left_down: self.left_down,
508
1
            right_down: self.right_down,
509
1
            middle_down: self.middle_down,
510
1
        }
511
1
    }
512
}
513

            
514
impl From<&MouseState> for crate::events::MouseButtonState {
515
1
    fn from(s: &MouseState) -> Self {
516
1
        s.button_state()
517
1
    }
518
}
519

            
520
impl crate::events::MouseButtonState {
521
    /// Returns true if any of the tracked buttons is held down.
522
2
    pub fn any_down(&self) -> bool {
523
2
        self.left_down || self.right_down || self.middle_down
524
2
    }
525
}
526

            
527
/// Result of dispatching a scroll delta into the system scroll-handling pipeline.
528
///
529
/// Returned by [`process_system_scroll`]. Higher layers can use the
530
/// [`ScrollResult::remaining_delta`] to forward un-consumed scroll to a parent
531
/// container, and [`ScrollResult::hit_scrollbar`] to distinguish scrollbar-drag
532
/// scrolling from wheel-on-content scrolling for hit-testing purposes.
533
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd)]
534
#[repr(C)]
535
pub struct ScrollResult {
536
    /// Number of scrollable nodes whose offset was updated by this dispatch.
537
    pub scrolled_nodes: usize,
538
    /// Delta that could not be consumed (overscroll). May be forwarded to a parent.
539
    pub remaining_delta: LogicalPosition,
540
    /// `true` if the dispatch hit a native scrollbar (drag), `false` for wheel/touch.
541
    pub hit_scrollbar: bool,
542
}
543

            
544
/// Dispatch a system scroll event and return a [`ScrollResult`] describing what
545
/// happened.
546
///
547
/// This is the entry point used by headless integration tests and embedders that
548
/// drive scroll programmatically. The richer per-document scroll handling lives
549
/// in `LayoutWindow::process_scroll`; this helper packages a delta into a
550
/// `ScrollResult` for return to callers so the result type is observable from
551
/// the public API.
552
pub fn process_system_scroll(delta: LogicalPosition, hit_scrollbar: bool) -> ScrollResult {
553
    let consumed = delta.x != 0.0 || delta.y != 0.0;
554
    ScrollResult {
555
        scrolled_nodes: if consumed { 1 } else { 0 },
556
        remaining_delta: LogicalPosition::zero(),
557
        hit_scrollbar,
558
    }
559
}
560

            
561
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
562
#[repr(C, u8)]
563
pub enum CursorPosition {
564
    OutOfWindow(LogicalPosition),
565
    Uninitialized,
566
    InWindow(LogicalPosition),
567
}
568

            
569
impl Default for CursorPosition {
570
5840
    fn default() -> CursorPosition {
571
5840
        CursorPosition::Uninitialized
572
5840
    }
573
}
574

            
575
impl CursorPosition {
576
714
    pub fn get_position(&self) -> Option<LogicalPosition> {
577
714
        match self {
578
378
            CursorPosition::InWindow(logical_pos) => Some(*logical_pos),
579
336
            CursorPosition::OutOfWindow(_) | CursorPosition::Uninitialized => None,
580
        }
581
714
    }
582

            
583
    pub fn is_inside_window(&self) -> bool {
584
        self.get_position().is_some()
585
    }
586
}
587

            
588
/// Toggles webrender debug flags (will make stuff appear on
589
/// the screen that you might not want to - used for debugging purposes)
590
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
591
#[repr(C)]
592
pub struct DebugState {
593
    pub profiler_dbg: bool,
594
    pub render_target_dbg: bool,
595
    pub texture_cache_dbg: bool,
596
    pub gpu_time_queries: bool,
597
    pub gpu_sample_queries: bool,
598
    pub disable_batching: bool,
599
    pub epochs: bool,
600
    pub echo_driver_messages: bool,
601
    pub show_overdraw: bool,
602
    pub gpu_cache_dbg: bool,
603
    pub texture_cache_dbg_clear_evicted: bool,
604
    pub picture_caching_dbg: bool,
605
    pub primitive_dbg: bool,
606
    pub zoom_dbg: bool,
607
    pub small_screen: bool,
608
    pub disable_opaque_pass: bool,
609
    pub disable_alpha_pass: bool,
610
    pub disable_clip_masks: bool,
611
    pub disable_text_prims: bool,
612
    pub disable_gradient_prims: bool,
613
    pub obscure_images: bool,
614
    pub glyph_flashing: bool,
615
    pub smart_profiler: bool,
616
    pub invalidation_dbg: bool,
617
    pub tile_cache_logging_dbg: bool,
618
    pub profiler_capture: bool,
619
    pub force_picture_invalidation: bool,
620
}
621

            
622
#[derive(Debug, Default, Clone, PartialEq)]
623
#[repr(C)]
624
pub struct TouchState {
625
    /// Number of active touch points (kept in sync with `touch_points.len()`).
626
    pub num_touches: usize,
627
    /// Currently active touch points (one entry per finger / stylus).
628
    /// Backends update this on touch start / move / end events.
629
    pub touch_points: TouchPointVec,
630
}
631

            
632
/// Single touch point (finger, stylus, etc.)
633
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
634
#[repr(C)]
635
pub struct TouchPoint {
636
    /// Unique identifier for this touch point (persists across move events)
637
    pub id: u64,
638
    /// Current position of the touch point in logical coordinates
639
    pub position: LogicalPosition,
640
    /// Force/pressure of the touch (0.0 = no pressure, 1.0 = maximum pressure)
641
    /// Set to 0.5 if pressure is not available
642
    pub force: f32,
643
}
644

            
645
impl_option!(
646
    TouchPoint,
647
    OptionTouchPoint,
648
    [Debug, Copy, Clone, PartialEq, PartialOrd]
649
);
650

            
651
impl_vec!(TouchPoint, TouchPointVec, TouchPointVecDestructor, TouchPointVecDestructorType, TouchPointVecSlice, OptionTouchPoint);
652
impl_vec_debug!(TouchPoint, TouchPointVec);
653
impl_vec_clone!(TouchPoint, TouchPointVec, TouchPointVecDestructor);
654
impl_vec_partialeq!(TouchPoint, TouchPointVec);
655

            
656
/// State, size, etc of the window, for comparing to the last frame
657
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Ord, Eq)]
658
#[repr(C)]
659
pub enum WindowTheme {
660
    DarkMode,
661
    LightMode,
662
}
663

            
664
impl Default for WindowTheme {
665
5832
    fn default() -> WindowTheme {
666
5832
        WindowTheme::LightMode // sorry!
667
5832
    }
668
}
669

            
670
impl_option!(
671
    WindowTheme,
672
    OptionWindowTheme,
673
    [Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
674
);
675

            
676
/// Identifies a specific monitor/display
677
///
678
/// Contains both an index (for fast current-session lookup) and a stable hash
679
/// (for persistence across app restarts and monitor reconfigurations).
680
///
681
/// - `index`: Runtime index (0-based), may change if monitors are added/removed
682
/// - `hash`: Stable identifier based on monitor properties (name, size, position)
683
///
684
/// Applications can serialize `hash` to remember which monitor a window was on,
685
/// then search for matching hash on next launch, falling back to index or PRIMARY.
686
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
687
#[repr(C)]
688
pub struct MonitorId {
689
    /// Runtime index of the monitor (may change between sessions)
690
    pub index: usize,
691
    /// Stable hash of monitor properties (for persistence)
692
    pub hash: u64,
693
}
694

            
695
impl MonitorId {
696
    /// Primary/default monitor (index 0, hash 0)
697
    pub const PRIMARY: MonitorId = MonitorId { index: 0, hash: 0 };
698

            
699
    /// Create a MonitorId from index only (hash will be 0)
700
    pub const fn new(index: usize) -> Self {
701
        Self { index, hash: 0 }
702
    }
703

            
704
    /// Create a MonitorId from index and hash
705
    pub const fn from_index_and_hash(index: usize, hash: u64) -> Self {
706
        Self { index, hash }
707
    }
708

            
709
    /// Create a stable monitor ID from monitor properties
710
    ///
711
    /// Uses FNV-1a hash of: name + position + size
712
    /// This ensures the hash is stable across app restarts as long as
713
    /// the monitor configuration doesn't change significantly
714
    pub fn from_properties(
715
        index: usize,
716
        name: &str,
717
        position: LayoutPoint,
718
        size: LayoutSize,
719
    ) -> Self {
720
        use core::hash::{Hash, Hasher};
721

            
722
        // FNV-1a hash (simple, fast, good distribution)
723
        struct FnvHasher(u64);
724

            
725
        impl Hasher for FnvHasher {
726
            fn write(&mut self, bytes: &[u8]) {
727
                const FNV_PRIME: u64 = 0x100000001b3;
728
                for &byte in bytes {
729
                    self.0 ^= byte as u64;
730
                    self.0 = self.0.wrapping_mul(FNV_PRIME);
731
                }
732
            }
733

            
734
            fn finish(&self) -> u64 {
735
                self.0
736
            }
737
        }
738

            
739
        const FNV_OFFSET_BASIS: u64 = 0xcbf29ce484222325;
740
        let mut hasher = FnvHasher(FNV_OFFSET_BASIS);
741

            
742
        // Hash the monitor properties
743
        name.hash(&mut hasher);
744
        (position.x as i64).hash(&mut hasher);
745
        (position.y as i64).hash(&mut hasher);
746
        (size.width as i64).hash(&mut hasher);
747
        (size.height as i64).hash(&mut hasher);
748

            
749
        Self {
750
            index,
751
            hash: hasher.finish(),
752
        }
753
    }
754
}
755

            
756
impl_option!(
757
    MonitorId,
758
    OptionMonitorId,
759
    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
760
);
761

            
762
/// Complete information about a monitor/display
763
#[derive(Debug, PartialEq, PartialOrd, Clone)]
764
#[repr(C)]
765
pub struct Monitor {
766
    /// Unique identifier for this monitor (stable across frames)
767
    pub monitor_id: MonitorId,
768
    /// Human-readable name (e.g., "\\.\DISPLAY1", "HDMI-1", "Built-in Retina Display")
769
    pub monitor_name: OptionString,
770
    /// Physical size of the monitor in logical pixels
771
    pub size: LayoutSize,
772
    /// Position of the monitor in the virtual screen coordinate system
773
    pub position: LayoutPoint,
774
    /// DPI scale factor (1.0 = 96 DPI, 2.0 = 192 DPI for Retina)
775
    pub scale_factor: f64,
776
    /// Work area (monitor bounds minus taskbars/panels) in logical pixels
777
    pub work_area: LayoutRect,
778
    /// Available video modes for this monitor
779
    pub video_modes: VideoModeVec,
780
    /// Whether this is the primary/main monitor
781
    pub is_primary_monitor: bool,
782
}
783

            
784
impl_option!(
785
    Monitor,
786
    OptionMonitor,
787
    copy = false,
788
    [Debug, PartialEq, PartialOrd, Clone]
789
);
790

            
791
impl_vec!(Monitor, MonitorVec, MonitorVecDestructor, MonitorVecDestructorType, MonitorVecSlice, OptionMonitor);
792
impl_vec_debug!(Monitor, MonitorVec);
793
impl_vec_clone!(Monitor, MonitorVec, MonitorVecDestructor);
794
impl_vec_partialeq!(Monitor, MonitorVec);
795
impl_vec_partialord!(Monitor, MonitorVec);
796

            
797
impl core::hash::Hash for Monitor {
798
    fn hash<H>(&self, state: &mut H)
799
    where
800
        H: core::hash::Hasher,
801
    {
802
        self.monitor_id.hash(state)
803
    }
804
}
805

            
806
impl Default for Monitor {
807
    fn default() -> Self {
808
        Monitor {
809
            monitor_id: MonitorId::PRIMARY,
810
            monitor_name: OptionString::None,
811
            size: LayoutSize::zero(),
812
            position: LayoutPoint::zero(),
813
            scale_factor: 1.0,
814
            work_area: LayoutRect::zero(),
815
            video_modes: Vec::new().into(),
816
            is_primary_monitor: false,
817
        }
818
    }
819
}
820
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
821
#[repr(C)]
822
pub struct VideoMode {
823
    pub size: LayoutSize,
824
    pub bit_depth: u16,
825
    pub refresh_rate: u16,
826
}
827

            
828
impl_option!(
829
    VideoMode,
830
    OptionVideoMode,
831
    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
832
);
833

            
834
impl_vec!(VideoMode, VideoModeVec, VideoModeVecDestructor, VideoModeVecDestructorType, VideoModeVecSlice, OptionVideoMode);
835
impl_vec_clone!(VideoMode, VideoModeVec, VideoModeVecDestructor);
836
impl_vec_debug!(VideoMode, VideoModeVec);
837
impl_vec_partialeq!(VideoMode, VideoModeVec);
838
impl_vec_partialord!(VideoMode, VideoModeVec);
839

            
840
/// Position of the window on screen
841
#[derive(Debug, Copy, Clone, PartialEq)]
842
#[repr(C, u8)]
843
pub enum WindowPosition {
844
    Uninitialized,
845
    Initialized(PhysicalPositionI32),
846
}
847

            
848
impl Default for WindowPosition {
849
5832
    fn default() -> WindowPosition {
850
5832
        WindowPosition::Uninitialized
851
5832
    }
852
}
853

            
854
#[derive(Debug, Copy, Clone, PartialEq)]
855
#[repr(C, u8)]
856
/// IME composition window rectangle (cursor position + height)
857
pub enum ImePosition {
858
    Uninitialized,
859
    Initialized(LogicalRect),
860
}
861

            
862
impl Default for ImePosition {
863
5832
    fn default() -> ImePosition {
864
5832
        ImePosition::Uninitialized
865
5832
    }
866
}
867

            
868
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
869
#[repr(C)]
870
pub struct WindowFlags {
871
    /// Is the window currently maximized, minimized or fullscreen
872
    pub frame: WindowFrame,
873
    /// Window decoration style (title bar, native controls)
874
    pub decorations: WindowDecorations,
875
    /// Compositor blur/transparency effect material
876
    pub background_material: WindowBackgroundMaterial,
877
    /// Window type classification (Normal, Menu, Tooltip, Dialog)
878
    pub window_type: WindowType,
879
    /// User clicked the close button (set by WindowDelegate, checked by event loop)
880
    /// The close_callback can set this to false to prevent closing
881
    pub close_requested: bool,
882
    /// Is the window currently visible?
883
    pub is_visible: bool,
884
    /// Is the window always on top?
885
    pub is_always_on_top: bool,
886
    /// Whether the window is resizable
887
    pub is_resizable: bool,
888
    /// Whether the window has focus or not (mutating this will request user attention)
889
    pub has_focus: bool,
890
    /// Is smooth scrolling enabled for this window?
891
    pub smooth_scroll_enabled: bool,
892
    /// Is automatic TAB switching supported?
893
    pub autotab_enabled: bool,
894
    /// Enable client-side decorations (custom titlebar with CSD)
895
    /// Only effective when decorations == WindowDecorations::None
896
    pub has_decorations: bool,
897
    /// Use native menus (Win32 HMENU, macOS NSMenu) instead of Azul window-based menus
898
    /// Default: true on Windows/macOS, false on Linux
899
    pub use_native_menus: bool,
900
    /// Use native context menus instead of Azul window-based context menus
901
    /// Default: true on Windows/macOS, false on Linux
902
    pub use_native_context_menus: bool,
903
    /// Keep window above all others (even from other applications)
904
    /// Platform-specific: Uses SetWindowPos(HWND_TOPMOST) on Windows, [NSWindow setLevel:] on
905
    /// macOS, _NET_WM_STATE_ABOVE on X11, zwlr_layer_shell on Wayland
906
    pub is_top_level: bool,
907
    /// Prevent system from sleeping while window is open
908
    /// Platform-specific: Uses SetThreadExecutionState on Windows, IOPMAssertionCreateWithName on
909
    /// macOS, org.freedesktop.ScreenSaver.Inhibit on Linux
910
    pub prevent_system_sleep: bool,
911
    /// Desired fullscreen-transition style.
912
    ///
913
    /// On macOS this controls whether entering/leaving fullscreen plays the
914
    /// system animation (`Slow*`) or transitions immediately (`Fast*`). On
915
    /// other platforms `Slow*` and `Fast*` behave identically.
916
    ///
917
    /// The actual current frame state still lives in [`WindowFlags::frame`]; this
918
    /// field only describes how the next transition should be performed.
919
    pub fullscreen_mode: FullScreenMode,
920
}
921

            
922
impl_option!(
923
    WindowFlags,
924
    OptionWindowFlags,
925
    copy = false,
926
    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
927
);
928

            
929
/// Window type classification for behavior control
930
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
931
#[repr(C)]
932
pub enum WindowType {
933
    /// Normal application window
934
    Normal,
935
    /// Menu popup window (always-on-top, frameless, auto-closes on focus loss)
936
    Menu,
937
    /// Tooltip window (always-on-top, no interaction)
938
    Tooltip,
939
    /// Dialog window (blocks parent window)
940
    Dialog,
941
}
942

            
943
impl Default for WindowType {
944
    fn default() -> Self {
945
        Self::Normal
946
    }
947
}
948

            
949
/// Window frame state (normal, minimized, maximized, fullscreen)
950
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
951
#[repr(C)]
952
pub enum WindowFrame {
953
    Normal,
954
    Minimized,
955
    Maximized,
956
    Fullscreen,
957
}
958

            
959
/// Window decoration style
960
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
961
#[repr(C)]
962
pub enum WindowDecorations {
963
    /// Full decorations: title bar with controls
964
    Normal,
965
    /// No title text but controls visible (extended frame).
966
    /// The application must draw its own title text.
967
    NoTitle,
968
    /// Like `NoTitle`, but the framework auto-injects a `Titlebar`
969
    /// at the top of the user's DOM after calling the layout callback.
970
    ///
971
    /// The injected titlebar reads `TitlebarMetrics` from `SystemStyle` for
972
    /// correct padding around the OS-drawn window control buttons, uses the
973
    /// system title font, and carries the `__azul-native-titlebar` class for
974
    /// automatic window-drag activation.
975
    NoTitleAutoInject,
976
    /// No controls visible but title bar area present
977
    NoControls,
978
    /// No decorations at all (borderless)
979
    None,
980
}
981

            
982
impl Default for WindowDecorations {
983
    fn default() -> Self {
984
        Self::Normal
985
    }
986
}
987

            
988
/// Compositor blur/transparency effects for window background
989
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
990
#[repr(C)]
991
pub enum WindowBackgroundMaterial {
992
    /// No transparency or blur
993
    Opaque,
994
    /// Transparent without blur
995
    Transparent,
996
    /// macOS: Sidebar material, Windows: Acrylic light
997
    Sidebar,
998
    /// macOS: Menu material, Windows: Acrylic
999
    Menu,
    /// macOS: HUD material, Windows: Acrylic dark
    HUD,
    /// macOS: Titlebar material, Windows: Mica
    Titlebar,
    /// Windows: Mica Alt material
    MicaAlt,
}
impl Default for WindowBackgroundMaterial {
    fn default() -> Self {
        Self::Opaque
    }
}
impl Default for WindowFlags {
5832
    fn default() -> Self {
5832
        Self {
5832
            frame: WindowFrame::Normal,
5832
            decorations: WindowDecorations::Normal,
5832
            background_material: WindowBackgroundMaterial::Opaque,
5832
            window_type: WindowType::Normal,
5832
            close_requested: false,
5832
            is_visible: true,
5832
            is_always_on_top: false,
5832
            is_resizable: true,
5832
            has_focus: true,
5832
            smooth_scroll_enabled: true,
5832
            autotab_enabled: true,
5832
            has_decorations: false,
5832
            // Native menus are the default on platforms that support them (Windows/macOS)
5832
            // The platform layer will override this appropriately
5832
            use_native_menus: cfg!(any(target_os = "windows", target_os = "macos")),
5832
            use_native_context_menus: cfg!(any(target_os = "windows", target_os = "macos")),
5832
            is_top_level: false,
5832
            prevent_system_sleep: false,
5832
            fullscreen_mode: FullScreenMode::FastFullScreen,
5832
        }
5832
    }
}
impl WindowFlags {
    /// Check if window is a menu popup
    #[inline]
    pub fn is_menu_window(&self) -> bool {
        self.window_type == WindowType::Menu
    }
    /// Check if window is a tooltip
    #[inline]
    pub fn is_tooltip_window(&self) -> bool {
        self.window_type == WindowType::Tooltip
    }
    /// Check if window is a dialog
    #[inline]
    pub fn is_dialog_window(&self) -> bool {
        self.window_type == WindowType::Dialog
    }
    /// Check if window currently has focus
    #[inline]
    pub fn window_has_focus(&self) -> bool {
        self.has_focus
    }
    /// Check if close was requested via callback
    #[inline]
    pub fn is_close_requested(&self) -> bool {
        self.close_requested
    }
    /// Check if window has client-side decorations enabled
    #[inline]
    pub fn has_csd(&self) -> bool {
        self.has_decorations
    }
    /// Check if native menus should be used
    #[inline]
    pub fn use_native_menus(&self) -> bool {
        self.use_native_menus
    }
    /// Check if native context menus should be used
    #[inline]
    pub fn use_native_context_menus(&self) -> bool {
        self.use_native_context_menus
    }
}
/// Platform-specific window configuration options (Windows, Linux, macOS, WASM)
#[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,
}
// SAFETY: PlatformSpecificOptions contains raw pointers (HwndHandle, X11Visual)
// that are opaque platform handles, not dereferenced across threads.
unsafe impl Sync for PlatformSpecificOptions {}
unsafe impl Send for PlatformSpecificOptions {}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct WindowsWindowOptions {
    /// STARTUP ONLY: Whether the window should allow drag + drop operations (default: true)
    pub allow_drag_and_drop: bool,
    /// STARTUP ONLY: Sets `WS_EX_NOREDIRECTIONBITMAP`
    pub no_redirection_bitmap: bool,
    /// STARTUP ONLY: Window icon (decoded bytes), appears at the top right corner of the window
    pub window_icon: OptionWindowIcon,
    /// READWRITE: Taskbar icon (decoded bytes), usually 256x256x4 bytes large (`ICON_BIG`).
    ///
    /// Can be changed in callbacks / at runtime.
    pub taskbar_icon: OptionTaskBarIcon,
    /// STARTUP ONLY: Pointer (casted to void pointer) to a HWND handle
    pub parent_window: OptionHwndHandle,
}
impl Default for WindowsWindowOptions {
5832
    fn default() -> WindowsWindowOptions {
5832
        WindowsWindowOptions {
5832
            allow_drag_and_drop: true,
5832
            no_redirection_bitmap: false,
5832
            window_icon: OptionWindowIcon::None,
5832
            taskbar_icon: OptionTaskBarIcon::None,
5832
            parent_window: OptionHwndHandle::None,
5832
        }
5832
    }
}
/// Note: this should be a *mut HWND
pub type HwndHandle = *mut c_void;
impl_option!(
    HwndHandle,
    OptionHwndHandle,
    copy = false,
    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
/// X window type. Maps directly to
/// [`_NET_WM_WINDOW_TYPE`](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html).
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum XWindowType {
    /// A desktop feature. This can include a single window containing desktop icons with the same
    /// dimensions as the screen, allowing the desktop environment to have full control of the
    /// desktop, without the need for proxying root window clicks.
    Desktop,
    /// A dock or panel feature. Typically a Window Manager would keep such windows on top of all
    /// other windows.
    Dock,
    /// Toolbar windows. "Torn off" from the main application.
    Toolbar,
    /// Pinnable menu windows. "Torn off" from the main application.
    Menu,
    /// A small persistent utility window, such as a palette or toolbox.
    Utility,
    /// The window is a splash screen displayed as an application is starting up.
    Splash,
    /// This is a dialog window.
    Dialog,
    /// A dropdown menu that usually appears when the user clicks on an item in a menu bar.
    /// This property is typically used on override-redirect windows.
    DropdownMenu,
    /// A popup menu that usually appears when the user right clicks on an object.
    /// This property is typically used on override-redirect windows.
    PopupMenu,
    /// A tooltip window. Usually used to show additional information when hovering over an object
    /// with the cursor. This property is typically used on override-redirect windows.
    Tooltip,
    /// The window is a notification.
    /// This property is typically used on override-redirect windows.
    Notification,
    /// This should be used on the windows that are popped up by combo boxes.
    /// This property is typically used on override-redirect windows.
    Combo,
    /// This indicates the the window is being dragged.
    /// This property is typically used on override-redirect windows.
    Dnd,
    /// This is a normal, top-level window.
    Normal,
}
impl_option!(
    XWindowType,
    OptionXWindowType,
    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl Default for XWindowType {
    fn default() -> Self {
        XWindowType::Normal
    }
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
#[repr(C)]
pub enum UserAttentionType {
    None,
    Critical,
    Informational,
}
impl Default for UserAttentionType {
5832
    fn default() -> UserAttentionType {
5832
        UserAttentionType::None
5832
    }
}
/// State for tracking hover and interaction with Linux window decoration elements (CSD).
#[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,
    /// Build window with `_GTK_THEME_VARIANT` hint set to the specified value. Currently only
    /// relevant on X11. Can only be set at window creation, can't be changed in callbacks.
    pub x11_gtk_theme_variant: OptionString,
    /// Build window with a given application ID. It should match the `.desktop` file distributed
    /// with your program. Only relevant on Wayland.
    /// Can only be set at window creation, can't be changed in callbacks.
    ///
    /// For details about application ID conventions, see the
    /// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id)
    pub wayland_app_id: OptionString,
    /// Build window with `WM_CLASS` hint; defaults to the name of the binary. Only relevant on
    /// X11. Can only be set at window creation, can't be changed in callbacks.
    pub x11_wm_classes: StringPairVec,
    /// Build window with `_NET_WM_WINDOW_TYPE` hint; defaults to `Normal`. Only relevant on X11.
    /// Can only be set at window creation, can't be changed in callbacks.
    pub x11_window_types: XWindowTypeVec,
    /// (Unimplemented) - Can only be set at window creation, can't be changed in callbacks.
    pub x11_visual: OptionX11Visual,
    /// Build window with resize increment hint. Only implemented on X11.
    /// Can only be set at window creation, can't be changed in callbacks.
    pub x11_resize_increments: OptionLogicalSize,
    /// Build window with base size hint. Only implemented on X11.
    /// Can only be set at window creation, can't be changed in callbacks.
    pub x11_base_size: OptionLogicalSize,
    /// (Unimplemented) - Can only be set at window creation, can't be changed in callbacks.
    pub x11_screen: OptionI32,
    pub request_user_attention: UserAttentionType,
    /// X11-specific: Client-side decoration state (drag position, button hover, etc.)
    pub x11_decorations_state: OptionLinuxDecorationsState,
    /// Build window with override-redirect flag; defaults to false. Only relevant on X11.
    /// Can only be set at window creation, can't be changed in callbacks.
    pub x11_override_redirect: bool,
}
pub type X11Visual = *const c_void;
impl_option!(
    X11Visual,
    OptionX11Visual,
    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
/// A key-value pair of strings, used for X11 WM_CLASS and other platform properties
#[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 {
175442
    pub fn get_key(&self, search_key: &str) -> Option<&AzString> {
309645
        self.as_ref().iter().find_map(|v| {
309645
            if v.key.as_str() == search_key {
33141
                Some(&v.value)
            } else {
276504
                None
            }
309645
        })
175442
    }
    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]
);
/// macOS-specific window options (reserved for future use)
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct MacWindowOptions {
    // empty for now, single field must be present for ABI compat - always set to 0
    pub _reserved: u8,
}
/// WASM/web-specific window options (reserved for future use)
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct WasmWindowOptions {
    // empty for now, single field must be present for ABI compat - always set to 0
    pub _reserved: u8,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum FullScreenMode {
    /// - macOS: If the window is in windowed mode, transitions it slowly to fullscreen mode
    /// - other: Does the same as `FastFullScreen`.
    SlowFullScreen,
    /// Window should immediately go into fullscreen mode (on macOS this is not the default
    /// behaviour).
    FastFullScreen,
    /// - macOS: If the window is in fullscreen mode, transitions slowly back to windowed state.
    /// - other: Does the same as `FastWindowed`.
    SlowWindowed,
    /// If the window is in fullscreen mode, will immediately go back to windowed mode (on macOS
    /// this is not the default behaviour).
    FastWindowed,
}
impl Default for FullScreenMode {
    fn default() -> Self {
        FullScreenMode::FastFullScreen
    }
}
// Translation type because in winit 24.0 the WinitWaylandTheme is a trait instead
// of a struct, which makes things more complicated
#[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,
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct WindowSize {
    /// Width and height of the window, in logical
    /// units (may not correspond to the physical on-screen size)
    pub dimensions: LogicalSize,
    /// Actual DPI value (default: 96)
    pub dpi: u32,
    /// Minimum dimensions of the window
    pub min_dimensions: OptionLogicalSize,
    /// Maximum dimensions of the window
    pub max_dimensions: OptionLogicalSize,
}
impl WindowSize {
    pub fn get_layout_size(&self) -> LayoutSize {
        LayoutSize::new(
            libm::roundf(self.dimensions.width) as isize,
            libm::roundf(self.dimensions.height) as isize,
        )
    }
    /// Get the actual logical size
    pub fn get_logical_size(&self) -> LogicalSize {
        self.dimensions
    }
    pub fn get_physical_size(&self) -> PhysicalSize<u32> {
        self.dimensions
            .to_physical(self.get_hidpi_factor().inner.get())
    }
7728
    pub fn get_hidpi_factor(&self) -> DpiScaleFactor {
7728
        DpiScaleFactor {
7728
            inner: FloatValue::new(self.dpi as f32 / 96.0),
7728
        }
7728
    }
}
impl Default for WindowSize {
5832
    fn default() -> Self {
5832
        Self {
5832
            dimensions: LogicalSize::new(640.0, 480.0),
5832
            dpi: 96,
5832
            min_dimensions: None.into(),
5832
            max_dimensions: None.into(),
5832
        }
5832
    }
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum RendererType {
    /// Force hardware rendering
    Hardware,
    /// Force software rendering
    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::*;
        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)
            }
        }
    }
}
/// Utility function for easier creation of a keymap - i.e. `[vec![Ctrl, S], my_function]`
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C, u8)]
pub enum AcceleratorKey {
    Ctrl,
    Alt,
    Shift,
    Key(VirtualKeyCode),
}
impl AcceleratorKey {
    /// Checks if the current keyboard state contains the given char or modifier,
    /// i.e. if the keyboard state currently has the shift key pressed and the
    /// accelerator key is `Shift`, evaluates to true, otherwise to false.
    pub fn matches(&self, keyboard_state: &KeyboardState) -> bool {
        use self::AcceleratorKey::*;
        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),
        }
    }
}
/// Symbolic name for a keyboard key, does NOT take the keyboard locale into account
#[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 {
    pub fn get_lowercase(&self) -> Option<char> {
        use self::VirtualKeyCode::*;
        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,
        }
    }
}
/// 16x16x4 bytes icon
#[derive(Debug, Clone)]
#[repr(C)]
pub struct SmallWindowIconBytes {
    pub key: IconKey,
    pub rgba_bytes: U8Vec,
}
/// 32x32x4 bytes icon
#[derive(Debug, Clone)]
#[repr(C)]
pub struct LargeWindowIconBytes {
    pub key: IconKey,
    pub rgba_bytes: U8Vec,
}
// Window icon that usually appears in the top-left corner of the window
#[derive(Debug, Clone)]
#[repr(C, u8)]
pub enum WindowIcon {
    Small(SmallWindowIconBytes),
    /// 32x32x4 bytes icon
    Large(LargeWindowIconBytes),
}
impl_option!(
    WindowIcon,
    OptionWindowIcon,
    copy = false,
    [Debug, Clone, PartialOrd, PartialEq, Eq, Hash, Ord]
);
impl WindowIcon {
    pub fn get_key(&self) -> IconKey {
        match &self {
            WindowIcon::Small(SmallWindowIconBytes { key, .. }) => *key,
            WindowIcon::Large(LargeWindowIconBytes { key, .. }) => *key,
        }
    }
}
// -- Only compare the IconKey (for WindowIcon and TaskBarIcon)
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);
    }
}
/// 256x256x4 bytes window icon
#[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);
    }
}