#[cfg(not(feature = "std"))]
use alloc::string::{String, ToString};
use alloc::{
boxed::Box,
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
vec::Vec,
};
use core::{
cmp::Ordering,
ffi::c_void,
hash::{Hash, Hasher},
ops,
sync::atomic::{AtomicI64, AtomicUsize, Ordering as AtomicOrdering},
};
use azul_css::{
css::CssPath,
props::{
basic::{ColorU, FloatValue, LayoutPoint, LayoutRect, LayoutSize},
property::CssProperty,
style::StyleCursor,
},
AzString, LayoutDebugMessage, OptionF32, OptionI32, OptionString, OptionU32, U8Vec,
};
use rust_fontconfig::FcFontCache;
use crate::{
callbacks::{LayoutCallback, LayoutCallbackType, Update},
dom::{DomId, DomNodeId, NodeHierarchy},
geom::{
LogicalPosition, LogicalRect, LogicalSize, OptionLogicalSize, PhysicalPositionI32,
PhysicalSize,
},
gl::OptionGlContextPtr,
hit_test::{ExternalScrollId, OverflowingScrollNode},
id::{NodeDataContainer, NodeId},
refany::OptionRefAny,
resources::{
DpiScaleFactor, Epoch, GlTextureCache, IdNamespace, ImageCache, ImageMask, ImageRef,
RendererResources, ResourceUpdate,
},
selection::SelectionState,
styled_dom::NodeHierarchyItemId,
task::{Instant, ThreadId, TimerId},
FastBTreeSet, FastHashMap,
};
pub const DEFAULT_TITLE: &str = "Azul App";
static LAST_WINDOW_ID: AtomicI64 = AtomicI64::new(0);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct WindowId {
pub id: i64,
}
impl WindowId {
pub fn new() -> Self {
WindowId {
id: LAST_WINDOW_ID.fetch_add(1, AtomicOrdering::SeqCst),
}
}
}
static LAST_ICON_KEY: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct IconKey {
icon_id: usize,
}
impl IconKey {
pub fn new() -> Self {
Self {
icon_id: LAST_ICON_KEY.fetch_add(1, AtomicOrdering::SeqCst),
}
}
}
#[repr(C)]
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
pub struct RendererOptions {
pub vsync: Vsync,
pub srgb: Srgb,
pub hw_accel: HwAcceleration,
}
impl_option!(
RendererOptions,
OptionRendererOptions,
[PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash]
);
impl Default for RendererOptions {
fn default() -> Self {
Self {
vsync: Vsync::Enabled,
srgb: Srgb::Disabled,
hw_accel: HwAcceleration::Enabled,
}
}
}
impl RendererOptions {
pub const fn new(vsync: Vsync, srgb: Srgb, hw_accel: HwAcceleration) -> Self {
Self {
vsync,
srgb,
hw_accel,
}
}
}
#[repr(C)]
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
pub enum Vsync {
Enabled,
Disabled,
DontCare,
}
impl Vsync {
pub const fn is_enabled(&self) -> bool {
match self {
Vsync::Enabled => true,
_ => false,
}
}
}
#[repr(C)]
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
pub enum Srgb {
Enabled,
Disabled,
DontCare,
}
impl Srgb {
pub const fn is_enabled(&self) -> bool {
match self {
Srgb::Enabled => true,
_ => false,
}
}
}
#[repr(C)]
#[derive(PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Eq, Hash)]
pub enum HwAcceleration {
Enabled,
Disabled,
DontCare,
}
impl HwAcceleration {
pub const fn is_enabled(&self) -> bool {
match self {
HwAcceleration::Enabled => true,
_ => false,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C, u8)]
pub enum RawWindowHandle {
IOS(IOSHandle),
MacOS(MacOSHandle),
Xlib(XlibHandle),
Xcb(XcbHandle),
Wayland(WaylandHandle),
Windows(WindowsHandle),
Web(WebHandle),
Android(AndroidHandle),
Unsupported,
}
unsafe impl Send for RawWindowHandle {}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct IOSHandle {
pub ui_window: *mut c_void,
pub ui_view: *mut c_void,
pub ui_view_controller: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct MacOSHandle {
pub ns_window: *mut c_void,
pub ns_view: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct XlibHandle {
pub window: u64,
pub display: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct XcbHandle {
pub window: u32,
pub connection: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct WaylandHandle {
pub surface: *mut c_void,
pub display: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct WindowsHandle {
pub hwnd: *mut c_void,
pub hinstance: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct WebHandle {
pub id: u32,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct AndroidHandle {
pub a_native_window: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum MouseCursorType {
Default,
Crosshair,
Hand,
Arrow,
Move,
Text,
Wait,
Help,
Progress,
NotAllowed,
ContextMenu,
Cell,
VerticalText,
Alias,
Copy,
NoDrop,
Grab,
Grabbing,
AllScroll,
ZoomIn,
ZoomOut,
EResize,
NResize,
NeResize,
NwResize,
SResize,
SeResize,
SwResize,
WResize,
EwResize,
NsResize,
NeswResize,
NwseResize,
ColResize,
RowResize,
}
impl Default for MouseCursorType {
fn default() -> Self {
MouseCursorType::Default
}
}
pub type ScanCode = u32;
#[derive(Default, Debug, Clone, PartialEq)]
#[repr(C)]
pub struct KeyboardState {
pub current_virtual_keycode: OptionVirtualKeyCode,
pub pressed_virtual_keycodes: VirtualKeyCodeVec,
pub pressed_scancodes: ScanCodeVec,
}
impl KeyboardState {
pub fn shift_down(&self) -> bool {
self.is_key_down(VirtualKeyCode::LShift) || self.is_key_down(VirtualKeyCode::RShift)
}
pub fn ctrl_down(&self) -> bool {
self.is_key_down(VirtualKeyCode::LControl) || self.is_key_down(VirtualKeyCode::RControl)
}
pub fn alt_down(&self) -> bool {
self.is_key_down(VirtualKeyCode::LAlt) || self.is_key_down(VirtualKeyCode::RAlt)
}
pub fn super_down(&self) -> bool {
self.is_key_down(VirtualKeyCode::LWin) || self.is_key_down(VirtualKeyCode::RWin)
}
pub fn is_key_down(&self, key: VirtualKeyCode) -> bool {
self.pressed_virtual_keycodes.iter().any(|k| *k == key)
}
}
impl_option!(
KeyboardState,
OptionKeyboardState,
copy = false,
[Debug, Clone, PartialEq]
);
impl_option!(
u32,
OptionChar,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_option!(
VirtualKeyCode,
OptionVirtualKeyCode,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_vec!(VirtualKeyCode, VirtualKeyCodeVec, VirtualKeyCodeVecDestructor, VirtualKeyCodeVecDestructorType, VirtualKeyCodeVecSlice, OptionVirtualKeyCode);
impl_vec_debug!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_partialord!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_ord!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_clone!(
VirtualKeyCode,
VirtualKeyCodeVec,
VirtualKeyCodeVecDestructor
);
impl_vec_partialeq!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_eq!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_hash!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec_as_hashmap!(VirtualKeyCode, VirtualKeyCodeVec);
impl_vec!(ScanCode, ScanCodeVec, ScanCodeVecDestructor, ScanCodeVecDestructorType, ScanCodeVecSlice, OptionU32);
impl_vec_debug!(ScanCode, ScanCodeVec);
impl_vec_partialord!(ScanCode, ScanCodeVec);
impl_vec_ord!(ScanCode, ScanCodeVec);
impl_vec_clone!(ScanCode, ScanCodeVec, ScanCodeVecDestructor);
impl_vec_partialeq!(ScanCode, ScanCodeVec);
impl_vec_eq!(ScanCode, ScanCodeVec);
impl_vec_hash!(ScanCode, ScanCodeVec);
impl_vec_as_hashmap!(ScanCode, ScanCodeVec);
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
#[repr(C)]
pub struct MouseState {
pub mouse_cursor_type: OptionMouseCursorType,
pub cursor_position: CursorPosition,
pub is_cursor_locked: bool,
pub left_down: bool,
pub right_down: bool,
pub middle_down: bool,
}
impl MouseState {
pub fn matches(&self, context: &ContextMenuMouseButton) -> bool {
use self::ContextMenuMouseButton::*;
match context {
Left => self.left_down,
Right => self.right_down,
Middle => self.middle_down,
}
}
}
impl_option!(
MouseState,
OptionMouseState,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
impl_option!(
MouseCursorType,
OptionMouseCursorType,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl Default for MouseState {
fn default() -> Self {
Self {
mouse_cursor_type: Some(MouseCursorType::Default).into(),
cursor_position: CursorPosition::default(),
is_cursor_locked: false,
left_down: false,
right_down: false,
middle_down: false,
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
#[repr(C)]
pub struct VirtualKeyCodeCombo {
pub keys: VirtualKeyCodeVec,
}
impl_option!(
VirtualKeyCodeCombo,
OptionVirtualKeyCodeCombo,
copy = false,
[Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord]
);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
#[repr(C)]
pub enum ContextMenuMouseButton {
Right,
Middle,
Left,
}
impl Default for ContextMenuMouseButton {
fn default() -> Self {
ContextMenuMouseButton::Right
}
}
impl MouseState {
pub fn mouse_down(&self) -> bool {
self.right_down || self.left_down || self.middle_down
}
}
#[derive(Debug)]
pub struct ScrollResult {}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C, u8)]
pub enum CursorPosition {
OutOfWindow(LogicalPosition),
Uninitialized,
InWindow(LogicalPosition),
}
impl Default for CursorPosition {
fn default() -> CursorPosition {
CursorPosition::Uninitialized
}
}
impl CursorPosition {
pub fn get_position(&self) -> Option<LogicalPosition> {
match self {
CursorPosition::InWindow(logical_pos) => Some(*logical_pos),
CursorPosition::OutOfWindow(_) | CursorPosition::Uninitialized => None,
}
}
pub fn is_inside_window(&self) -> bool {
self.get_position().is_some()
}
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(C)]
pub struct DebugState {
pub profiler_dbg: bool,
pub render_target_dbg: bool,
pub texture_cache_dbg: bool,
pub gpu_time_queries: bool,
pub gpu_sample_queries: bool,
pub disable_batching: bool,
pub epochs: bool,
pub echo_driver_messages: bool,
pub show_overdraw: bool,
pub gpu_cache_dbg: bool,
pub texture_cache_dbg_clear_evicted: bool,
pub picture_caching_dbg: bool,
pub primitive_dbg: bool,
pub zoom_dbg: bool,
pub small_screen: bool,
pub disable_opaque_pass: bool,
pub disable_alpha_pass: bool,
pub disable_clip_masks: bool,
pub disable_text_prims: bool,
pub disable_gradient_prims: bool,
pub obscure_images: bool,
pub glyph_flashing: bool,
pub smart_profiler: bool,
pub invalidation_dbg: bool,
pub tile_cache_logging_dbg: bool,
pub profiler_capture: bool,
pub force_picture_invalidation: bool,
}
fn translate_cursor(cursor: StyleCursor) -> MouseCursorType {
use azul_css::props::style::effects::StyleCursor;
match cursor {
StyleCursor::Default => MouseCursorType::Default,
StyleCursor::Crosshair => MouseCursorType::Crosshair,
StyleCursor::Pointer => MouseCursorType::Hand,
StyleCursor::Move => MouseCursorType::Move,
StyleCursor::Text => MouseCursorType::Text,
StyleCursor::Wait => MouseCursorType::Wait,
StyleCursor::Help => MouseCursorType::Help,
StyleCursor::Progress => MouseCursorType::Progress,
StyleCursor::ContextMenu => MouseCursorType::ContextMenu,
StyleCursor::Cell => MouseCursorType::Cell,
StyleCursor::VerticalText => MouseCursorType::VerticalText,
StyleCursor::Alias => MouseCursorType::Alias,
StyleCursor::Copy => MouseCursorType::Copy,
StyleCursor::Grab => MouseCursorType::Grab,
StyleCursor::Grabbing => MouseCursorType::Grabbing,
StyleCursor::AllScroll => MouseCursorType::AllScroll,
StyleCursor::ZoomIn => MouseCursorType::ZoomIn,
StyleCursor::ZoomOut => MouseCursorType::ZoomOut,
StyleCursor::EResize => MouseCursorType::EResize,
StyleCursor::NResize => MouseCursorType::NResize,
StyleCursor::SResize => MouseCursorType::SResize,
StyleCursor::SeResize => MouseCursorType::SeResize,
StyleCursor::WResize => MouseCursorType::WResize,
StyleCursor::EwResize => MouseCursorType::EwResize,
StyleCursor::NsResize => MouseCursorType::NsResize,
StyleCursor::NeswResize => MouseCursorType::NeswResize,
StyleCursor::NwseResize => MouseCursorType::NwseResize,
StyleCursor::ColResize => MouseCursorType::ColResize,
StyleCursor::RowResize => MouseCursorType::RowResize,
StyleCursor::Unset => MouseCursorType::Default,
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Hash, Ord, Eq)]
#[repr(C)]
pub struct TouchState {
pub num_touches: usize,
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct TouchPoint {
pub id: u64,
pub position: LogicalPosition,
pub force: f32,
}
impl_option!(
TouchPoint,
OptionTouchPoint,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
impl_vec!(TouchPoint, TouchPointVec, TouchPointVecDestructor, TouchPointVecDestructorType, TouchPointVecSlice, OptionTouchPoint);
impl_vec_debug!(TouchPoint, TouchPointVec);
impl_vec_clone!(TouchPoint, TouchPointVec, TouchPointVecDestructor);
impl_vec_partialeq!(TouchPoint, TouchPointVec);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Ord, Eq)]
#[repr(C)]
pub enum WindowTheme {
DarkMode,
LightMode,
}
impl Default for WindowTheme {
fn default() -> WindowTheme {
WindowTheme::LightMode }
}
impl_option!(
WindowTheme,
OptionWindowTheme,
[Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[repr(C)]
pub struct MonitorId {
pub index: usize,
pub hash: u64,
}
impl MonitorId {
pub const PRIMARY: MonitorId = MonitorId { index: 0, hash: 0 };
pub const fn new(index: usize) -> Self {
Self { index, hash: 0 }
}
pub const fn from_index_and_hash(index: usize, hash: u64) -> Self {
Self { index, hash }
}
pub fn from_properties(
index: usize,
name: &str,
position: LayoutPoint,
size: LayoutSize,
) -> Self {
use core::hash::{Hash, Hasher};
struct FnvHasher(u64);
impl Hasher for FnvHasher {
fn write(&mut self, bytes: &[u8]) {
const FNV_PRIME: u64 = 0x100000001b3;
for &byte in bytes {
self.0 ^= byte as u64;
self.0 = self.0.wrapping_mul(FNV_PRIME);
}
}
fn finish(&self) -> u64 {
self.0
}
}
const FNV_OFFSET_BASIS: u64 = 0xcbf29ce484222325;
let mut hasher = FnvHasher(FNV_OFFSET_BASIS);
name.hash(&mut hasher);
(position.x as i64).hash(&mut hasher);
(position.y as i64).hash(&mut hasher);
(size.width as i64).hash(&mut hasher);
(size.height as i64).hash(&mut hasher);
Self {
index,
hash: hasher.finish(),
}
}
}
impl_option!(
MonitorId,
OptionMonitorId,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
#[derive(Debug, PartialEq, PartialOrd, Clone)]
#[repr(C)]
pub struct Monitor {
pub monitor_id: MonitorId,
pub monitor_name: OptionString,
pub size: LayoutSize,
pub position: LayoutPoint,
pub scale_factor: f64,
pub work_area: LayoutRect,
pub video_modes: VideoModeVec,
pub is_primary_monitor: bool,
}
impl_option!(
Monitor,
OptionMonitor,
copy = false,
[Debug, PartialEq, PartialOrd, Clone]
);
impl_vec!(Monitor, MonitorVec, MonitorVecDestructor, MonitorVecDestructorType, MonitorVecSlice, OptionMonitor);
impl_vec_debug!(Monitor, MonitorVec);
impl_vec_clone!(Monitor, MonitorVec, MonitorVecDestructor);
impl_vec_partialeq!(Monitor, MonitorVec);
impl_vec_partialord!(Monitor, MonitorVec);
impl core::hash::Hash for Monitor {
fn hash<H>(&self, state: &mut H)
where
H: core::hash::Hasher,
{
self.monitor_id.hash(state)
}
}
impl Default for Monitor {
fn default() -> Self {
Monitor {
monitor_id: MonitorId::PRIMARY,
monitor_name: OptionString::None,
size: LayoutSize::zero(),
position: LayoutPoint::zero(),
scale_factor: 1.0,
work_area: LayoutRect::zero(),
video_modes: Vec::new().into(),
is_primary_monitor: false,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct VideoMode {
pub size: LayoutSize,
pub bit_depth: u16,
pub refresh_rate: u16,
}
impl_option!(
VideoMode,
OptionVideoMode,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_vec!(VideoMode, VideoModeVec, VideoModeVecDestructor, VideoModeVecDestructorType, VideoModeVecSlice, OptionVideoMode);
impl_vec_clone!(VideoMode, VideoModeVec, VideoModeVecDestructor);
impl_vec_debug!(VideoMode, VideoModeVec);
impl_vec_partialeq!(VideoMode, VideoModeVec);
impl_vec_partialord!(VideoMode, VideoModeVec);
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C, u8)]
pub enum WindowPosition {
Uninitialized,
Initialized(PhysicalPositionI32),
}
impl Default for WindowPosition {
fn default() -> WindowPosition {
WindowPosition::Uninitialized
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C, u8)]
pub enum ImePosition {
Uninitialized,
Initialized(LogicalRect),
}
impl Default for ImePosition {
fn default() -> ImePosition {
ImePosition::Uninitialized
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub struct WindowFlags {
pub frame: WindowFrame,
pub close_requested: bool,
pub decorations: WindowDecorations,
pub is_visible: bool,
pub is_always_on_top: bool,
pub is_resizable: bool,
pub has_focus: bool,
pub background_material: WindowBackgroundMaterial,
pub smooth_scroll_enabled: bool,
pub autotab_enabled: bool,
pub window_type: WindowType,
pub has_decorations: bool,
pub use_native_menus: bool,
pub use_native_context_menus: bool,
pub is_top_level: bool,
pub prevent_system_sleep: bool,
}
impl_option!(
WindowFlags,
OptionWindowFlags,
copy = false,
[Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub enum WindowType {
Normal,
Menu,
Tooltip,
Dialog,
}
impl Default for WindowType {
fn default() -> Self {
Self::Normal
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub enum WindowFrame {
Normal,
Minimized,
Maximized,
Fullscreen,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub enum WindowDecorations {
Normal,
NoTitle,
NoTitleAutoInject,
NoControls,
None,
}
impl Default for WindowDecorations {
fn default() -> Self {
Self::Normal
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub enum WindowBackgroundMaterial {
Opaque,
Transparent,
Sidebar,
Menu,
HUD,
Titlebar,
MicaAlt,
}
impl Default for WindowBackgroundMaterial {
fn default() -> Self {
Self::Opaque
}
}
impl Default for WindowFlags {
fn default() -> Self {
Self {
frame: WindowFrame::Normal,
close_requested: false,
decorations: WindowDecorations::Normal,
is_visible: true,
is_always_on_top: false,
is_resizable: true,
has_focus: true,
background_material: WindowBackgroundMaterial::Opaque,
smooth_scroll_enabled: true,
autotab_enabled: true,
window_type: WindowType::Normal,
has_decorations: false,
use_native_menus: cfg!(any(target_os = "windows", target_os = "macos")),
use_native_context_menus: cfg!(any(target_os = "windows", target_os = "macos")),
is_top_level: false,
prevent_system_sleep: false,
}
}
}
impl WindowFlags {
#[inline]
pub fn is_menu_window(&self) -> bool {
self.window_type == WindowType::Menu
}
#[inline]
pub fn is_tooltip_window(&self) -> bool {
self.window_type == WindowType::Tooltip
}
#[inline]
pub fn is_dialog_window(&self) -> bool {
self.window_type == WindowType::Dialog
}
#[inline]
pub fn window_has_focus(&self) -> bool {
self.has_focus
}
#[inline]
pub fn is_close_requested(&self) -> bool {
self.close_requested
}
#[inline]
pub fn has_csd(&self) -> bool {
self.has_decorations
}
#[inline]
pub fn use_native_menus(&self) -> bool {
self.use_native_menus
}
#[inline]
pub fn use_native_context_menus(&self) -> bool {
self.use_native_context_menus
}
}
#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct PlatformSpecificOptions {
pub windows_options: WindowsWindowOptions,
pub linux_options: LinuxWindowOptions,
pub mac_options: MacWindowOptions,
pub wasm_options: WasmWindowOptions,
}
unsafe impl Sync for PlatformSpecificOptions {}
unsafe impl Send for PlatformSpecificOptions {}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct WindowsWindowOptions {
pub allow_drag_and_drop: bool,
pub no_redirection_bitmap: bool,
pub window_icon: OptionWindowIcon,
pub taskbar_icon: OptionTaskBarIcon,
pub parent_window: OptionHwndHandle,
}
impl Default for WindowsWindowOptions {
fn default() -> WindowsWindowOptions {
WindowsWindowOptions {
allow_drag_and_drop: true,
no_redirection_bitmap: false,
window_icon: OptionWindowIcon::None,
taskbar_icon: OptionTaskBarIcon::None,
parent_window: OptionHwndHandle::None,
}
}
}
pub type HwndHandle = *mut c_void;
impl_option!(
HwndHandle,
OptionHwndHandle,
copy = false,
[Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum XWindowType {
Desktop,
Dock,
Toolbar,
Menu,
Utility,
Splash,
Dialog,
DropdownMenu,
PopupMenu,
Tooltip,
Notification,
Combo,
Dnd,
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 {
fn default() -> UserAttentionType {
UserAttentionType::None
}
}
#[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 x11_visual: OptionX11Visual,
pub x11_screen: OptionI32,
pub x11_wm_classes: StringPairVec,
pub x11_override_redirect: bool,
pub x11_window_types: XWindowTypeVec,
pub x11_gtk_theme_variant: OptionString,
pub x11_resize_increments: OptionLogicalSize,
pub x11_base_size: OptionLogicalSize,
pub wayland_app_id: OptionString,
pub wayland_theme: OptionWaylandTheme,
pub request_user_attention: UserAttentionType,
pub window_icon: OptionWindowIcon,
pub x11_decorations_state: OptionLinuxDecorationsState,
}
pub type X11Visual = *const c_void;
impl_option!(
X11Visual,
OptionX11Visual,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct AzStringPair {
pub key: AzString,
pub value: AzString,
}
impl_option!(
AzStringPair,
OptionStringPair,
copy = false,
[Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
);
impl_vec!(AzStringPair, StringPairVec, StringPairVecDestructor, StringPairVecDestructorType, StringPairVecSlice, OptionStringPair);
impl_vec_mut!(AzStringPair, StringPairVec);
impl_vec_debug!(AzStringPair, StringPairVec);
impl_vec_partialord!(AzStringPair, StringPairVec);
impl_vec_ord!(AzStringPair, StringPairVec);
impl_vec_clone!(AzStringPair, StringPairVec, StringPairVecDestructor);
impl_vec_partialeq!(AzStringPair, StringPairVec);
impl_vec_eq!(AzStringPair, StringPairVec);
impl_vec_hash!(AzStringPair, StringPairVec);
impl_option!(
StringPairVec,
OptionStringPairVec,
copy = false,
[Debug, Clone, PartialOrd, PartialEq, Ord, Eq, Hash]
);
impl StringPairVec {
pub fn get_key(&self, search_key: &str) -> Option<&AzString> {
self.as_ref().iter().find_map(|v| {
if v.key.as_str() == search_key {
Some(&v.value)
} else {
None
}
})
}
pub fn get_key_mut(&mut self, search_key: &str) -> Option<&mut AzStringPair> {
self.as_mut()
.iter_mut()
.find(|v| v.key.as_str() == search_key)
}
pub fn insert_kv<I: Into<AzString>>(&mut self, key: I, value: I) {
let key = key.into();
let value = value.into();
match self.get_key_mut(key.as_str()) {
None => {}
Some(s) => {
s.value = value;
return;
}
}
self.push(AzStringPair { key, value });
}
}
impl_vec!(XWindowType, XWindowTypeVec, XWindowTypeVecDestructor, XWindowTypeVecDestructorType, XWindowTypeVecSlice, OptionXWindowType);
impl_vec_debug!(XWindowType, XWindowTypeVec);
impl_vec_partialord!(XWindowType, XWindowTypeVec);
impl_vec_ord!(XWindowType, XWindowTypeVec);
impl_vec_clone!(XWindowType, XWindowTypeVec, XWindowTypeVecDestructor);
impl_vec_partialeq!(XWindowType, XWindowTypeVec);
impl_vec_eq!(XWindowType, XWindowTypeVec);
impl_vec_hash!(XWindowType, XWindowTypeVec);
impl_option!(
WaylandTheme,
OptionWaylandTheme,
copy = false,
[Debug, Clone, PartialEq, PartialOrd]
);
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct MacWindowOptions {
pub _reserved: u8,
}
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct WasmWindowOptions {
pub _reserved: u8,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum FullScreenMode {
SlowFullScreen,
FastFullScreen,
SlowWindowed,
FastWindowed,
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct WaylandTheme {
pub title_bar_active_background_color: ColorU,
pub title_bar_active_separator_color: ColorU,
pub title_bar_active_text_color: ColorU,
pub title_bar_inactive_background_color: ColorU,
pub title_bar_inactive_separator_color: ColorU,
pub title_bar_inactive_text_color: ColorU,
pub maximize_idle_foreground_inactive_color: ColorU,
pub minimize_idle_foreground_inactive_color: ColorU,
pub close_idle_foreground_inactive_color: ColorU,
pub maximize_hovered_foreground_inactive_color: ColorU,
pub minimize_hovered_foreground_inactive_color: ColorU,
pub close_hovered_foreground_inactive_color: ColorU,
pub maximize_disabled_foreground_inactive_color: ColorU,
pub minimize_disabled_foreground_inactive_color: ColorU,
pub close_disabled_foreground_inactive_color: ColorU,
pub maximize_idle_background_inactive_color: ColorU,
pub minimize_idle_background_inactive_color: ColorU,
pub close_idle_background_inactive_color: ColorU,
pub maximize_hovered_background_inactive_color: ColorU,
pub minimize_hovered_background_inactive_color: ColorU,
pub close_hovered_background_inactive_color: ColorU,
pub maximize_disabled_background_inactive_color: ColorU,
pub minimize_disabled_background_inactive_color: ColorU,
pub close_disabled_background_inactive_color: ColorU,
pub maximize_idle_foreground_active_color: ColorU,
pub minimize_idle_foreground_active_color: ColorU,
pub close_idle_foreground_active_color: ColorU,
pub maximize_hovered_foreground_active_color: ColorU,
pub minimize_hovered_foreground_active_color: ColorU,
pub close_hovered_foreground_active_color: ColorU,
pub maximize_disabled_foreground_active_color: ColorU,
pub minimize_disabled_foreground_active_color: ColorU,
pub close_disabled_foreground_active_color: ColorU,
pub maximize_idle_background_active_color: ColorU,
pub minimize_idle_background_active_color: ColorU,
pub close_idle_background_active_color: ColorU,
pub maximize_hovered_background_active_color: ColorU,
pub minimize_hovered_background_active_color: ColorU,
pub close_hovered_background_active_color: ColorU,
pub maximize_disabled_background_active_color: ColorU,
pub minimize_disabled_background_active_color: ColorU,
pub close_disabled_background_active_color: ColorU,
pub title_bar_font: AzString,
pub title_bar_font_size: f32,
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct WindowSize {
pub dimensions: LogicalSize,
pub dpi: u32,
pub min_dimensions: OptionLogicalSize,
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,
)
}
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())
}
pub fn get_hidpi_factor(&self) -> DpiScaleFactor {
DpiScaleFactor {
inner: FloatValue::new(self.dpi as f32 / 96.0),
}
}
}
impl Default for WindowSize {
fn default() -> Self {
Self {
#[cfg(not(feature = "glow"))]
dimensions: LogicalSize::new(640.0, 480.0),
dpi: 96,
min_dimensions: None.into(),
max_dimensions: None.into(),
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum RendererType {
Hardware,
Software,
}
impl_option!(
RendererType,
OptionRendererType,
[Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash]
);
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum UpdateFocusWarning {
FocusInvalidDomId(DomId),
FocusInvalidNodeId(NodeHierarchyItemId),
CouldNotFindFocusNode(CssPath),
}
impl ::core::fmt::Display for UpdateFocusWarning {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
use self::UpdateFocusWarning::*;
match self {
FocusInvalidDomId(dom_id) => write!(f, "Focusing on DOM with invalid ID: {:?}", dom_id),
FocusInvalidNodeId(node_id) => {
write!(f, "Focusing on node with invalid ID: {}", node_id)
}
CouldNotFindFocusNode(css_path) => {
write!(f, "Could not find focus node for path: {}", css_path)
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C, u8)]
pub enum AcceleratorKey {
Ctrl,
Alt,
Shift,
Key(VirtualKeyCode),
}
impl AcceleratorKey {
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),
}
}
}
#[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,
}
}
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct SmallWindowIconBytes {
pub key: IconKey,
pub rgba_bytes: U8Vec,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct LargeWindowIconBytes {
pub key: IconKey,
pub rgba_bytes: U8Vec,
}
#[derive(Debug, Clone)]
#[repr(C, u8)]
pub enum WindowIcon {
Small(SmallWindowIconBytes),
Large(LargeWindowIconBytes),
}
impl_option!(
WindowIcon,
OptionWindowIcon,
copy = false,
[Debug, Clone, PartialOrd, PartialEq, Eq, Hash, Ord]
);
impl WindowIcon {
pub fn get_key(&self) -> IconKey {
match &self {
WindowIcon::Small(SmallWindowIconBytes { key, .. }) => *key,
WindowIcon::Large(LargeWindowIconBytes { key, .. }) => *key,
}
}
}
impl PartialEq for WindowIcon {
fn eq(&self, rhs: &Self) -> bool {
self.get_key() == rhs.get_key()
}
}
impl PartialOrd for WindowIcon {
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
Some((self.get_key()).cmp(&rhs.get_key()))
}
}
impl Eq for WindowIcon {}
impl Ord for WindowIcon {
fn cmp(&self, rhs: &Self) -> Ordering {
(self.get_key()).cmp(&rhs.get_key())
}
}
impl Hash for WindowIcon {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.get_key().hash(state);
}
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TaskBarIcon {
pub key: IconKey,
pub rgba_bytes: U8Vec,
}
impl_option!(
TaskBarIcon,
OptionTaskBarIcon,
copy = false,
[Debug, Clone, PartialOrd, PartialEq, Eq, Hash, Ord]
);
impl PartialEq for TaskBarIcon {
fn eq(&self, rhs: &Self) -> bool {
self.key == rhs.key
}
}
impl PartialOrd for TaskBarIcon {
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
Some((self.key).cmp(&rhs.key))
}
}
impl Eq for TaskBarIcon {}
impl Ord for TaskBarIcon {
fn cmp(&self, rhs: &Self) -> Ordering {
(self.key).cmp(&rhs.key)
}
}
impl Hash for TaskBarIcon {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.key.hash(state);
}
}