From 0d95e1910d7ea0dcccb2cc774ba189dfe5b5c8ba Mon Sep 17 00:00:00 2001 From: MicroBlock <66859419+MicroCBer@users.noreply.github.com> Date: Fri, 16 Feb 2024 08:10:32 +0000 Subject: [PATCH 1/4] update https://sciter.com/forums/topic/linux-no-libsciter-gtk-so-and-shader-compilation-error/ --- src/capi/scdef.rs | 8 ++++++++ src/lib.rs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/capi/scdef.rs b/src/capi/scdef.rs index e731416..80aff3e 100644 --- a/src/capi/scdef.rs +++ b/src/capi/scdef.rs @@ -74,6 +74,14 @@ pub enum GFX_LAYER /// Skia backend with OpenGL rendering. SKIA_OPENGL = 5, + /// vulkan + SKIA_VULKAN = 6, + #[cfg(osx)] + SKIA_METAL = 7, + #[cfg(windows)] + SKIA_DX12 = 8, + // auto + SKIA_GPU = 9, } #[repr(C)] diff --git a/src/lib.rs b/src/lib.rs index 67e5cca..f423b9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -225,7 +225,7 @@ mod ext { pub static mut CUSTOM_DLL_PATH: Option = None; #[cfg(target_os = "linux")] - const DLL_NAMES: &[&str] = &[ "libsciter-gtk.so" ]; + const DLL_NAMES: &[&str] = &[ "libsciter.so" ]; // "libsciter.dylib" since Sciter 4.4.6.3. #[cfg(target_os = "macos")] From 518076af3956161030ee4b40516082d3e58ddb1a Mon Sep 17 00:00:00 2001 From: MicroBlock <66859419+MicroCBer@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:42:22 +0800 Subject: [PATCH 2/4] Update value.rs --- src/value.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/value.rs b/src/value.rs index f83405f..162d6f3 100644 --- a/src/value.rs +++ b/src/value.rs @@ -556,9 +556,11 @@ impl Value { let argc = count as usize; let mut argv: Vec = Vec::with_capacity(argc); assert!(argc == 0 || !args.is_null()); - let args = ::std::slice::from_raw_parts(args, argc); - for arg in args { - argv.push(Value::copy_from(arg)); + if argc != 0 { + let args = ::std::slice::from_raw_parts(args, argc); + for arg in args { + argv.push(Value::copy_from(arg)); + } } return argv; } From 9569e59adb4ffc7eb0aa8811c41c9723ea99097a Mon Sep 17 00:00:00 2001 From: MicroBlock <66859419+std-microblock@users.noreply.github.com> Date: Tue, 7 Oct 2025 17:52:05 +0800 Subject: [PATCH 3/4] feat: Introduce bitflags for script runtime features and window creation flags --- Cargo.toml | 1 + examples/interop.rs | 6 ++-- examples/minimal.rs | 6 ++-- src/capi/scdef.rs | 77 +++++++++++++++++++++------------------------ src/lib.rs | 1 + src/platform.rs | 8 ++--- src/window.rs | 6 ++-- 7 files changed, 48 insertions(+), 57 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 27d014e..a6b188e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ windowless = [] [dependencies] libc = "0.2" lazy_static = "1.0" +bitflags = "1.0" [target.'cfg(target_vendor = "apple")'.dependencies] objc = "0.2" diff --git a/examples/interop.rs b/examples/interop.rs index df1f0b7..6faab8c 100644 --- a/examples/interop.rs +++ b/examples/interop.rs @@ -133,10 +133,8 @@ impl sciter::EventHandler for EventHandler { } fn check_options() { - sciter::set_options(sciter::RuntimeOptions::ScriptFeatures( - sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_SYSINFO as u8 // Enables `Sciter.machineName()` - | sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_FILE_IO as u8 // Enables opening file dialog (`view.selectFile()`) - )).ok(); + let mask = (sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_SYSINFO | sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_FILE_IO).bits() as u8; + sciter::set_options(sciter::RuntimeOptions::ScriptFeatures(mask)).ok(); for arg in std::env::args() { if arg.starts_with("--sciter-gfx=") { diff --git a/examples/minimal.rs b/examples/minimal.rs index 3f01018..a201707 100644 --- a/examples/minimal.rs +++ b/examples/minimal.rs @@ -12,10 +12,8 @@ fn main() { let html = include_bytes!("minimal.htm"); // Step 2: Enable the features we need in our tiscript code. - sciter::set_options(sciter::RuntimeOptions::ScriptFeatures( - sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_SYSINFO as u8 // Enables `Sciter.machineName()`. Required for opening file dialog (`view.selectFile()`) - | sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_FILE_IO as u8 // Enables opening file dialog (`view.selectFile()`) - )).unwrap(); + let mask = (sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_SYSINFO | sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_FILE_IO).bits() as u8; + sciter::set_options(sciter::RuntimeOptions::ScriptFeatures(mask)).unwrap(); // Enable debug mode for all windows, so that we can inspect them via Inspector. sciter::set_options(sciter::RuntimeOptions::DebugMode(true)).unwrap(); diff --git a/src/capi/scdef.rs b/src/capi/scdef.rs index 80aff3e..00d5208 100644 --- a/src/capi/scdef.rs +++ b/src/capi/scdef.rs @@ -37,15 +37,15 @@ pub enum LOAD_RESULT { } /// Script runtime options. -#[repr(C)] -#[derive(Debug)] -#[allow(missing_docs)] -pub enum SCRIPT_RUNTIME_FEATURES -{ - ALLOW_FILE_IO = 0x1, - ALLOW_SOCKET_IO = 0x2, - ALLOW_EVAL = 0x4, - ALLOW_SYSINFO = 0x8, +bitflags! { + #[repr(C)] + #[allow(missing_docs)] + pub struct SCRIPT_RUNTIME_FEATURES: u8 { + const ALLOW_FILE_IO = 0x1; + const ALLOW_SOCKET_IO = 0x2; + const ALLOW_EVAL = 0x4; + const ALLOW_SYSINFO = 0x8; + } } /// Sciter graphics rendering backend. @@ -128,30 +128,32 @@ pub enum SCITER_RT_OPTIONS } /// Window flags -#[repr(C)] -pub enum SCITER_CREATE_WINDOW_FLAGS { - /// child window only, if this flag is set all other flags ignored. - SW_CHILD = 1, - /// toplevel window, has titlebar. - SW_TITLEBAR = 1 << 1, - /// has resizeable frame. - SW_RESIZEABLE = 1 << 2, - /// is tool window. - SW_TOOL = 1 << 3, - /// has minimize / maximize buttons. - SW_CONTROLS = 1 << 4, - /// glassy window - "Acrylic" on Windows and "Vibrant" on macOS. - SW_GLASSY = 1 << 5, - /// transparent window (e.g. `WS_EX_LAYERED` on Windows, macOS is supported too). - SW_ALPHA = 1 << 6, - /// main window of the app, will terminate the app on close. - SW_MAIN = 1 << 7, - /// the window is created as topmost window. - SW_POPUP = 1 << 8, - /// make this window inspector ready. - SW_ENABLE_DEBUG = 1 << 9, - /// it has its own script VM. - SW_OWNS_VM = 1 << 10, +bitflags! { + #[repr(C)] + pub struct SCITER_CREATE_WINDOW_FLAGS: u32 { + /// child window only, if this flag is set all other flags ignored. + const SW_CHILD = 1; + /// toplevel window, has titlebar. + const SW_TITLEBAR = 1 << 1; + /// has resizeable frame. + const SW_RESIZEABLE = 1 << 2; + /// is tool window. + const SW_TOOL = 1 << 3; + /// has minimize / maximize buttons. + const SW_CONTROLS = 1 << 4; + /// glassy window - "Acrylic" on Windows and "Vibrant" on macOS. + const SW_GLASSY = 1 << 5; + /// transparent window (e.g. `WS_EX_LAYERED` on Windows, macOS is supported too). + const SW_ALPHA = 1 << 6; + /// main window of the app, will terminate the app on close. + const SW_MAIN = 1 << 7; + /// the window is created as topmost window. + const SW_POPUP = 1 << 8; + /// make this window inspector ready. + const SW_ENABLE_DEBUG = 1 << 9; + /// it has its own script VM. + const SW_OWNS_VM = 1 << 10; + } } impl Default for SCITER_CREATE_WINDOW_FLAGS { @@ -160,15 +162,6 @@ impl Default for SCITER_CREATE_WINDOW_FLAGS { } } -/// Flags can be OR'ed as `SW_MAIN|SW_ALPHA`. -impl ::std::ops::BitOr for SCITER_CREATE_WINDOW_FLAGS { - type Output = SCITER_CREATE_WINDOW_FLAGS; - fn bitor(self, rhs: Self::Output) -> Self::Output { - let rn = (self as UINT) | (rhs as UINT); - unsafe { ::std::mem::transmute(rn) } - } -} - #[repr(C)] #[derive(Debug, PartialOrd, PartialEq)] pub enum SCITER_NOTIFICATION { diff --git a/src/lib.rs b/src/lib.rs index f423b9c..d8a3f80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,6 +77,7 @@ folder for more complex usage and module-level sections for the guides about: #[cfg(target_os = "macos")] #[macro_use] extern crate objc; #[macro_use] extern crate lazy_static; +#[macro_use] extern crate bitflags; #[macro_use] pub mod macros; diff --git a/src/platform.rs b/src/platform.rs index 736d818..7732805 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -80,7 +80,7 @@ mod windows { /// Create a new native window. fn create(&mut self, rc: RECT, flags: UINT, parent: HWINDOW) -> HWINDOW { - if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN as u32) != 0 { + if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN.bits()) != 0 { OsWindow::init_app(); } @@ -225,7 +225,7 @@ mod linux { /// Create a new native window. fn create(&mut self, rc: RECT, flags: UINT, parent: HWINDOW) -> HWINDOW { - if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN as u32) != 0 { + if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN.bits()) != 0 { OsWindow::init_app(); } @@ -385,7 +385,7 @@ mod macos { /// Create a new native window. fn create(&mut self, rc: RECT, flags: UINT, parent: HWINDOW) -> HWINDOW { - if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN as u32) != 0 { + if (flags & SCITER_CREATE_WINDOW_FLAGS::SW_MAIN.bits()) != 0 { OsWindow::init_app(); } @@ -430,7 +430,7 @@ mod macos { /// Show or maximize window. fn expand(&self, maximize: bool) { let wnd = self.window(); - if (self.flags & SCITER_CREATE_WINDOW_FLAGS::SW_TITLEBAR as UINT) != 0 { + if (self.flags & SCITER_CREATE_WINDOW_FLAGS::SW_TITLEBAR.bits()) != 0 { let app = OsWindow::get_app(); let _: () = unsafe { msg_send!(app, activateIgnoringOtherApps:true) }; } diff --git a/src/window.rs b/src/window.rs index 8642319..8a20155 100644 --- a/src/window.rs +++ b/src/window.rs @@ -108,7 +108,7 @@ impl Window { } let mut base = OsWindow::new(); - let hwnd = base.create(rect, flags as UINT, parent.unwrap_or(0 as HWINDOW)); + let hwnd = base.create(rect, flags.bits() as UINT, parent.unwrap_or(0 as HWINDOW)); assert!(!hwnd.is_null()); let wnd = Window { base: base, host: Rc::new(Host::attach(hwnd))}; @@ -552,8 +552,8 @@ impl Builder { } fn and(mut self, flag: Flags) -> Self { - let masked = self.flags as u32 & !(flag as u32); - self.flags = unsafe { ::std::mem::transmute(masked) }; + let masked = self.flags.bits() & !flag.bits(); + self.flags = SCITER_CREATE_WINDOW_FLAGS::from_bits_truncate(masked); self } From 18e23fcbbb2b740d9462d64cf3934e4cad02856f Mon Sep 17 00:00:00 2001 From: MicroBlock <66859419+std-microblock@users.noreply.github.com> Date: Tue, 7 Oct 2025 18:03:01 +0800 Subject: [PATCH 4/4] refactor: Replace enums with bitflags for EVENT_GROUPS and ELEMENT_STATE_BITS --- src/capi/scbehavior.rs | 103 +++++++++---------- src/capi/scdom.rs | 221 +++++++++++++++++++---------------------- src/dom.rs | 89 ++++++++--------- src/eventhandler.rs | 8 +- src/host.rs | 2 +- 5 files changed, 199 insertions(+), 224 deletions(-) diff --git a/src/capi/scbehavior.rs b/src/capi/scbehavior.rs index 897b65f..6ffe332 100644 --- a/src/capi/scbehavior.rs +++ b/src/capi/scbehavior.rs @@ -158,54 +158,54 @@ pub enum DRAW_EVENTS { /// Event groups for subscription. -#[repr(C)] -#[derive(Copy, Clone)] -#[derive(Debug, PartialOrd, PartialEq)] -pub enum EVENT_GROUPS -{ /// Attached/detached. - HANDLE_INITIALIZATION = 0x0000, - /// Mouse events. - HANDLE_MOUSE = 0x0001, - /// Key events. - HANDLE_KEY = 0x0002, - /// Focus events, if this flag is set it also means that element it attached to is focusable. - HANDLE_FOCUS = 0x0004, - /// Scroll events. - HANDLE_SCROLL = 0x0008, - /// Timer event. - HANDLE_TIMER = 0x0010, - /// Size changed event. - HANDLE_SIZE = 0x0020, - /// Drawing request (event). - HANDLE_DRAW = 0x0040, - /// Requested data has been delivered. - HANDLE_DATA_ARRIVED = 0x080, - - /// Logical, synthetic events: - /// `BUTTON_CLICK`, `HYPERLINK_CLICK`, etc., - /// a.k.a. notifications from intrinsic behaviors. - HANDLE_BEHAVIOR_EVENT = 0x0100, - /// Behavior specific methods. - HANDLE_METHOD_CALL = 0x0200, - /// Behavior specific methods. - HANDLE_SCRIPTING_METHOD_CALL = 0x0400, - - /// Behavior specific methods using direct `tiscript::value`'s. - #[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")] - HANDLE_TISCRIPT_METHOD_CALL = 0x0800, - - /// System drag-n-drop. - HANDLE_EXCHANGE = 0x1000, - /// Touch input events. - HANDLE_GESTURE = 0x2000, - /// SOM passport and asset requests. - HANDLE_SOM = 0x8000, - - /// All of them. - HANDLE_ALL = 0xFFFF, - - /// Special value for getting subscription flags. - SUBSCRIPTIONS_REQUEST = -1, +bitflags! { + #[repr(C)] + pub struct EVENT_GROUPS: u32 { + /// Attached/detached. + const HANDLE_INITIALIZATION = 0x0000; + /// Mouse events. + const HANDLE_MOUSE = 0x0001; + /// Key events. + const HANDLE_KEY = 0x0002; + /// Focus events, if this flag is set it also means that element it attached to is focusable. + const HANDLE_FOCUS = 0x0004; + /// Scroll events. + const HANDLE_SCROLL = 0x0008; + /// Timer event. + const HANDLE_TIMER = 0x0010; + /// Size changed event. + const HANDLE_SIZE = 0x0020; + /// Drawing request (event). + const HANDLE_DRAW = 0x0040; + /// Requested data has been delivered. + const HANDLE_DATA_ARRIVED = 0x0080; + + /// Logical, synthetic events: + /// `BUTTON_CLICK`, `HYPERLINK_CLICK`, etc., + /// a.k.a. notifications from intrinsic behaviors. + const HANDLE_BEHAVIOR_EVENT = 0x0100; + /// Behavior specific methods. + const HANDLE_METHOD_CALL = 0x0200; + /// Behavior specific methods. + const HANDLE_SCRIPTING_METHOD_CALL = 0x0400; + + /// Behavior specific methods using direct `tiscript::value`'s. + #[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")] + const HANDLE_TISCRIPT_METHOD_CALL = 0x0800; + + /// System drag-n-drop. + const HANDLE_EXCHANGE = 0x1000; + /// Touch input events. + const HANDLE_GESTURE = 0x2000; + /// SOM passport and asset requests. + const HANDLE_SOM = 0x8000; + + /// All of them. + const HANDLE_ALL = 0xFFFF; + + /// Special value for getting subscription flags. + const SUBSCRIPTIONS_REQUEST = 0xFFFFFFFF; // since -1 as u32 + } } #[repr(C)] @@ -542,10 +542,3 @@ pub enum BEHAVIOR_EVENTS } -impl ::std::ops::BitOr for EVENT_GROUPS { - type Output = EVENT_GROUPS; - fn bitor(self, rhs: Self::Output) -> Self::Output { - let rn = (self as UINT) | (rhs as UINT); - unsafe { ::std::mem::transmute(rn) } - } -} diff --git a/src/capi/scdom.rs b/src/capi/scdom.rs index 9473859..6c5b5be 100644 --- a/src/capi/scdom.rs +++ b/src/capi/scdom.rs @@ -106,127 +106,110 @@ impl ELEMENT_AREAS { /// e.g. `STATE_HOVER` is `:hover`, `STATE_ACTIVE` is `:active`, and so on. /// /// Implements `|` and `&` bitwise operators. -#[repr(C)] -#[derive(Debug, PartialOrd, PartialEq)] -pub enum ELEMENT_STATE_BITS -{ - /// Zero state. - STATE_NONE = 0x00000000, - - /// Element is a link. - /// - /// E.g. `` or `` elements. - STATE_ACTIVE = 0x00000004, - /// Element is focused. - STATE_FOCUS = 0x00000008, - - /// Element was visited. - /// - /// For example, a link that was clicked. - STATE_VISITED = 0x00000010, - /// Current (hot) item. - STATE_CURRENT = 0x00000020, - /// Element is checked (or selected). - STATE_CHECKED = 0x00000040, - /// Element is disabled. - STATE_DISABLED = 0x00000080, - /// Readonly input element. - STATE_READONLY = 0x00000100, - - /// Expanded state - e.g. nodes in tree view. - /// - /// Mutually exclusive with `STATE_COLLAPSED`. - STATE_EXPANDED = 0x00000200, - - /// Collapsed state - e.g. nodes in tree view. - /// - /// Mutually exclusive with `STATE_EXPANDED`. - STATE_COLLAPSED = 0x00000400, - - /// One of fore/back images was requested but is not delivered. - STATE_INCOMPLETE = 0x00000800, - /// Is animating currently. - STATE_ANIMATING = 0x00001000, - /// Will accept focus. - STATE_FOCUSABLE = 0x00002000, - - /// Anchor in selection (used with current in selects). - STATE_ANCHOR = 0x00004000, - /// This is a synthetic element - i.e. don't emit it's head/tail. - STATE_SYNTHETIC = 0x00008000, - /// A popup element is shown for this particular element. - STATE_OWNS_POPUP = 0x00010000, - - /// Focus gained by tab traversal. - STATE_TABFOCUS = 0x00020000, - - /// Element is empty. - /// - /// i.e. the element has no text content nor children nodes. - /// - /// If element has a behavior attached then the behavior is responsible for the value of this flag. - STATE_EMPTY = 0x00040000, - - /// Busy or loading. - STATE_BUSY = 0x00080000, - - /// Drag over the block that can accept it (so is a current drop target). - /// - /// Flag is set for the drop target block. - STATE_DRAG_OVER = 0x00100000, - /// Active drop target. - STATE_DROP_TARGET = 0x00200000, - /// Dragging/moving - the flag is set for the moving block. - STATE_MOVING = 0x00400000, - /// Dragging/copying - the flag is set for the copying block. - STATE_COPYING = 0x00800000, - /// Element that is a drag source. - STATE_DRAG_SOURCE = 0x01000000, - /// Element is drop marker. - STATE_DROP_MARKER = 0x02000000, - - /// Close to `STATE_ACTIVE` but has wider life span. - /// - /// E.g. in `MOUSE_UP` it is still on; - /// so behavior can check it in `MOUSE_UP` to discover the `CLICK` condition. - STATE_PRESSED = 0x04000000, - - /// This element is out of flow. - STATE_POPUP = 0x08000000, - - /// The element or one of its containers has `dir=ltr` declared. - STATE_IS_LTR = 0x10000000, - /// The element or one of its containers has `dir=rtl` declared. - STATE_IS_RTL = 0x20000000, - - /// Element is ready (behavior has finished initialization). - STATE_READY = 0x40000000, +bitflags! { + #[repr(C)] + pub struct ELEMENT_STATE_BITS: u32 { + /// Zero state. + const STATE_NONE = 0x00000000; + + /// Element is a link. + /// + /// E.g. `` or `` elements. + const STATE_ACTIVE = 0x00000004; + /// Element is focused. + const STATE_FOCUS = 0x00000008; + + /// Element was visited. + /// + /// For example, a link that was clicked. + const STATE_VISITED = 0x00000010; + /// Current (hot) item. + const STATE_CURRENT = 0x00000020; + /// Element is checked (or selected). + const STATE_CHECKED = 0x00000040; + /// Element is disabled. + const STATE_DISABLED = 0x00000080; + /// Readonly input element. + const STATE_READONLY = 0x00000100; + + /// Expanded state - e.g. nodes in tree view. + /// + /// Mutually exclusive with `STATE_COLLAPSED`. + const STATE_EXPANDED = 0x00000200; + + /// Collapsed state - e.g. nodes in tree view. + /// + /// Mutually exclusive with `STATE_EXPANDED`. + const STATE_COLLAPSED = 0x00000400; + + /// One of fore/back images was requested but is not delivered. + const STATE_INCOMPLETE = 0x00000800; + /// Is animating currently. + const STATE_ANIMATING = 0x00001000; + /// Will accept focus. + const STATE_FOCUSABLE = 0x00002000; + + /// Anchor in selection (used with current in selects). + const STATE_ANCHOR = 0x00004000; + /// This is a synthetic element - i.e. don't emit it's head/tail. + const STATE_SYNTHETIC = 0x00008000; + /// A popup element is shown for this particular element. + const STATE_OWNS_POPUP = 0x00010000; + + /// Focus gained by tab traversal. + const STATE_TABFOCUS = 0x00020000; + + /// Element is empty. + /// + /// i.e. the element has no text content nor children nodes. + /// + /// If element has a behavior attached then the behavior is responsible for the value of this flag. + const STATE_EMPTY = 0x00040000; + + /// Busy or loading. + const STATE_BUSY = 0x00080000; + + /// Drag over the block that can accept it (so is a current drop target). + /// + /// Flag is set for the drop target block. + const STATE_DRAG_OVER = 0x00100000; + /// Active drop target. + const STATE_DROP_TARGET = 0x00200000; + /// Dragging/moving - the flag is set for the moving block. + const STATE_MOVING = 0x00400000; + /// Dragging/copying - the flag is set for the copying block. + const STATE_COPYING = 0x00800000; + /// Element that is a drag source. + const STATE_DRAG_SOURCE = 0x01000000; + /// Element is drop marker. + const STATE_DROP_MARKER = 0x02000000; + + /// Close to `STATE_ACTIVE` but has wider life span. + /// + /// E.g. in `MOUSE_UP` it is still on; + /// so behavior can check it in `MOUSE_UP` to discover the `CLICK` condition. + const STATE_PRESSED = 0x04000000; + + /// This element is out of flow. + const STATE_POPUP = 0x08000000; + + /// The element or one of its containers has `dir=ltr` declared. + const STATE_IS_LTR = 0x10000000; + /// The element or one of its containers has `dir=rtl` declared. + const STATE_IS_RTL = 0x20000000; + + /// Element is ready (behavior has finished initialization). + const STATE_READY = 0x40000000; + } } -/// Flags can be OR'ed. -impl ::std::ops::BitOr for ELEMENT_STATE_BITS { - type Output = ELEMENT_STATE_BITS; - fn bitor(self, rhs: Self::Output) -> Self::Output { - let rn = (self as UINT) | (rhs as UINT); - unsafe { ::std::mem::transmute(rn) } - } -} - -/// Flags can be AND'ed. -impl ::std::ops::BitAnd for ELEMENT_STATE_BITS { - type Output = ELEMENT_STATE_BITS; - fn bitand(self, rhs: Self::Output) -> Self::Output { - let rn = (self as UINT) & (rhs as UINT); - unsafe { ::std::mem::transmute(rn) } - } -} pub type SciterElementCallback = extern "system" fn (he: HELEMENT, param: LPVOID) -> BOOL; diff --git a/src/dom.rs b/src/dom.rs index ae15827..9c3045e 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -492,14 +492,14 @@ impl Element { pub fn get_state(&self) -> ELEMENT_STATE_BITS { let mut rv = 0u32; (_API.SciterGetElementState)(self.he, &mut rv as *mut _); - let state = unsafe { ::std::mem::transmute(rv) }; + let state = ELEMENT_STATE_BITS::from_bits_truncate(rv); return state; } /// Set UI state of the element with optional view update. pub fn set_state(&mut self, set: ELEMENT_STATE_BITS, clear: Option, update: bool) -> Result<()> { let clear = clear.unwrap_or(ELEMENT_STATE_BITS::STATE_NONE); - let ok = (_API.SciterSetElementState)(self.he, set as UINT, clear as UINT, update as BOOL); + let ok = (_API.SciterSetElementState)(self.he, set.bits() as UINT, clear.bits() as UINT, update as BOOL); ok_or!((), ok) } @@ -1181,56 +1181,55 @@ impl ::std::fmt::Display for Element { impl ::std::fmt::Debug for Element { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { if f.alternate() { - use ::std::mem; - - fn state_name(value: &ELEMENT_STATE_BITS) -> &'static str { - match *value { - ELEMENT_STATE_BITS::STATE_LINK => "link", - ELEMENT_STATE_BITS::STATE_HOVER => "hover", - ELEMENT_STATE_BITS::STATE_ACTIVE => "active", - ELEMENT_STATE_BITS::STATE_VISITED => "visited", - ELEMENT_STATE_BITS::STATE_FOCUS => "focus", - ELEMENT_STATE_BITS::STATE_POPUP => "popup", - ELEMENT_STATE_BITS::STATE_CURRENT => "current", - ELEMENT_STATE_BITS::STATE_CHECKED => "checked", - ELEMENT_STATE_BITS::STATE_EXPANDED => "expanded", - ELEMENT_STATE_BITS::STATE_COLLAPSED => "collapsed", - ELEMENT_STATE_BITS::STATE_DISABLED => "disabled", - ELEMENT_STATE_BITS::STATE_INCOMPLETE => "incomplete", - ELEMENT_STATE_BITS::STATE_BUSY => "busy", - ELEMENT_STATE_BITS::STATE_ANIMATING => "animating", - ELEMENT_STATE_BITS::STATE_FOCUSABLE => "", - ELEMENT_STATE_BITS::STATE_READONLY => "readonly", - ELEMENT_STATE_BITS::STATE_EMPTY => "empty", - ELEMENT_STATE_BITS::STATE_ANCHOR => "anchor", - ELEMENT_STATE_BITS::STATE_SYNTHETIC => "synthetic", - ELEMENT_STATE_BITS::STATE_OWNS_POPUP => "owns_popup", - ELEMENT_STATE_BITS::STATE_TABFOCUS => "tabfocus", - ELEMENT_STATE_BITS::STATE_IS_RTL => "is_rtl", - ELEMENT_STATE_BITS::STATE_IS_LTR => "is_ltr", - ELEMENT_STATE_BITS::STATE_DRAG_OVER => "drag_over", - ELEMENT_STATE_BITS::STATE_DROP_TARGET => "drop_target", - ELEMENT_STATE_BITS::STATE_MOVING => "moving", - ELEMENT_STATE_BITS::STATE_COPYING => "copying", - ELEMENT_STATE_BITS::STATE_DRAG_SOURCE => "drag_source", - ELEMENT_STATE_BITS::STATE_DROP_MARKER => "drop_marker", - - ELEMENT_STATE_BITS::STATE_READY => "", - ELEMENT_STATE_BITS::STATE_PRESSED => "pressed", - - ELEMENT_STATE_BITS::STATE_NONE => "", + + fn state_name(bits: u32) -> &'static str { + match bits { + 0x00000001 => "link", + 0x00000002 => "hover", + 0x00000004 => "active", + 0x00000010 => "visited", + 0x00000008 => "focus", + 0x08000000 => "popup", + 0x00000020 => "current", + 0x00000040 => "checked", + 0x00000200 => "expanded", + 0x00000400 => "collapsed", + 0x00000080 => "disabled", + 0x00000800 => "incomplete", + 0x00080000 => "busy", + 0x00001000 => "animating", + 0x00002000 => "", + 0x00000100 => "readonly", + 0x00040000 => "empty", + 0x00004000 => "anchor", + 0x00008000 => "synthetic", + 0x00010000 => "owns_popup", + 0x00020000 => "tabfocus", + 0x20000000 => "is_rtl", + 0x10000000 => "is_ltr", + 0x00100000 => "drag_over", + 0x00200000 => "drop_target", + 0x00400000 => "moving", + 0x00800000 => "copying", + 0x01000000 => "drag_source", + 0x02000000 => "drop_marker", + + 0x40000000 => "", + 0x04000000 => "pressed", + + 0x00000000 => "", + _ => "", } } // "tag#id.class:state1:state2..." - let state = self.get_state() as u32; + let state = self.get_state().bits(); write!(f, "{{{}", self)?; for i in 0..31 { - let bit = state & (1 << i); - if bit != 0 { - let state_bit: ELEMENT_STATE_BITS = unsafe { mem::transmute(bit) }; - let name = state_name(&state_bit); + let bit = 1 << i; + if (state & bit) != 0 { + let name = state_name(bit); if !name.is_empty() { write!(f, ":{}", name)?; } diff --git a/src/eventhandler.rs b/src/eventhandler.rs index 935624b..76a20cb 100644 --- a/src/eventhandler.rs +++ b/src/eventhandler.rs @@ -17,7 +17,7 @@ pub(crate) struct BoxedHandler { } fn is_detach_event(evtg: UINT, params: LPVOID) -> bool { - let evtg : EVENT_GROUPS = unsafe { ::std::mem::transmute(evtg) }; + let evtg : EVENT_GROUPS = EVENT_GROUPS::from_bits_truncate(evtg); if evtg == EVENT_GROUPS::HANDLE_INITIALIZATION { assert!(!params.is_null()); let scnm = params as *const INITIALIZATION_EVENTS; @@ -94,14 +94,14 @@ pub(crate) extern "system" fn _event_handler_proc(tag: LPVOID, fn process_events(me: &mut dyn EventHandler, he: HELEMENT, evtg: UINT, params: LPVOID) -> BOOL { - let evtg : EVENT_GROUPS = unsafe { ::std::mem::transmute(evtg) }; + let evtg : EVENT_GROUPS = EVENT_GROUPS::from_bits_truncate(evtg); if he.is_null() && evtg != EVENT_GROUPS::SUBSCRIPTIONS_REQUEST && evtg != EVENT_GROUPS::HANDLE_BEHAVIOR_EVENT && evtg != EVENT_GROUPS::HANDLE_INITIALIZATION && evtg != EVENT_GROUPS::HANDLE_SOM { - eprintln!("[sciter] warning! null element for {:04X}", evtg as u32); + eprintln!("[sciter] warning! null element for {:04X}", evtg.bits()); } let result = match evtg { @@ -312,7 +312,7 @@ fn process_events(me: &mut dyn EventHandler, he: HELEMENT, evtg: UINT, params: L // unknown `EVENT_GROUPS` notification _ => { - eprintln!("[sciter] warning! unknown event group {:04X}", evtg as u32); + eprintln!("[sciter] warning! unknown event group {:04X}", evtg.bits()); false }, }; diff --git a/src/host.rs b/src/host.rs index 370caa6..7fadc3e 100644 --- a/src/host.rs +++ b/src/host.rs @@ -213,7 +213,7 @@ impl Host { let func = _event_handler_window_proc::; let flags = dom::event::default_events(); - (_API.SciterWindowAttachEventHandler)(hwnd, func, ptr as LPVOID, flags as UINT); + (_API.SciterWindowAttachEventHandler)(hwnd, func, ptr as LPVOID, flags.bits() as UINT); } /// Set callback for Sciter engine events.