mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-23 21:21:05 +03:00
move rust-sciter in
This commit is contained in:
14
libs/rust-sciter/src/capi/mod.rs
Normal file
14
libs/rust-sciter/src/capi/mod.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
/*! C interface headers */
|
||||
|
||||
pub mod scapi;
|
||||
pub mod scbehavior;
|
||||
pub mod scdef;
|
||||
pub mod scdom;
|
||||
pub mod scgraphics;
|
||||
pub mod screquest;
|
||||
pub mod sctiscript;
|
||||
pub mod sctypes;
|
||||
pub mod scvalue;
|
||||
pub mod schandler;
|
||||
pub mod scmsg;
|
||||
pub mod scom;
|
||||
279
libs/rust-sciter/src/capi/scapi.rs
Normal file
279
libs/rust-sciter/src/capi/scapi.rs
Normal file
@@ -0,0 +1,279 @@
|
||||
//! Sciter C API interface.
|
||||
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::*;
|
||||
use capi::scdom::*;
|
||||
use capi::scvalue::*;
|
||||
use capi::sctiscript::{HVM, tiscript_value, tiscript_native_interface};
|
||||
use capi::scbehavior::*;
|
||||
use capi::scgraphics::SciterGraphicsAPI;
|
||||
use capi::screquest::{SciterRequestAPI, HREQUEST, REQUEST_PARAM};
|
||||
use capi::scmsg::{SCITER_X_MSG};
|
||||
use capi::scom::som_asset_t;
|
||||
|
||||
|
||||
/// Sciter API functions.
|
||||
#[repr(C)]
|
||||
#[allow(missing_docs)]
|
||||
#[doc(hidden)]
|
||||
pub struct ISciterAPI
|
||||
{
|
||||
pub version: UINT,
|
||||
|
||||
pub SciterClassName: extern "system" fn () -> LPCWSTR,
|
||||
pub SciterVersion: extern "system" fn (major: BOOL) -> UINT,
|
||||
|
||||
pub SciterDataReady: extern "system" fn (hwnd: HWINDOW, uri: LPCWSTR, data: LPCBYTE, dataLength: UINT) -> BOOL,
|
||||
pub SciterDataReadyAsync: extern "system" fn (hwnd: HWINDOW, uri: LPCWSTR, data: LPCBYTE, dataLength: UINT, requestId: HREQUEST) -> BOOL,
|
||||
|
||||
// #ifdef WINDOWS
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterProc: extern "system" fn (hwnd: HWINDOW, msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterProcND: extern "system" fn (hwnd: HWINDOW, msg: UINT, wParam: WPARAM, lParam: LPARAM, pbHandled: * mut BOOL) -> LRESULT,
|
||||
// #endif
|
||||
|
||||
pub SciterLoadFile: extern "system" fn (hWndSciter: HWINDOW, filename: LPCWSTR) -> BOOL,
|
||||
|
||||
pub SciterLoadHtml: extern "system" fn (hWndSciter: HWINDOW, html: LPCBYTE, htmlSize: UINT, baseUrl: LPCWSTR) -> BOOL,
|
||||
pub SciterSetCallback: extern "system" fn (hWndSciter: HWINDOW, cb: SciterHostCallback, cbParam: LPVOID) -> VOID,
|
||||
pub SciterSetMasterCSS: extern "system" fn (utf8: LPCBYTE, numBytes: UINT) -> BOOL,
|
||||
pub SciterAppendMasterCSS: extern "system" fn (utf8: LPCBYTE, numBytes: UINT) -> BOOL,
|
||||
pub SciterSetCSS: extern "system" fn (hWndSciter: HWINDOW, utf8: LPCBYTE, numBytes: UINT, baseUrl: LPCWSTR, mediaType: LPCWSTR) -> BOOL,
|
||||
pub SciterSetMediaType: extern "system" fn (hWndSciter: HWINDOW, mediaType: LPCWSTR) -> BOOL,
|
||||
pub SciterSetMediaVars: extern "system" fn (hWndSciter: HWINDOW, mediaVars: * const VALUE) -> BOOL,
|
||||
pub SciterGetMinWidth: extern "system" fn (hWndSciter: HWINDOW) -> UINT,
|
||||
pub SciterGetMinHeight: extern "system" fn (hWndSciter: HWINDOW, width: UINT) -> UINT,
|
||||
pub SciterCall: extern "system" fn (hWnd: HWINDOW, functionName: LPCSTR, argc: UINT, argv: * const VALUE, retval: * mut VALUE) -> BOOL,
|
||||
pub SciterEval: extern "system" fn (hwnd: HWINDOW, script: LPCWSTR, scriptLength: UINT, pretval: * mut VALUE) -> BOOL,
|
||||
pub SciterUpdateWindow: extern "system" fn (hwnd: HWINDOW) -> VOID,
|
||||
|
||||
// #ifdef WINDOWS
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterTranslateMessage: extern "system" fn (lpMsg: * mut MSG) -> BOOL,
|
||||
// #endif
|
||||
|
||||
pub SciterSetOption: extern "system" fn (hWnd: HWINDOW, option: SCITER_RT_OPTIONS, value: UINT_PTR) -> BOOL,
|
||||
pub SciterGetPPI: extern "system" fn (hWndSciter: HWINDOW, px: * mut UINT, py: * mut UINT) -> VOID,
|
||||
pub SciterGetViewExpando: extern "system" fn (hwnd: HWINDOW, pval: * mut VALUE) -> BOOL,
|
||||
|
||||
// #ifdef WINDOWS
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterRenderD2D: extern "system" fn (hWndSciter: HWINDOW, prt: * mut ID2D1RenderTarget) -> BOOL,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterD2DFactory: extern "system" fn (ppf: * mut* mut ID2D1Factory) -> BOOL,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterDWFactory: extern "system" fn (ppf: * mut* mut IDWriteFactory) -> BOOL,
|
||||
// #endif
|
||||
|
||||
pub SciterGraphicsCaps: extern "system" fn (pcaps: LPUINT) -> BOOL,
|
||||
pub SciterSetHomeURL: extern "system" fn (hWndSciter: HWINDOW, baseUrl: LPCWSTR) -> BOOL,
|
||||
|
||||
// #if defined(OSX)
|
||||
#[cfg(all(target_os="macos", not(feature = "windowless")))]
|
||||
pub SciterCreateNSView: extern "system" fn (frame: LPRECT) -> HWINDOW, // returns NSView*
|
||||
// #endif
|
||||
|
||||
// #if defined(LINUX)
|
||||
#[cfg(all(target_os="linux", not(feature = "windowless")))]
|
||||
pub SciterCreateWidget: extern "system" fn (frame: LPRECT) -> HWINDOW, // returns GtkWidget
|
||||
// #endif
|
||||
|
||||
#[cfg(not(feature = "windowless"))]
|
||||
pub SciterCreateWindow: extern "system" fn (creationFlags: UINT, frame: LPCRECT, delegate: * const SciterWindowDelegate, delegateParam: LPVOID, parent: HWINDOW) -> HWINDOW,
|
||||
|
||||
pub SciterSetupDebugOutput: extern "system" fn (hwndOrNull: HWINDOW, param: LPVOID, pfOutput: DEBUG_OUTPUT_PROC),
|
||||
|
||||
//|
|
||||
//| DOM Element API
|
||||
//|
|
||||
pub Sciter_UseElement: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub Sciter_UnuseElement: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetRootElement: extern "system" fn (hwnd: HWINDOW, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetFocusElement: extern "system" fn (hwnd: HWINDOW, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterFindElement: extern "system" fn (hwnd: HWINDOW, pt: POINT, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetChildrenCount: extern "system" fn (he: HELEMENT, count: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetNthChild: extern "system" fn (he: HELEMENT, n: UINT, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetParentElement: extern "system" fn (he: HELEMENT, p_parent_he: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementHtmlCB: extern "system" fn (he: HELEMENT, outer: BOOL, rcv: LPCBYTE_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterGetElementTextCB: extern "system" fn (he: HELEMENT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSetElementText: extern "system" fn (he: HELEMENT, utf16: LPCWSTR, length: UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetAttributeCount: extern "system" fn (he: HELEMENT, p_count: LPUINT) -> SCDOM_RESULT,
|
||||
pub SciterGetNthAttributeNameCB: extern "system" fn (he: HELEMENT, n: UINT, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterGetNthAttributeValueCB: extern "system" fn (he: HELEMENT, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterGetAttributeByNameCB: extern "system" fn (he: HELEMENT, name: LPCSTR, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSetAttributeByName: extern "system" fn (he: HELEMENT, name: LPCSTR, value: LPCWSTR) -> SCDOM_RESULT,
|
||||
pub SciterClearAttributes: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementIndex: extern "system" fn (he: HELEMENT, p_index: LPUINT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementType: extern "system" fn (he: HELEMENT, p_type: * mut LPCSTR) -> SCDOM_RESULT,
|
||||
pub SciterGetElementTypeCB: extern "system" fn (he: HELEMENT, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterGetStyleAttributeCB: extern "system" fn (he: HELEMENT, name: LPCSTR, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSetStyleAttribute: extern "system" fn (he: HELEMENT, name: LPCSTR, value: LPCWSTR) -> SCDOM_RESULT,
|
||||
pub SciterGetElementLocation: extern "system" fn (he: HELEMENT, p_location: LPRECT, areas: UINT /*ELEMENT_AREAS*/) -> SCDOM_RESULT,
|
||||
pub SciterScrollToView: extern "system" fn (he: HELEMENT, SciterScrollFlags: UINT) -> SCDOM_RESULT,
|
||||
pub SciterUpdateElement: extern "system" fn (he: HELEMENT, andForceRender: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterRefreshElementArea: extern "system" fn (he: HELEMENT, rc: RECT) -> SCDOM_RESULT,
|
||||
pub SciterSetCapture: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterReleaseCapture: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementHwnd: extern "system" fn (he: HELEMENT, p_hwnd: * mut HWINDOW, rootWindow: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterCombineURL: extern "system" fn (he: HELEMENT, szUrlBuffer: LPWSTR, UrlBufferSize: UINT) -> SCDOM_RESULT,
|
||||
pub SciterSelectElements: extern "system" fn (he: HELEMENT, CSS_selectors: LPCSTR, callback: SciterElementCallback, param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSelectElementsW: extern "system" fn (he: HELEMENT, CSS_selectors: LPCWSTR, callback: SciterElementCallback, param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSelectParent: extern "system" fn (he: HELEMENT, selector: LPCSTR, depth: UINT, heFound: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterSelectParentW: extern "system" fn (he: HELEMENT, selector: LPCWSTR, depth: UINT, heFound: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterSetElementHtml: extern "system" fn (he: HELEMENT, html: * const BYTE, htmlLength: UINT, how: UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementUID: extern "system" fn (he: HELEMENT, puid: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementByUID: extern "system" fn (hwnd: HWINDOW, uid: UINT, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterShowPopup: extern "system" fn (hePopup: HELEMENT, heAnchor: HELEMENT, placement: UINT) -> SCDOM_RESULT,
|
||||
pub SciterShowPopupAt: extern "system" fn (hePopup: HELEMENT, pos: POINT, placement: UINT) -> SCDOM_RESULT,
|
||||
pub SciterHidePopup: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementState: extern "system" fn (he: HELEMENT, pstateBits: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterSetElementState: extern "system" fn (he: HELEMENT, stateBitsToSet: UINT, stateBitsToClear: UINT, updateView: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterCreateElement: extern "system" fn (tagname: LPCSTR, textOrNull: LPCWSTR, /*out*/ phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterCloneElement: extern "system" fn (he: HELEMENT, /*out*/ phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterInsertElement: extern "system" fn (he: HELEMENT, hparent: HELEMENT, index: UINT) -> SCDOM_RESULT,
|
||||
pub SciterDetachElement: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterDeleteElement: extern "system" fn (he: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterSetTimer: extern "system" fn (he: HELEMENT, milliseconds: UINT, timer_id: UINT_PTR) -> SCDOM_RESULT,
|
||||
pub SciterDetachEventHandler: extern "system" fn (he: HELEMENT, pep: ElementEventProc, tag: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterAttachEventHandler: extern "system" fn (he: HELEMENT, pep: ElementEventProc, tag: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterWindowAttachEventHandler: extern "system" fn (hwndLayout: HWINDOW, pep: ElementEventProc, tag: LPVOID, subscription: UINT) -> SCDOM_RESULT,
|
||||
pub SciterWindowDetachEventHandler: extern "system" fn (hwndLayout: HWINDOW, pep: ElementEventProc, tag: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSendEvent: extern "system" fn (he: HELEMENT, appEventCode: UINT, heSource: HELEMENT, reason: UINT_PTR, /*out*/ handled: * mut BOOL) -> SCDOM_RESULT,
|
||||
pub SciterPostEvent: extern "system" fn (he: HELEMENT, appEventCode: UINT, heSource: HELEMENT, reason: UINT_PTR) -> SCDOM_RESULT,
|
||||
pub SciterCallBehaviorMethod: extern "system" fn (he: HELEMENT, params: * const METHOD_PARAMS) -> SCDOM_RESULT,
|
||||
pub SciterRequestElementData: extern "system" fn (he: HELEMENT, url: LPCWSTR, dataType: UINT, initiator: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterHttpRequest: extern "system" fn (he: HELEMENT, url: LPCWSTR, dataType: UINT, requestType: UINT, requestParams: * const REQUEST_PARAM, nParams: UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetScrollInfo: extern "system" fn (he: HELEMENT, scrollPos: LPPOINT, viewRect: LPRECT, contentSize: LPSIZE) -> SCDOM_RESULT,
|
||||
pub SciterSetScrollPos: extern "system" fn (he: HELEMENT, scrollPos: POINT, smooth: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterGetElementIntrinsicWidths: extern "system" fn (he: HELEMENT, pMinWidth: * mut INT, pMaxWidth: * mut INT) -> SCDOM_RESULT,
|
||||
pub SciterGetElementIntrinsicHeight: extern "system" fn (he: HELEMENT, forWidth: INT, pHeight: * mut INT) -> SCDOM_RESULT,
|
||||
pub SciterIsElementVisible: extern "system" fn (he: HELEMENT, pVisible: * mut BOOL) -> SCDOM_RESULT,
|
||||
pub SciterIsElementEnabled: extern "system" fn (he: HELEMENT, pEnabled: * mut BOOL) -> SCDOM_RESULT,
|
||||
pub SciterSortElements: extern "system" fn (he: HELEMENT, firstIndex: UINT, lastIndex: UINT, cmpFunc: * mut ELEMENT_COMPARATOR, cmpFuncParam: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterSwapElements: extern "system" fn (he1: HELEMENT, he2: HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterTraverseUIEvent: extern "system" fn (evt: UINT, eventCtlStruct: LPVOID, bOutProcessed: * mut BOOL) -> SCDOM_RESULT,
|
||||
pub SciterCallScriptingMethod: extern "system" fn (he: HELEMENT, name: LPCSTR, argv: * const VALUE, argc: UINT, retval: * mut VALUE) -> SCDOM_RESULT,
|
||||
pub SciterCallScriptingFunction: extern "system" fn (he: HELEMENT, name: LPCSTR, argv: * const VALUE, argc: UINT, retval: * mut VALUE) -> SCDOM_RESULT,
|
||||
pub SciterEvalElementScript: extern "system" fn (he: HELEMENT, script: LPCWSTR, scriptLength: UINT, retval: * mut VALUE) -> SCDOM_RESULT,
|
||||
pub SciterAttachHwndToElement: extern "system" fn (he: HELEMENT, hwnd: HWINDOW) -> SCDOM_RESULT,
|
||||
pub SciterControlGetType: extern "system" fn (he: HELEMENT, /*CTL_TYPE*/ pType: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterGetValue: extern "system" fn (he: HELEMENT, pval: * mut VALUE) -> SCDOM_RESULT,
|
||||
pub SciterSetValue: extern "system" fn (he: HELEMENT, pval: * const VALUE) -> SCDOM_RESULT,
|
||||
pub SciterGetExpando: extern "system" fn (he: HELEMENT, pval: * mut VALUE, forceCreation: BOOL) -> SCDOM_RESULT,
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub SciterGetObject: extern "system" fn (he: HELEMENT, pval: * mut tiscript_value, forceCreation: BOOL) -> SCDOM_RESULT,
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub SciterGetElementNamespace: extern "system" fn (he: HELEMENT, pval: * mut tiscript_value) -> SCDOM_RESULT,
|
||||
|
||||
pub SciterGetHighlightedElement: extern "system" fn (hwnd: HWINDOW, phe: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterSetHighlightedElement: extern "system" fn (hwnd: HWINDOW, he: HELEMENT) -> SCDOM_RESULT,
|
||||
//|
|
||||
//| DOM Node API
|
||||
//|
|
||||
pub SciterNodeAddRef: extern "system" fn (hn: HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeRelease: extern "system" fn (hn: HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeCastFromElement: extern "system" fn (he: HELEMENT, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeCastToElement: extern "system" fn (hn: HNODE, he: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterNodeFirstChild: extern "system" fn (hn: HNODE, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeLastChild: extern "system" fn (hn: HNODE, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeNextSibling: extern "system" fn (hn: HNODE, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodePrevSibling: extern "system" fn (hn: HNODE, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeParent: extern "system" fn (hnode: HNODE, pheParent: * mut HELEMENT) -> SCDOM_RESULT,
|
||||
pub SciterNodeNthChild: extern "system" fn (hnode: HNODE, n: UINT, phn: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeChildrenCount: extern "system" fn (hnode: HNODE, pn: * mut UINT) -> SCDOM_RESULT,
|
||||
pub SciterNodeType: extern "system" fn (hnode: HNODE, pNodeType: * mut UINT /*NODE_TYPE*/) -> SCDOM_RESULT,
|
||||
pub SciterNodeGetText: extern "system" fn (hnode: HNODE, rcv: * mut LPCWSTR_RECEIVER, rcv_param: LPVOID) -> SCDOM_RESULT,
|
||||
pub SciterNodeSetText: extern "system" fn (hnode: HNODE, text: LPCWSTR, textLength: UINT) -> SCDOM_RESULT,
|
||||
pub SciterNodeInsert: extern "system" fn (hnode: HNODE, how: UINT /*NODE_INS_TARGET*/, what: HNODE) -> SCDOM_RESULT,
|
||||
pub SciterNodeRemove: extern "system" fn (hnode: HNODE, finalize: BOOL) -> SCDOM_RESULT,
|
||||
pub SciterCreateTextNode: extern "system" fn (text: LPCWSTR, textLength: UINT, phnode: * mut HNODE) -> SCDOM_RESULT,
|
||||
pub SciterCreateCommentNode: extern "system" fn (text: LPCWSTR, textLength: UINT, phnode: * mut HNODE) -> SCDOM_RESULT,
|
||||
//|
|
||||
//| Value API
|
||||
//|
|
||||
pub ValueInit: extern "system" fn (pval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueClear: extern "system" fn (pval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueCompare: extern "system" fn (pval1: * const VALUE, pval2: * const VALUE) -> VALUE_RESULT,
|
||||
pub ValueCopy: extern "system" fn (pdst: * mut VALUE, psrc: * const VALUE) -> VALUE_RESULT,
|
||||
pub ValueIsolate: extern "system" fn (pdst: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueType: extern "system" fn (pval: * const VALUE, pType: * mut UINT, pUnits: * mut UINT) -> VALUE_RESULT,
|
||||
pub ValueStringData: extern "system" fn (pval: * const VALUE, pChars: * mut LPCWSTR, pNumChars: * mut UINT) -> VALUE_RESULT,
|
||||
pub ValueStringDataSet: extern "system" fn (pval: * mut VALUE, chars: LPCWSTR, numChars: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueIntData: extern "system" fn (pval: * const VALUE, pData: * mut INT) -> VALUE_RESULT,
|
||||
pub ValueIntDataSet: extern "system" fn (pval: * mut VALUE, data: INT, vtype: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueInt64Data: extern "system" fn (pval: * const VALUE, pData: * mut INT64) -> VALUE_RESULT,
|
||||
pub ValueInt64DataSet: extern "system" fn (pval: * mut VALUE, data: INT64, vtype: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueFloatData: extern "system" fn (pval: * const VALUE, pData: * mut FLOAT_VALUE) -> VALUE_RESULT,
|
||||
pub ValueFloatDataSet: extern "system" fn (pval: * mut VALUE, data: FLOAT_VALUE, vtype: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueBinaryData: extern "system" fn (pval: * const VALUE, pBytes: * mut LPCBYTE, pnBytes: * mut UINT) -> VALUE_RESULT,
|
||||
pub ValueBinaryDataSet: extern "system" fn (pval: * mut VALUE, pBytes: LPCBYTE, nBytes: UINT, vtype: UINT, units: UINT) -> VALUE_RESULT,
|
||||
pub ValueElementsCount: extern "system" fn (pval: * const VALUE, pn: * mut INT) -> VALUE_RESULT,
|
||||
pub ValueNthElementValue: extern "system" fn (pval: * const VALUE, n: INT, pretval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueNthElementValueSet: extern "system" fn (pval: * mut VALUE, n: INT, pval_to_set: * const VALUE) -> VALUE_RESULT,
|
||||
pub ValueNthElementKey: extern "system" fn (pval: * const VALUE, n: INT, pretval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueEnumElements: extern "system" fn (pval: * const VALUE, penum: KeyValueCallback, param: LPVOID) -> VALUE_RESULT,
|
||||
pub ValueSetValueToKey: extern "system" fn (pval: * mut VALUE, pkey: * const VALUE, pval_to_set: * const VALUE) -> VALUE_RESULT,
|
||||
pub ValueGetValueOfKey: extern "system" fn (pval: * const VALUE, pkey: * const VALUE, pretval: * mut VALUE) -> VALUE_RESULT,
|
||||
pub ValueToString: extern "system" fn (pval: * mut VALUE, how: VALUE_STRING_CVT_TYPE) -> VALUE_RESULT,
|
||||
pub ValueFromString: extern "system" fn (pval: * mut VALUE, str: LPCWSTR, strLength: UINT, how: VALUE_STRING_CVT_TYPE) -> UINT,
|
||||
pub ValueInvoke: extern "system" fn (pval: * const VALUE, pthis: * mut VALUE, argc: UINT, argv: * const VALUE, pretval: * mut VALUE, url: LPCWSTR) -> VALUE_RESULT,
|
||||
pub ValueNativeFunctorSet: extern "system" fn (pval: * mut VALUE, pinvoke: NATIVE_FUNCTOR_INVOKE, prelease: NATIVE_FUNCTOR_RELEASE, tag: LPVOID) -> VALUE_RESULT,
|
||||
pub ValueIsNativeFunctor: extern "system" fn (pval: * const VALUE) -> BOOL,
|
||||
|
||||
// tiscript VM API
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub TIScriptAPI: extern "system" fn () -> * mut tiscript_native_interface,
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub SciterGetVM: extern "system" fn (hwnd: HWINDOW) -> HVM,
|
||||
|
||||
// since 3.1.0.12
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub Sciter_v2V: extern "system" fn (vm: HVM, script_value: tiscript_value, value: * mut VALUE, isolate: BOOL) -> BOOL,
|
||||
|
||||
#[deprecated(since="Sciter 4.4.3.24", note="TIScript native API is gone, use SOM instead.")]
|
||||
pub Sciter_V2v: extern "system" fn (vm: HVM, valuev: * const VALUE, script_value: * mut tiscript_value) -> BOOL,
|
||||
|
||||
// since 3.1.0.18
|
||||
pub SciterOpenArchive: extern "system" fn (archiveData: LPCBYTE, archiveDataLength: UINT) -> HSARCHIVE,
|
||||
pub SciterGetArchiveItem: extern "system" fn (harc: HSARCHIVE, path: LPCWSTR, pdata: * mut LPCBYTE, pdataLength: * mut UINT) -> BOOL,
|
||||
pub SciterCloseArchive: extern "system" fn (harc: HSARCHIVE) -> BOOL,
|
||||
|
||||
// since 3.2.0.0
|
||||
pub SciterFireEvent: extern "system" fn (evt: * const BEHAVIOR_EVENT_PARAMS, post: BOOL, handled: * mut BOOL) -> SCDOM_RESULT,
|
||||
|
||||
pub SciterGetCallbackParam: extern "system" fn (hwnd: HWINDOW) -> LPVOID,
|
||||
pub SciterPostCallback: extern "system" fn (hwnd: HWINDOW, wparam: UINT_PTR, lparam: UINT_PTR, timeoutms: UINT) -> UINT_PTR,
|
||||
|
||||
// since 3.3.1.0
|
||||
pub GetSciterGraphicsAPI: extern "system" fn () -> * const SciterGraphicsAPI,
|
||||
|
||||
// since 3.3.1.6
|
||||
pub GetSciterRequestAPI: extern "system" fn () -> * const SciterRequestAPI,
|
||||
|
||||
// #ifdef WINDOWS
|
||||
// since 3.3.1.4
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterCreateOnDirectXWindow: extern "system" fn (hwnd: HWINDOW, pSwapChain: * mut IDXGISwapChain) -> BOOL,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterRenderOnDirectXWindow: extern "system" fn (hwnd: HWINDOW, elementToRenderOrNull: HELEMENT, frontLayer: BOOL) -> BOOL,
|
||||
#[cfg(all(windows, not(feature = "windowless")))]
|
||||
pub SciterRenderOnDirectXTexture: extern "system" fn (hwnd: HWINDOW, elementToRenderOrNull: HELEMENT, surface: * mut IDXGISurface) -> BOOL,
|
||||
// #endif
|
||||
|
||||
// since 4.0.0.0
|
||||
pub SciterProcX: extern "system" fn(hwnd: HWINDOW, msg: * const SCITER_X_MSG) -> BOOL,
|
||||
|
||||
// since 4.4.2.14
|
||||
pub SciterAtomValue: extern "system" fn(name: LPCSTR) -> UINT64,
|
||||
pub SciterAtomNameCB: extern "system" fn(atomv: UINT64, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> BOOL,
|
||||
|
||||
// since 4.4.2.16
|
||||
pub SciterSetGlobalAsset: extern "system" fn(pass: *mut som_asset_t) -> BOOL,
|
||||
}
|
||||
0
libs/rust-sciter/src/capi/scarchive.rs
Normal file
0
libs/rust-sciter/src/capi/scarchive.rs
Normal file
543
libs/rust-sciter/src/capi/scbehavior.rs
Normal file
543
libs/rust-sciter/src/capi/scbehavior.rs
Normal file
@@ -0,0 +1,543 @@
|
||||
//! C interface for behaviors support (a.k.a windowless controls).
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scdom::*;
|
||||
use capi::scvalue::{VALUE};
|
||||
use capi::scgraphics::{HGFX};
|
||||
use capi::scom::{som_asset_t, som_passport_t};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct BEHAVIOR_EVENT_PARAMS
|
||||
{
|
||||
/// Behavior event code. See [`BEHAVIOR_EVENTS`](enum.BEHAVIOR_EVENTS.html).
|
||||
pub cmd: UINT,
|
||||
|
||||
/// Target element handler.
|
||||
pub heTarget: HELEMENT,
|
||||
|
||||
/// Source element.
|
||||
pub he: HELEMENT,
|
||||
|
||||
/// UI action causing change.
|
||||
pub reason: UINT_PTR,
|
||||
|
||||
/// Auxiliary data accompanied with the event.
|
||||
pub data: VALUE,
|
||||
|
||||
/// Name of the custom event (when `cmd` is [`BEHAVIOR_EVENTS::CUSTOM`](enum.BEHAVIOR_EVENTS.html#variant.CUSTOM)).
|
||||
/// Since 4.2.8.
|
||||
pub name: LPCWSTR,
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum INITIALIZATION_EVENTS
|
||||
{
|
||||
BEHAVIOR_DETACH = 0,
|
||||
BEHAVIOR_ATTACH = 1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct INITIALIZATION_PARAMS
|
||||
{
|
||||
pub cmd: INITIALIZATION_EVENTS,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum SOM_EVENTS
|
||||
{
|
||||
SOM_GET_PASSPORT = 0,
|
||||
SOM_GET_ASSET = 1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union SOM_PARAMS_DATA
|
||||
{
|
||||
pub asset: *const som_asset_t,
|
||||
pub passport: *const som_passport_t,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SOM_PARAMS
|
||||
{
|
||||
pub cmd: SOM_EVENTS,
|
||||
pub result: SOM_PARAMS_DATA,
|
||||
}
|
||||
|
||||
/// Identifiers of methods currently supported by intrinsic behaviors.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub enum BEHAVIOR_METHOD_IDENTIFIERS {
|
||||
/// Raise a click event.
|
||||
DO_CLICK = 1,
|
||||
|
||||
/// `IS_EMPTY_PARAMS::is_empty` reflects the `:empty` state of the element.
|
||||
IS_EMPTY = 0xFC,
|
||||
|
||||
/// `VALUE_PARAMS`
|
||||
GET_VALUE = 0xFD,
|
||||
/// `VALUE_PARAMS`
|
||||
SET_VALUE = 0xFE,
|
||||
|
||||
/// User method identifier used in custom behaviors.
|
||||
///
|
||||
/// All custom event codes shall be greater than this number.
|
||||
/// All codes below this will be used solely by application - Sciter will not intrepret it
|
||||
/// and will do just dispatching. To send event notifications with these codes use
|
||||
/// `SciterCallBehaviorMethod` API.
|
||||
FIRST_APPLICATION_METHOD_ID = 0x100,
|
||||
}
|
||||
|
||||
/// Method arguments used in `SciterCallBehaviorMethod()` or `HANDLE_METHOD_CALL`.
|
||||
#[repr(C)]
|
||||
pub struct METHOD_PARAMS {
|
||||
/// [`BEHAVIOR_METHOD_IDENTIFIERS`](enum.BEHAVIOR_METHOD_IDENTIFIERS.html) or user identifiers.
|
||||
pub method: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct IS_EMPTY_PARAMS {
|
||||
pub method: UINT,
|
||||
pub is_empty: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct VALUE_PARAMS {
|
||||
pub method: UINT,
|
||||
pub value: VALUE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SCRIPTING_METHOD_PARAMS
|
||||
{
|
||||
pub name: LPCSTR,
|
||||
pub argv: *const VALUE,
|
||||
pub argc: UINT,
|
||||
pub result: VALUE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct TIMER_PARAMS
|
||||
{
|
||||
pub timerId: UINT_PTR,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DRAW_PARAMS {
|
||||
/// Element layer to draw.
|
||||
pub layer: DRAW_EVENTS,
|
||||
|
||||
/// Graphics context.
|
||||
pub gfx: HGFX,
|
||||
|
||||
/// Element area.
|
||||
pub area: RECT,
|
||||
|
||||
/// Zero at the moment.
|
||||
pub reserved: UINT,
|
||||
}
|
||||
|
||||
/// Layer to draw.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DRAW_EVENTS {
|
||||
DRAW_BACKGROUND = 0,
|
||||
DRAW_CONTENT,
|
||||
DRAW_FOREGROUND,
|
||||
/// Note: since 4.2.3.
|
||||
DRAW_OUTLINE,
|
||||
}
|
||||
|
||||
|
||||
/// 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,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Event propagation schema.
|
||||
pub enum PHASE_MASK
|
||||
{
|
||||
/// Bubbling phase – direction: from a child element to all its containers.
|
||||
BUBBLING = 0,
|
||||
/// Sinking phase – direction: from containers to target child element.
|
||||
SINKING = 0x0_8000,
|
||||
/// Bubbling event consumed by some child.
|
||||
BUBBLING_HANDLED= 0x1_0000,
|
||||
/// Sinking event consumed by some child.
|
||||
SINKING_HANDLED = 0x1_8000,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Mouse buttons.
|
||||
pub enum MOUSE_BUTTONS
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
/// Left button.
|
||||
MAIN = 1,
|
||||
/// Right button.
|
||||
PROP = 2,
|
||||
/// Middle button.
|
||||
MIDDLE = 3,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Keyboard modifier buttons state.
|
||||
pub enum KEYBOARD_STATES
|
||||
{
|
||||
CONTROL_KEY_PRESSED = 0x01,
|
||||
SHIFT_KEY_PRESSED = 0x02,
|
||||
ALT_KEY_PRESSED = 0x04,
|
||||
}
|
||||
|
||||
impl std::convert::From<u32> for KEYBOARD_STATES {
|
||||
fn from(u: u32) -> Self {
|
||||
unsafe { std::mem::transmute(u) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Keyboard input events.
|
||||
pub enum KEY_EVENTS
|
||||
{
|
||||
KEY_DOWN = 0,
|
||||
KEY_UP,
|
||||
KEY_CHAR,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Mouse events.
|
||||
pub enum MOUSE_EVENTS
|
||||
{
|
||||
MOUSE_ENTER = 0,
|
||||
MOUSE_LEAVE,
|
||||
MOUSE_MOVE,
|
||||
MOUSE_UP,
|
||||
MOUSE_DOWN,
|
||||
MOUSE_DCLICK,
|
||||
MOUSE_WHEEL,
|
||||
/// mouse pressed ticks
|
||||
MOUSE_TICK,
|
||||
/// mouse stay idle for some time
|
||||
MOUSE_IDLE,
|
||||
|
||||
/// item dropped, target is that dropped item
|
||||
DROP = 9,
|
||||
/// drag arrived to the target element that is one of current drop targets.
|
||||
DRAG_ENTER = 0xA,
|
||||
/// drag left one of current drop targets. target is the drop target element.
|
||||
DRAG_LEAVE = 0xB,
|
||||
/// drag src notification before drag start. To cancel - return true from handler.
|
||||
DRAG_REQUEST = 0xC,
|
||||
|
||||
/// mouse click event
|
||||
MOUSE_CLICK = 0xFF,
|
||||
|
||||
/// This flag is `OR`ed with `MOUSE_ENTER..MOUSE_DOWN` codes if dragging operation is in effect.
|
||||
/// E.g. event `DRAGGING | MOUSE_MOVE` is sent to underlying DOM elements while dragging.
|
||||
DRAGGING = 0x100,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
/// General event source triggers
|
||||
pub enum CLICK_REASON
|
||||
{
|
||||
/// By mouse button.
|
||||
BY_MOUSE_CLICK,
|
||||
/// By keyboard (e.g. spacebar).
|
||||
BY_KEY_CLICK,
|
||||
/// Synthesized, by code.
|
||||
SYNTHESIZED,
|
||||
/// Icon click, e.g. arrow icon on drop-down select.
|
||||
BY_MOUSE_ON_ICON,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Edit control change trigger.
|
||||
pub enum EDIT_CHANGED_REASON
|
||||
{
|
||||
/// Single char insertion.
|
||||
BY_INS_CHAR,
|
||||
/// Character range insertion, clipboard.
|
||||
BY_INS_CHARS,
|
||||
/// Single char deletion.
|
||||
BY_DEL_CHAR,
|
||||
/// Character range (selection) deletion.
|
||||
BY_DEL_CHARS,
|
||||
/// Undo/redo.
|
||||
BY_UNDO_REDO,
|
||||
/// Single char insertion, previous character was inserted in previous position.
|
||||
CHANGE_BY_INS_CONSECUTIVE_CHAR,
|
||||
/// Single char removal, previous character was removed in previous position
|
||||
CHANGE_BY_DEL_CONSECUTIVE_CHAR,
|
||||
CHANGE_BY_CODE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Behavior event codes.
|
||||
pub enum BEHAVIOR_EVENTS
|
||||
{
|
||||
/// click on button
|
||||
BUTTON_CLICK = 0,
|
||||
/// mouse down or key down in button
|
||||
BUTTON_PRESS,
|
||||
/// checkbox/radio/slider changed its state/value
|
||||
BUTTON_STATE_CHANGED,
|
||||
/// before text change
|
||||
EDIT_VALUE_CHANGING,
|
||||
/// after text change
|
||||
EDIT_VALUE_CHANGED,
|
||||
/// selection in `<select>` changed
|
||||
SELECT_SELECTION_CHANGED,
|
||||
/// node in select expanded/collapsed, heTarget is the node
|
||||
SELECT_STATE_CHANGED,
|
||||
|
||||
/// request to show popup just received,
|
||||
/// here DOM of popup element can be modifed.
|
||||
POPUP_REQUEST,
|
||||
|
||||
/// popup element has been measured and ready to be shown on screen,
|
||||
/// here you can use functions like `ScrollToView`.
|
||||
POPUP_READY,
|
||||
|
||||
/// popup element is closed,
|
||||
/// here DOM of popup element can be modifed again - e.g. some items can be removed to free memory.
|
||||
POPUP_DISMISSED,
|
||||
|
||||
/// menu item activated by mouse hover or by keyboard,
|
||||
MENU_ITEM_ACTIVE,
|
||||
|
||||
/// menu item click,
|
||||
/// BEHAVIOR_EVENT_PARAMS structure layout
|
||||
/// BEHAVIOR_EVENT_PARAMS.cmd - MENU_ITEM_CLICK/MENU_ITEM_ACTIVE
|
||||
/// BEHAVIOR_EVENT_PARAMS.heTarget - owner(anchor) of the menu
|
||||
/// BEHAVIOR_EVENT_PARAMS.he - the menu item, presumably `<li>` element
|
||||
/// BEHAVIOR_EVENT_PARAMS.reason - BY_MOUSE_CLICK | BY_KEY_CLICK
|
||||
MENU_ITEM_CLICK,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// "right-click", BEHAVIOR_EVENT_PARAMS::he is current popup menu `HELEMENT` being processed or `NULL`.
|
||||
/// application can provide its own `HELEMENT` here (if it is `NULL`) or modify current menu element.
|
||||
CONTEXT_MENU_REQUEST = 0x10,
|
||||
|
||||
|
||||
/// broadcast notification, sent to all elements of some container being shown or hidden
|
||||
VISIUAL_STATUS_CHANGED,
|
||||
/// broadcast notification, sent to all elements of some container that got new value of `:disabled` state
|
||||
DISABLED_STATUS_CHANGED,
|
||||
|
||||
/// popup is about to be closed
|
||||
POPUP_DISMISSING,
|
||||
|
||||
/// content has been changed, is posted to the element that gets content changed, reason is combination of `CONTENT_CHANGE_BITS`.
|
||||
/// `target == NULL` means the window got new document and this event is dispatched only to the window.
|
||||
CONTENT_CHANGED = 0x15,
|
||||
|
||||
|
||||
/// generic click
|
||||
CLICK = 0x16,
|
||||
/// generic change
|
||||
CHANGE = 0x17,
|
||||
|
||||
/// media changed (screen resolution, number of displays, etc.)
|
||||
MEDIA_CHANGED = 0x18,
|
||||
/// input language has changed, data is iso lang-country string
|
||||
INPUT_LANGUAGE_CHANGED = 0x19,
|
||||
/// editable content has changed
|
||||
CONTENT_MODIFIED = 0x1A,
|
||||
/// a broadcast notification being posted to all elements of some container
|
||||
/// that changes its `:read-only` state.
|
||||
READONLY_STATUS_CHANGED = 0x1B,
|
||||
/// change in `aria-live="polite|assertive"`
|
||||
ARIA_LIVE_AREA_CHANGED = 0x1C,
|
||||
|
||||
// "grey" event codes - notfications from behaviors from this SDK
|
||||
/// hyperlink click
|
||||
HYPERLINK_CLICK = 0x80,
|
||||
|
||||
PASTE_TEXT = 0x8E,
|
||||
PASTE_HTML = 0x8F,
|
||||
|
||||
/// element was collapsed, so far only `behavior:tabs` is sending these two to the panels
|
||||
ELEMENT_COLLAPSED = 0x90,
|
||||
/// element was expanded,
|
||||
ELEMENT_EXPANDED,
|
||||
|
||||
/// activate (select) child,
|
||||
/// used, for example, by `accesskeys` behaviors to send activation request, e.g. tab on `behavior:tabs`.
|
||||
ACTIVATE_CHILD,
|
||||
|
||||
/// ui state changed, observers shall update their visual states.
|
||||
/// is sent, for example, by `behavior:richtext` when caret position/selection has changed.
|
||||
UI_STATE_CHANGED = 0x95,
|
||||
|
||||
|
||||
/// `behavior:form` detected submission event. `BEHAVIOR_EVENT_PARAMS::data` field contains data to be posted.
|
||||
/// `BEHAVIOR_EVENT_PARAMS::data` is of type `T_MAP` in this case key/value pairs of data that is about
|
||||
/// to be submitted. You can modify the data or discard submission by returning true from the handler.
|
||||
FORM_SUBMIT,
|
||||
|
||||
|
||||
/// `behavior:form` detected reset event (from `button type=reset`). `BEHAVIOR_EVENT_PARAMS::data` field contains data to be reset.
|
||||
/// `BEHAVIOR_EVENT_PARAMS::data` is of type `T_MAP` in this case key/value pairs of data that is about
|
||||
/// to be rest. You can modify the data or discard reset by returning true from the handler.
|
||||
FORM_RESET,
|
||||
|
||||
|
||||
|
||||
/// document in `behavior:frame` or root document is complete.
|
||||
DOCUMENT_COMPLETE,
|
||||
|
||||
/// requests to `behavior:history` (commands)
|
||||
HISTORY_PUSH,
|
||||
HISTORY_DROP,
|
||||
HISTORY_PRIOR,
|
||||
HISTORY_NEXT,
|
||||
/// `behavior:history` notification - history stack has changed
|
||||
HISTORY_STATE_CHANGED,
|
||||
|
||||
/// close popup request,
|
||||
CLOSE_POPUP,
|
||||
/// request tooltip, `evt.source` <- is the tooltip element.
|
||||
TOOLTIP_REQUEST,
|
||||
|
||||
/// animation started (`reason=1`) or ended(`reason=0`) on the element.
|
||||
ANIMATION = 0xA0,
|
||||
|
||||
/// document created, script namespace initialized. `target` -> the document
|
||||
DOCUMENT_CREATED = 0xC0,
|
||||
/// document is about to be closed, to cancel closing do: `evt.data = sciter::Value("cancel")`;
|
||||
DOCUMENT_CLOSE_REQUEST,
|
||||
/// last notification before document removal from the DOM
|
||||
DOCUMENT_CLOSE,
|
||||
/// document has got DOM structure, styles and behaviors of DOM elements. Script loading run is complete at this moment.
|
||||
DOCUMENT_READY,
|
||||
/// document just finished parsing - has got DOM structure. This event is generated before the `DOCUMENT_READY`.
|
||||
/// Since 4.0.3.
|
||||
DOCUMENT_PARSED = 0xC4,
|
||||
|
||||
/// `<video>` "ready" notification
|
||||
VIDEO_INITIALIZED = 0xD1,
|
||||
/// `<video>` playback started notification
|
||||
VIDEO_STARTED,
|
||||
/// `<video>` playback stoped/paused notification
|
||||
VIDEO_STOPPED,
|
||||
/// `<video>` request for frame source binding,
|
||||
/// If you want to provide your own video frames source for the given target `<video>` element do the following:
|
||||
///
|
||||
/// 1. Handle and consume this `VIDEO_BIND_RQ` request
|
||||
/// 2. You will receive second `VIDEO_BIND_RQ` request/event for the same `<video>` element
|
||||
/// but this time with the `reason` field set to an instance of `sciter::video_destination` interface.
|
||||
/// 3. `add_ref()` it and store it, for example, in a worker thread producing video frames.
|
||||
/// 4. call `sciter::video_destination::start_streaming(...)` providing needed parameters
|
||||
/// call `sciter::video_destination::render_frame(...)` as soon as they are available
|
||||
/// call `sciter::video_destination::stop_streaming()` to stop the rendering (a.k.a. end of movie reached)
|
||||
VIDEO_BIND_RQ,
|
||||
|
||||
|
||||
/// `behavior:pager` starts pagination
|
||||
PAGINATION_STARTS = 0xE0,
|
||||
/// `behavior:pager` paginated page no, reason -> page no
|
||||
PAGINATION_PAGE,
|
||||
/// `behavior:pager` end pagination, reason -> total pages
|
||||
PAGINATION_ENDS,
|
||||
|
||||
/// event with custom name.
|
||||
/// Since 4.2.8.
|
||||
CUSTOM = 0xF0,
|
||||
|
||||
/// SSX, delayed mount_component
|
||||
MOUNT_COMPONENT = 0xF1,
|
||||
|
||||
/// all custom event codes shall be greater than this number. All codes below this will be used
|
||||
/// solely by application - Sciter will not intrepret it and will do just dispatching.
|
||||
/// To send event notifications with these codes use `SciterSend`/`PostEvent` API.
|
||||
FIRST_APPLICATION_EVENT_CODE = 0x100,
|
||||
|
||||
}
|
||||
|
||||
|
||||
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) }
|
||||
}
|
||||
}
|
||||
388
libs/rust-sciter/src/capi/scdef.rs
Normal file
388
libs/rust-sciter/src/capi/scdef.rs
Normal file
@@ -0,0 +1,388 @@
|
||||
//! Common Sciter declarations.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scvalue::{VALUE};
|
||||
use capi::screquest::{HREQUEST};
|
||||
use capi::scdom::{HELEMENT};
|
||||
use capi::scapi::ISciterAPI;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
pub enum ID2D1RenderTarget {}
|
||||
pub enum ID2D1Factory {}
|
||||
pub enum IDWriteFactory {}
|
||||
pub enum IDXGISwapChain {}
|
||||
pub enum IDXGISurface {}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// `HostHandler::on_data_load()` result code.
|
||||
///
|
||||
/// This notification gives application a chance to override built-in loader and
|
||||
/// implement loading of resources in its own way (for example, images can be loaded from
|
||||
/// a database or other resource).
|
||||
pub enum LOAD_RESULT {
|
||||
/// Do the default loading if data is not set.
|
||||
LOAD_DEFAULT,
|
||||
/// Discard the request completely (data will not be loaded at the document).
|
||||
LOAD_DISCARD,
|
||||
/// Data will be delivered later by the host application.
|
||||
LOAD_DELAYED,
|
||||
/// You return this result to indicate that your (the host) application took or
|
||||
/// will take care about `HREQUEST` in your code completely.
|
||||
LOAD_MYSELF,
|
||||
}
|
||||
|
||||
/// 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,
|
||||
}
|
||||
|
||||
/// Sciter graphics rendering backend.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum GFX_LAYER
|
||||
{
|
||||
/// An auto-selected backend.
|
||||
AUTO = 0xFFFF,
|
||||
|
||||
/// Depends on OS: GDI, Cairo or CoreGraphics.
|
||||
CPU = 1,
|
||||
|
||||
/// A software rasterizer for Direct2D (Windows only).
|
||||
#[cfg(windows)]
|
||||
WARP = 2,
|
||||
|
||||
/// A hardware Direct2D mode (Windows only).
|
||||
#[cfg(windows)]
|
||||
D2D = 3,
|
||||
|
||||
/// Skia backend with CPU rasterization mode.
|
||||
SKIA_CPU = 4,
|
||||
|
||||
/// Skia backend with OpenGL rendering.
|
||||
SKIA_OPENGL = 5,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Various Sciter engine options (global or per-window).
|
||||
pub enum SCITER_RT_OPTIONS
|
||||
{
|
||||
/// value:TRUE - enable, value:FALSE - disable, enabled by default.
|
||||
SCITER_SMOOTH_SCROLL = 1,
|
||||
/// global; value: milliseconds, connection timeout of http client.
|
||||
SCITER_CONNECTION_TIMEOUT = 2,
|
||||
/// global; value: 0 - drop connection, 1 - use builtin dialog, 2 - accept connection silently.
|
||||
SCITER_HTTPS_ERROR = 3,
|
||||
/// value: 0 - system default, 1 - no smoothing, 2 - std smoothing, 3 - clear type.
|
||||
SCITER_FONT_SMOOTHING = 4,
|
||||
/// Windows Aero support, value:
|
||||
/// 0 - normal drawing,
|
||||
/// 1 - window has transparent background after calls `DwmExtendFrameIntoClientArea()` or `DwmEnableBlurBehindWindow()`.
|
||||
SCITER_TRANSPARENT_WINDOW = 6,
|
||||
/// global; value = LPCBYTE, json - GPU black list, see: gpu-blacklist.json resource.
|
||||
/// Note: is not used since Sciter 4.
|
||||
#[deprecated(since="4.0.1", note="This option isn't working since Sciter 4.0.1.1.")]
|
||||
SCITER_SET_GPU_BLACKLIST = 7,
|
||||
/// global or per-window; value - combination of [SCRIPT_RUNTIME_FEATURES](enum.SCRIPT_RUNTIME_FEATURES.html) flags.
|
||||
SCITER_SET_SCRIPT_RUNTIME_FEATURES = 8,
|
||||
/// global (must be called before any window creation); value - [GFX_LAYER](enum.GFX_LAYER.html).
|
||||
SCITER_SET_GFX_LAYER = 9,
|
||||
/// global or per-window; value - TRUE/FALSE
|
||||
SCITER_SET_DEBUG_MODE = 10,
|
||||
/// global; value - BOOL, TRUE - the engine will use "unisex" theme that is common for all platforms.
|
||||
/// That UX theme is not using OS primitives for rendering input elements.
|
||||
/// Use it if you want exactly the same (modulo fonts) look-n-feel on all platforms.
|
||||
SCITER_SET_UX_THEMING = 11,
|
||||
/// value - TRUE/FALSE - window uses per pixel alpha (e.g. `WS_EX_LAYERED`/`UpdateLayeredWindow()` window).
|
||||
SCITER_ALPHA_WINDOW = 12,
|
||||
/// global; value: UTF-8 encoded script source to be loaded into each view before any other script execution.
|
||||
SCITER_SET_INIT_SCRIPT = 13,
|
||||
/// per-window; value - TRUE/FALSE - window is main, will destroy all other dependent windows on close.
|
||||
SCITER_SET_MAIN_WINDOW = 14,
|
||||
/// global; value - max request length in megabytes (1024*1024 bytes).
|
||||
SCITER_SET_MAX_HTTP_DATA_LENGTH = 15,
|
||||
}
|
||||
|
||||
/// 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,
|
||||
}
|
||||
|
||||
impl Default for SCITER_CREATE_WINDOW_FLAGS {
|
||||
fn default() -> Self {
|
||||
SCITER_CREATE_WINDOW_FLAGS::SW_CHILD
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
SC_LOAD_DATA = 1,
|
||||
SC_DATA_LOADED = 2,
|
||||
SC_ATTACH_BEHAVIOR = 4,
|
||||
SC_ENGINE_DESTROYED = 5,
|
||||
SC_POSTED_NOTIFICATION = 6,
|
||||
SC_GRAPHICS_CRITICAL_FAILURE = 7,
|
||||
SC_KEYBOARD_REQUEST = 8,
|
||||
SC_INVALIDATE_RECT = 9,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// The type of a loaded resource.
|
||||
pub enum RESOURCE_TYPE {
|
||||
/// HTML document.
|
||||
HTML = 0,
|
||||
/// Image.
|
||||
IMAGE = 1,
|
||||
/// CSS.
|
||||
STYLE = 2,
|
||||
/// Mouse cursor image.
|
||||
CURSOR = 3,
|
||||
/// TIScript document.
|
||||
SCRIPT = 4,
|
||||
/// Any data.
|
||||
RAW = 5,
|
||||
/// Font.
|
||||
FONT,
|
||||
/// Sound (wav bytes).
|
||||
SOUND,
|
||||
}
|
||||
|
||||
/// The type of a loaded resource.
|
||||
pub type SCITER_RESOURCE_TYPE = RESOURCE_TYPE;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Notifies that Sciter is about to download a referred resource.
|
||||
pub struct SCN_LOAD_DATA
|
||||
{
|
||||
/// `SC_LOAD_DATA` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
|
||||
/// [in] Zero terminated string, fully qualified uri, for example, "http://server/folder/file.ext".
|
||||
pub uri: LPCWSTR,
|
||||
|
||||
/// [in,out] pointer to loaded data to return. If data exists in the cache then this field contain pointer to it.
|
||||
pub outData: LPCBYTE,
|
||||
/// [in,out] loaded data size to return.
|
||||
pub outDataSize: UINT,
|
||||
|
||||
/// [in] resource type category
|
||||
pub dataType: RESOURCE_TYPE,
|
||||
|
||||
/// [in] request handle that can be used with Sciter request API.
|
||||
pub request_id: HREQUEST,
|
||||
|
||||
/// [in] destination element for request.
|
||||
pub principal: HELEMENT,
|
||||
/// [in] source element for request.
|
||||
pub initiator: HELEMENT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// This notification indicates that external data (for example, image) download process has been completed.
|
||||
pub struct SCN_DATA_LOADED
|
||||
{
|
||||
/// `SC_DATA_LOADED` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
/// [in] zero terminated string, fully qualified uri, for example, "http://server/folder/file.ext".
|
||||
pub uri: LPCWSTR,
|
||||
/// [in] pointer to loaded data.
|
||||
pub data: LPCBYTE,
|
||||
/// [in] loaded data size (in bytes).
|
||||
pub dataSize: UINT,
|
||||
/// [in] resource type category
|
||||
pub dataType: RESOURCE_TYPE,
|
||||
/// Download status code:
|
||||
///
|
||||
/// * status = 0 and `dataSize == 0` - unknown error.
|
||||
/// * status = 100..505 - http response status, note: 200 - OK!
|
||||
/// * status > 12000 - wininet error code, see `ERROR_INTERNET_***` in wininet.h
|
||||
pub status: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// This notification is sent on parsing the document and while processing elements
|
||||
/// having non empty `behavior: ` style attribute value.
|
||||
pub struct SCN_ATTACH_BEHAVIOR
|
||||
{
|
||||
/// `SC_ATTACH_BEHAVIOR` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
|
||||
/// [in] target DOM element handle
|
||||
pub element: HELEMENT,
|
||||
/// [in] zero terminated string, string appears as value of CSS `behavior: ` attribute.
|
||||
pub name: LPCSTR,
|
||||
/// [out] pointer to ElementEventProc function.
|
||||
pub elementProc: ElementEventProc,
|
||||
/// [out] tag value, passed as is into pointer ElementEventProc function.
|
||||
pub elementTag: LPVOID,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// This notification is issued when keyboard needs to be shown –
|
||||
/// mobiles can show soft keyboard by handling it.
|
||||
pub struct SCN_KEYBOARD_REQUEST
|
||||
{
|
||||
/// `SC_KEYBOARD_REQUEST` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
|
||||
pub keyboard_mode: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// This notification is sent when a specific window area
|
||||
/// needs to be redrawn.
|
||||
pub struct SCN_INVALIDATE_RECT
|
||||
{
|
||||
/// `SC_INVALIDATE_RECT` here.
|
||||
pub code: UINT,
|
||||
/// `HWINDOW` of the window this callback was attached to.
|
||||
pub hwnd: HWINDOW,
|
||||
|
||||
/// Coordinates of the invalidated area.
|
||||
pub invalid_rect: RECT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SCITER_CALLBACK_NOTIFICATION
|
||||
{
|
||||
pub code: UINT,
|
||||
pub hwnd: HWINDOW,
|
||||
}
|
||||
pub type LPSCITER_CALLBACK_NOTIFICATION = *mut SCITER_CALLBACK_NOTIFICATION;
|
||||
|
||||
pub type SciterHostCallback = extern "system" fn (pns: LPSCITER_CALLBACK_NOTIFICATION, callbackParam: LPVOID) -> UINT;
|
||||
|
||||
pub type SciterWindowDelegate = extern "system" fn (hwnd: HWINDOW, msg: UINT, wParam: WPARAM, lParam: LPARAM, pParam: LPVOID, handled: * mut BOOL) -> LRESULT;
|
||||
|
||||
pub type ElementEventProc = extern "system" fn (tag: LPVOID, he: HELEMENT, evtg: UINT, prms: LPVOID) -> BOOL;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Debug output categories.
|
||||
pub enum OUTPUT_SUBSYTEMS
|
||||
{
|
||||
/// html parser & runtime
|
||||
DOM = 0,
|
||||
/// csss! parser & runtime
|
||||
CSSS,
|
||||
/// css parser
|
||||
CSS,
|
||||
/// TIS parser & runtime
|
||||
TIS,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
/// Debug output severity.
|
||||
pub enum OUTPUT_SEVERITY
|
||||
{
|
||||
INFO,
|
||||
WARNING,
|
||||
ERROR,
|
||||
}
|
||||
|
||||
pub type DEBUG_OUTPUT_PROC = extern "system" fn (param: LPVOID, subsystem: OUTPUT_SUBSYTEMS, severity: OUTPUT_SEVERITY, text: LPCWSTR, text_length: UINT);
|
||||
|
||||
pub type LPCWSTR_RECEIVER = extern "system" fn (szstr: LPCWSTR, str_length: UINT, param: LPVOID);
|
||||
pub type LPCSTR_RECEIVER = extern "system" fn (szstr: LPCSTR, str_length: UINT, param: LPVOID);
|
||||
pub type LPCBYTE_RECEIVER = extern "system" fn (szstr: LPCBYTE, str_length: UINT, param: LPVOID);
|
||||
|
||||
pub type ELEMENT_BITMAP_RECEIVER = extern "system" fn (rgba: LPCBYTE, x: INT, y: INT, width: UINT, height: UINT, param: LPVOID);
|
||||
|
||||
pub type KeyValueCallback = extern "system" fn (param: LPVOID, pkey: *const VALUE, pval: *const VALUE) -> BOOL;
|
||||
|
||||
/// Signature of Sciter extension library.
|
||||
///
|
||||
/// * `api` - Sciter API to be used inside the extension.
|
||||
/// * `exported` - extension object, it can be [asset](https://sciter.com/developers/for-native-gui-programmers/sciter-object-model/),
|
||||
/// function, or other `sciter::Value` supported type.
|
||||
///
|
||||
/// Return `true` if the `exported` object was initialized.
|
||||
///
|
||||
/// The extension should be placed in the same folder as "sciter.dll"
|
||||
/// and export a `SciterLibraryInit` function:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use sciter::types::{BOOL, VALUE};
|
||||
/// use sciter::Value;
|
||||
///
|
||||
/// #[no_mangle]
|
||||
/// pub extern "system"
|
||||
/// fn SciterLibraryInit(api: &'static sciter::ISciterAPI, exported: &mut VALUE) -> BOOL
|
||||
/// {
|
||||
/// sciter::set_host_api(api);
|
||||
///
|
||||
/// unimplemented!("export some extension functions");
|
||||
///
|
||||
/// true as BOOL
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// In script such extension library can be imported as:
|
||||
///
|
||||
/// ```javascript
|
||||
/// const exported = include library "library-name";
|
||||
/// ```
|
||||
///
|
||||
/// See the [blog post](https://sciter.com/include-library-name-native-extensions/) for more details.
|
||||
///
|
||||
pub type SciterLibraryInit = extern "system" fn (api: &'static ISciterAPI, exported: &mut VALUE) -> BOOL;
|
||||
233
libs/rust-sciter/src/capi/scdom.rs
Normal file
233
libs/rust-sciter/src/capi/scdom.rs
Normal file
@@ -0,0 +1,233 @@
|
||||
//! DOM access methods, C interface.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
|
||||
MAKE_HANDLE!(#[doc = "Element native handle."] HELEMENT, _HELEMENT);
|
||||
MAKE_HANDLE!(#[doc = "Node native handle."] HNODE, _HNODE);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// Type of the result value for Sciter DOM functions.
|
||||
pub enum SCDOM_RESULT {
|
||||
/// Function completed successfully.
|
||||
OK = 0,
|
||||
/// Invalid `HWINDOW`.
|
||||
INVALID_HWND = 1,
|
||||
/// Invalid `HELEMENT`.
|
||||
INVALID_HANDLE = 2,
|
||||
/// Attempt to use `HELEMENT` which is not attached to document.
|
||||
PASSIVE_HANDLE = 3,
|
||||
/// Parameter is invalid, e.g. pointer is null.
|
||||
INVALID_PARAMETER = 4,
|
||||
/// Operation failed, e.g. invalid html passed.
|
||||
OPERATION_FAILED = 5,
|
||||
/// Function completed successfully, but no result (e.g. no such attribute at element).
|
||||
OK_NOT_HANDLED = -1,
|
||||
}
|
||||
|
||||
impl std::error::Error for SCDOM_RESULT {}
|
||||
|
||||
impl std::fmt::Display for SCDOM_RESULT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// `dom::Element.set_html()` options.
|
||||
pub enum SET_ELEMENT_HTML
|
||||
{
|
||||
SIH_REPLACE_CONTENT = 0,
|
||||
SIH_INSERT_AT_START = 1,
|
||||
SIH_APPEND_AFTER_LAST = 2,
|
||||
SOH_REPLACE = 3,
|
||||
SOH_INSERT_BEFORE = 4,
|
||||
SOH_INSERT_AFTER = 5,
|
||||
}
|
||||
|
||||
/// Bounding rectangle of the element.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum ELEMENT_AREAS {
|
||||
|
||||
/// `or` this flag if you want to get Sciter window relative coordinates,
|
||||
/// otherwise it will use nearest windowed container e.g. popup window.
|
||||
ROOT_RELATIVE = 0x01,
|
||||
|
||||
/// `or` this flag if you want to get coordinates relative to the origin of element iself.
|
||||
SELF_RELATIVE = 0x02,
|
||||
|
||||
/// Position inside immediate container.
|
||||
CONTAINER_RELATIVE = 0x03,
|
||||
|
||||
/// Position relative to view - Sciter window.
|
||||
VIEW_RELATIVE = 0x04,
|
||||
|
||||
/// Content (inner) box.
|
||||
CONTENT_BOX = 0x00,
|
||||
|
||||
/// Content + paddings.
|
||||
PADDING_BOX = 0x10,
|
||||
|
||||
/// Content + paddings + border.
|
||||
BORDER_BOX = 0x20,
|
||||
|
||||
/// Content + paddings + border + margins.
|
||||
MARGIN_BOX = 0x30,
|
||||
|
||||
/// Relative to content origin - location of background image (if it set `no-repeat`).
|
||||
BACK_IMAGE_AREA = 0x40,
|
||||
|
||||
/// Relative to content origin - location of foreground image (if it set `no-repeat`).
|
||||
FORE_IMAGE_AREA = 0x50,
|
||||
|
||||
/// Scroll_area - scrollable area in content box.
|
||||
SCROLLABLE_AREA = 0x60,
|
||||
}
|
||||
|
||||
impl ELEMENT_AREAS {
|
||||
/// Size of content (i.e `(0, 0, width, height)`).
|
||||
pub fn self_content() -> u32 {
|
||||
ELEMENT_AREAS::SELF_RELATIVE as u32
|
||||
}
|
||||
|
||||
/// Size of rect (i.e `(left, top, width, height)`)
|
||||
pub fn self_rect() -> u32 {
|
||||
ELEMENT_AREAS::ROOT_RELATIVE as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// Collection of states (runtime flags) of a DOM element.
|
||||
///
|
||||
/// They reflect CSS pseudo-classes that are used in selectors,
|
||||
/// 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. `<a href`.
|
||||
STATE_LINK = 0x00000001,
|
||||
|
||||
/// Mouse over the element at the moment.
|
||||
STATE_HOVER = 0x00000002,
|
||||
/// Element is pressed.
|
||||
///
|
||||
/// Commonly used by `<button>` or `<a>` 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,
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
||||
pub type ELEMENT_COMPARATOR = extern "system" fn (he1: HELEMENT, he2: HELEMENT, param: LPVOID) -> INT;
|
||||
353
libs/rust-sciter/src/capi/scgraphics.rs
Normal file
353
libs/rust-sciter/src/capi/scgraphics.rs
Normal file
@@ -0,0 +1,353 @@
|
||||
//! Sciter's platform independent graphics interface.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::scdom::HELEMENT;
|
||||
use capi::sctypes::{BOOL, LPCBYTE, LPCWSTR, LPVOID, UINT};
|
||||
use capi::scvalue::VALUE;
|
||||
|
||||
MAKE_HANDLE!(#[doc = "Graphics native handle."] HGFX, _HGFX);
|
||||
MAKE_HANDLE!(#[doc = "Image native handle."] HIMG, _HIMG);
|
||||
MAKE_HANDLE!(#[doc = "Path native handle."] HPATH, _HPATH);
|
||||
MAKE_HANDLE!(#[doc = "Text native handle."] HTEXT, _HTEXT);
|
||||
|
||||
pub type SC_REAL = f32;
|
||||
pub type SC_POS = SC_REAL;
|
||||
pub type SC_DIM = SC_REAL;
|
||||
pub type SC_ANGLE = SC_REAL;
|
||||
|
||||
pub type SC_COLOR = u32;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// Type of the result value for Sciter Graphics functions.
|
||||
pub enum GRAPHIN_RESULT {
|
||||
/// E.g. not enough memory.
|
||||
PANIC = -1,
|
||||
/// Success.
|
||||
OK = 0,
|
||||
/// Bad parameter.
|
||||
BAD_PARAM = 1,
|
||||
/// Operation failed, e.g. `restore()` without `save()`.
|
||||
FAILURE = 2,
|
||||
/// Platform does not support the requested feature.
|
||||
NOTSUPPORTED = 3,
|
||||
}
|
||||
|
||||
impl std::error::Error for GRAPHIN_RESULT {}
|
||||
|
||||
impl std::fmt::Display for GRAPHIN_RESULT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Path drawing mode.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DRAW_PATH {
|
||||
/// Draw without outline line.
|
||||
FILL_ONLY = 1,
|
||||
/// Draw outline without fill.
|
||||
STROKE_ONLY = 2,
|
||||
/// Draw outlined and filled path.
|
||||
FILL_AND_STROKE = 3,
|
||||
}
|
||||
|
||||
/// Line drawing join mode.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum LINE_JOIN {
|
||||
/// Specifies a mitered join. This produces a sharp corner or a clipped corner,
|
||||
/// depending on whether the length of the miter exceeds the miter limit (`10.0`).
|
||||
MITER = 0,
|
||||
/// Specifies a circular join. This produces a smooth, circular arc between the lines.
|
||||
ROUND = 1,
|
||||
/// Specifies a beveled join. This produces a diagonal corner.
|
||||
BEVEL = 2,
|
||||
/// Specifies a mitered join. This produces a sharp corner or a beveled corner,
|
||||
/// depending on whether the length of the miter exceeds the miter limit (`10.0`).
|
||||
MITER_OR_BEVEL = 3,
|
||||
}
|
||||
|
||||
/// Line drawing cap mode.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum LINE_CAP {
|
||||
/// The ends of lines are squared off at the endpoints.
|
||||
BUTT = 0,
|
||||
/// The ends of lines are squared off by adding a box with an equal width
|
||||
/// and half the height of the line's thickness.
|
||||
SQUARE = 1,
|
||||
/// The ends of lines are rounded.
|
||||
ROUND = 2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum IMAGE_ENCODING {
|
||||
RAW, // [a,b,g,r,a,b,g,r,...] vector
|
||||
PNG,
|
||||
JPG,
|
||||
WEBP,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct SC_COLOR_STOP {
|
||||
pub color: SC_COLOR,
|
||||
pub offset: f32,
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct SciterGraphicsAPI {
|
||||
// image primitives
|
||||
pub imageCreate: extern "system" fn(poutImg: &mut HIMG, width: UINT, height: UINT, withAlpha: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
// construct image from B[n+0],G[n+1],R[n+2],A[n+3] data.
|
||||
// Size of pixmap data is pixmapWidth*pixmapHeight*4
|
||||
pub imageCreateFromPixmap:
|
||||
extern "system" fn(poutImg: &mut HIMG, pixmapWidth: UINT, pixmapHeight: UINT, withAlpha: BOOL, pixmap: LPCBYTE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageAddRef: extern "system" fn(himg: HIMG) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageRelease: extern "system" fn(himg: HIMG) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageGetInfo: extern "system" fn(himg: HIMG, width: &mut UINT, height: &mut UINT, usesAlpha: &mut BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageClear: extern "system" fn(himg: HIMG, byColor: SC_COLOR) -> GRAPHIN_RESULT,
|
||||
|
||||
pub imageLoad: extern "system" fn(bytes: LPCBYTE, num_bytes: UINT, pout_img: &mut HIMG) -> GRAPHIN_RESULT, // load png/jpeg/etc. image from stream of bytes
|
||||
|
||||
pub imageSave: extern "system" fn(himg: HIMG, pfn: ImageWriteFunction, prm: LPVOID, encoding: IMAGE_ENCODING, quality: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: graphics primitives and drawing operations
|
||||
|
||||
// create SC_COLOR value
|
||||
pub RGBA: extern "system" fn(red: UINT, green: UINT, blue: UINT, alpha: UINT) -> SC_COLOR,
|
||||
|
||||
pub gCreate: extern "system" fn(img: HIMG, pout_gfx: &mut HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gAddRef: extern "system" fn(gfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gRelease: extern "system" fn(gfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws line from x1,y1 to x2,y2 using current lineColor and lineGradient.
|
||||
pub gLine: extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws rectangle using current lineColor/lineGradient and fillColor/fillGradient with (optional) rounded corners.
|
||||
pub gRectangle: extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws rounded rectangle using current lineColor/lineGradient and fillColor/fillGradient with (optional) rounded corners.
|
||||
pub gRoundedRectangle: extern "system" fn(
|
||||
hgfx: HGFX,
|
||||
x1: SC_POS,
|
||||
y1: SC_POS,
|
||||
x2: SC_POS,
|
||||
y2: SC_POS,
|
||||
radii8: *const SC_DIM,
|
||||
) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws circle or ellipse using current lineColor/lineGradient and fillColor/fillGradient.
|
||||
pub gEllipse: extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, rx: SC_DIM, ry: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws closed arc using current lineColor/lineGradient and fillColor/fillGradient.
|
||||
pub gArc:
|
||||
extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, rx: SC_POS, ry: SC_POS, start: SC_ANGLE, sweep: SC_ANGLE) -> GRAPHIN_RESULT,
|
||||
|
||||
// Draws star.
|
||||
pub gStar: extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, r1: SC_DIM, r2: SC_DIM, start: SC_ANGLE, rays: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// Closed polygon.
|
||||
pub gPolygon: extern "system" fn(hgfx: HGFX, xy: *const SC_POS, num_points: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// Polyline.
|
||||
pub gPolyline: extern "system" fn(hgfx: HGFX, xy: *const SC_POS, num_points: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: Path operations
|
||||
pub pathCreate: extern "system" fn(path: &mut HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathAddRef: extern "system" fn(path: HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathRelease: extern "system" fn(path: HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathMoveTo: extern "system" fn(path: HPATH, x: SC_POS, y: SC_POS, relative: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathLineTo: extern "system" fn(path: HPATH, x: SC_POS, y: SC_POS, relative: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathArcTo: extern "system" fn(
|
||||
path: HPATH,
|
||||
x: SC_POS,
|
||||
y: SC_POS,
|
||||
angle: SC_ANGLE,
|
||||
rx: SC_DIM,
|
||||
ry: SC_DIM,
|
||||
is_large_arc: BOOL,
|
||||
clockwise: BOOL,
|
||||
relative: BOOL,
|
||||
) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathQuadraticCurveTo: extern "system" fn(path: HPATH, xc: SC_POS, yc: SC_POS, x: SC_POS, y: SC_POS, relative: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
pub pathBezierCurveTo:
|
||||
extern "system" fn(path: HPATH, xc1: SC_POS, yc1: SC_POS, xc2: SC_POS, yc2: SC_POS, x: SC_POS, y: SC_POS, relative: BOOL)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
pub pathClosePath: extern "system" fn(path: HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gDrawPath: extern "system" fn(hgfx: HGFX, path: HPATH, dpm: DRAW_PATH) -> GRAPHIN_RESULT,
|
||||
|
||||
// end of path opearations
|
||||
|
||||
// SECTION: affine tranformations:
|
||||
pub gRotate: extern "system" fn(hgfx: HGFX, radians: SC_ANGLE, cx: Option<&SC_POS>, cy: Option<&SC_POS>) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gTranslate: extern "system" fn(hgfx: HGFX, cx: SC_POS, cy: SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gScale: extern "system" fn(hgfx: HGFX, x: SC_DIM, y: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gSkew: extern "system" fn(hgfx: HGFX, dx: SC_DIM, dy: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
// all above in one shot
|
||||
pub gTransform:
|
||||
extern "system" fn(hgfx: HGFX, m11: SC_POS, m12: SC_POS, m21: SC_POS, m22: SC_POS, dx: SC_POS, dy: SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
// end of affine tranformations.
|
||||
|
||||
// SECTION: state save/restore
|
||||
pub gStateSave: extern "system" fn(hgfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gStateRestore: extern "system" fn(hgfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
// end of state save/restore
|
||||
|
||||
// SECTION: drawing attributes
|
||||
|
||||
// set line width for subsequent drawings.
|
||||
pub gLineWidth: extern "system" fn(hgfx: HGFX, width: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gLineJoin: extern "system" fn(hgfx: HGFX, join_type: LINE_JOIN) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gLineCap: extern "system" fn(hgfx: HGFX, cap_type: LINE_CAP) -> GRAPHIN_RESULT,
|
||||
|
||||
// SC_COLOR for solid lines/strokes
|
||||
pub gLineColor: extern "system" fn(hgfx: HGFX, color: SC_COLOR) -> GRAPHIN_RESULT,
|
||||
|
||||
// SC_COLOR for solid fills
|
||||
pub gFillColor: extern "system" fn(hgfx: HGFX, color: SC_COLOR) -> GRAPHIN_RESULT,
|
||||
|
||||
// setup parameters of linear gradient of lines.
|
||||
pub gLineGradientLinear:
|
||||
extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS, stops: *const SC_COLOR_STOP, nstops: UINT)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
// setup parameters of linear gradient of fills.
|
||||
pub gFillGradientLinear:
|
||||
extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS, stops: *const SC_COLOR_STOP, nstops: UINT)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
// setup parameters of line gradient radial fills.
|
||||
pub gLineGradientRadial:
|
||||
extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, rx: SC_DIM, ry: SC_DIM, stops: *const SC_COLOR_STOP, nstops: UINT)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
// setup parameters of gradient radial fills.
|
||||
pub gFillGradientRadial:
|
||||
extern "system" fn(hgfx: HGFX, x: SC_POS, y: SC_POS, rx: SC_DIM, ry: SC_DIM, stops: *const SC_COLOR_STOP, nstops: UINT)
|
||||
-> GRAPHIN_RESULT,
|
||||
|
||||
pub gFillMode: extern "system" fn(hgfx: HGFX, even_odd: BOOL) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: text
|
||||
|
||||
// create text layout for host element
|
||||
pub textCreateForElement: extern "system" fn(ptext: &mut HTEXT, text: LPCWSTR, textLength: UINT, he: HELEMENT, classNameOrNull: LPCWSTR) -> GRAPHIN_RESULT,
|
||||
|
||||
// create text layout using explicit style declaration
|
||||
pub textCreateForElementAndStyle:
|
||||
extern "system" fn(ptext: &mut HTEXT, text: LPCWSTR, textLength: UINT, he: HELEMENT, style: LPCWSTR, styleLength: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// since 4.1.10
|
||||
pub textAddRef: extern "system" fn(text: HTEXT) -> GRAPHIN_RESULT,
|
||||
|
||||
// since 4.1.10
|
||||
pub textRelease: extern "system" fn(text: HTEXT) -> GRAPHIN_RESULT,
|
||||
|
||||
pub textGetMetrics: extern "system" fn(
|
||||
text: HTEXT,
|
||||
minWidth: &mut SC_DIM,
|
||||
maxWidth: &mut SC_DIM,
|
||||
height: &mut SC_DIM,
|
||||
ascent: &mut SC_DIM,
|
||||
descent: &mut SC_DIM,
|
||||
nLines: &mut UINT,
|
||||
) -> GRAPHIN_RESULT,
|
||||
|
||||
pub textSetBox: extern "system" fn(text: HTEXT, width: SC_DIM, height: SC_DIM) -> GRAPHIN_RESULT,
|
||||
|
||||
// draw text with position (1..9 on MUMPAD) at px,py
|
||||
// Ex: gDrawText(100,100,5) will draw text box with its center at 100,100 px
|
||||
pub gDrawText: extern "system" fn(hgfx: HGFX, text: HTEXT, px: SC_POS, py: SC_POS, position: UINT) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: image rendering
|
||||
|
||||
// draws img onto the graphics surface with current transformation applied (scale, rotation).
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub gDrawImage: extern "system" fn(
|
||||
hgfx: HGFX,
|
||||
himg: HIMG,
|
||||
x: SC_POS,
|
||||
y: SC_POS,
|
||||
w: Option<&SC_DIM>,
|
||||
h: Option<&SC_DIM>,
|
||||
ix: Option<&UINT>,
|
||||
iy: Option<&UINT>,
|
||||
iw: Option<&UINT>,
|
||||
ih: Option<&UINT>,
|
||||
opacity: Option<&f32>,
|
||||
) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: coordinate space
|
||||
pub gWorldToScreen: extern "system" fn(hgfx: HGFX, inout_x: &mut SC_POS, inout_y: &mut SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gScreenToWorld: extern "system" fn(hgfx: HGFX, inout_x: &mut SC_POS, inout_y: &mut SC_POS) -> GRAPHIN_RESULT,
|
||||
|
||||
// SECTION: clipping
|
||||
pub gPushClipBox: extern "system" fn(hgfx: HGFX, x1: SC_POS, y1: SC_POS, x2: SC_POS, y2: SC_POS, opacity: f32) -> GRAPHIN_RESULT,
|
||||
|
||||
pub gPushClipPath: extern "system" fn(hgfx: HGFX, hpath: HPATH, opacity: f32) -> GRAPHIN_RESULT,
|
||||
|
||||
// pop clip layer previously set by gPushClipBox or gPushClipPath
|
||||
pub gPopClip: extern "system" fn(hgfx: HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
// image painter
|
||||
pub imagePaint: extern "system" fn(himg: HIMG, pPainter: ImagePaintFunction, prm: LPVOID) -> GRAPHIN_RESULT, // paint on image using graphics
|
||||
|
||||
// VALUE interface
|
||||
pub vWrapGfx: extern "system" fn(hgfx: HGFX, toValue: *mut VALUE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vWrapImage: extern "system" fn(himg: HIMG, toValue: *mut VALUE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vWrapPath: extern "system" fn(hpath: HPATH, toValue: *mut VALUE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vWrapText: extern "system" fn(htext: HTEXT, toValue: *mut VALUE) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vUnWrapGfx: extern "system" fn(fromValue: *const VALUE, phgfx: &mut HGFX) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vUnWrapImage: extern "system" fn(fromValue: *const VALUE, phimg: &mut HIMG) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vUnWrapPath: extern "system" fn(fromValue: *const VALUE, phpath: &mut HPATH) -> GRAPHIN_RESULT,
|
||||
|
||||
pub vUnWrapText: extern "system" fn(fromValue: *const VALUE, phtext: &mut HTEXT) -> GRAPHIN_RESULT,
|
||||
|
||||
// since 4.4.3.20
|
||||
pub gFlush: extern "system" fn(hgfx: HGFX) -> GRAPHIN_RESULT,
|
||||
}
|
||||
|
||||
pub type ImageWriteFunction = extern "system" fn(prm: LPVOID, data: LPCBYTE, data_length: UINT);
|
||||
pub type ImagePaintFunction = extern "system" fn(prm: LPVOID, hgfx: HGFX, width: UINT, height: UINT);
|
||||
118
libs/rust-sciter/src/capi/schandler.rs
Normal file
118
libs/rust-sciter/src/capi/schandler.rs
Normal file
@@ -0,0 +1,118 @@
|
||||
//! Native handler wrappers.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::{LPCVOID, LPVOID};
|
||||
|
||||
type Opaque = LPCVOID;
|
||||
|
||||
|
||||
/// Native wrapper for handlers which can be passed to foreign functions.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct NativeHandler {
|
||||
// pointer to handler
|
||||
handler: Opaque,
|
||||
|
||||
// pointer to handler destructor
|
||||
dtor: fn(param: Opaque),
|
||||
}
|
||||
|
||||
impl Drop for NativeHandler {
|
||||
fn drop(&mut self) {
|
||||
if !self.handler.is_null() {
|
||||
(self.dtor)(self.handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NativeHandler {
|
||||
fn default() -> Self {
|
||||
NativeHandler { handler: ::std::ptr::null(), dtor: NativeHandler::drop_it::<i32> }
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeHandler {
|
||||
|
||||
/// Construct boxed wrapper from handler object.
|
||||
pub fn from<T>(handler: T) -> NativeHandler {
|
||||
let boxed = Box::new(handler);
|
||||
let ptr = Box::into_raw(boxed);
|
||||
let dtor = NativeHandler::drop_it::<T>;
|
||||
return NativeHandler { handler: ptr as Opaque, dtor: dtor };
|
||||
}
|
||||
|
||||
/// Return a native pointer to handler wrapper.
|
||||
pub fn as_ptr(&self) -> LPCVOID {
|
||||
self.handler as LPCVOID
|
||||
}
|
||||
|
||||
/// Return a native pointer to handler wrapper.
|
||||
pub fn as_mut_ptr(&self) -> LPVOID {
|
||||
self.handler as LPVOID
|
||||
}
|
||||
|
||||
/// Access handler by reference.
|
||||
pub fn as_ref<T>(&self) -> &T {
|
||||
let pobj = self.handler as *const T;
|
||||
let boxed = unsafe { &*pobj };
|
||||
return boxed;
|
||||
}
|
||||
|
||||
/// Access handler by mutable reference.
|
||||
pub fn as_mut<T>(&mut self) -> &mut T {
|
||||
let pobj = self.handler as *mut T;
|
||||
let boxed = unsafe { &mut *pobj };
|
||||
return boxed;
|
||||
}
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
pub fn get_data<T>(ptr: &LPVOID) -> &mut T {
|
||||
assert!(!ptr.is_null());
|
||||
let obj = *ptr as *mut T;
|
||||
unsafe { &mut *obj}
|
||||
}
|
||||
|
||||
// Call destructor of handler.
|
||||
fn drop_it<T>(param: Opaque) {
|
||||
// reconstruct pointer to Box
|
||||
let pobj = param as *mut T;
|
||||
if !pobj.is_null() {
|
||||
// and drop it
|
||||
unsafe { Box::from_raw(pobj) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::NativeHandler;
|
||||
|
||||
struct Handler {
|
||||
pub i: i32,
|
||||
}
|
||||
|
||||
impl Drop for Handler {
|
||||
fn drop(&mut self) {
|
||||
println!("Handler::drop");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[test]
|
||||
fn test1() {
|
||||
{
|
||||
println!("\ncreate");
|
||||
let h = Handler { i: 7 };
|
||||
let p = NativeHandler::from(h);
|
||||
|
||||
println!("handler i {:?}", p.as_ref::<Handler>().i);
|
||||
println!("quit");
|
||||
}
|
||||
println!("done.");
|
||||
|
||||
// assert!(false);
|
||||
}
|
||||
|
||||
}
|
||||
462
libs/rust-sciter/src/capi/scmsg.rs
Normal file
462
libs/rust-sciter/src/capi/scmsg.rs
Normal file
@@ -0,0 +1,462 @@
|
||||
//! Sciter.Lite interface.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::{GFX_LAYER, ELEMENT_BITMAP_RECEIVER};
|
||||
use capi::scdom::HELEMENT;
|
||||
use capi::scbehavior::{MOUSE_BUTTONS, MOUSE_EVENTS, KEY_EVENTS};
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum SCITER_X_MSG_CODE
|
||||
{
|
||||
SXM_CREATE = 0,
|
||||
SXM_DESTROY = 1,
|
||||
SXM_SIZE = 2,
|
||||
SXM_PAINT = 3,
|
||||
SXM_RESOLUTION = 4,
|
||||
SXM_HEARTBIT = 5,
|
||||
SXM_MOUSE = 6,
|
||||
SXM_KEY = 7,
|
||||
SXM_FOCUS = 8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Common header of message structures passed to `SciterProcX`.
|
||||
pub struct SCITER_X_MSG
|
||||
{
|
||||
pub msg: SCITER_X_MSG_CODE,
|
||||
}
|
||||
|
||||
impl From<SCITER_X_MSG_CODE> for SCITER_X_MSG {
|
||||
fn from(code: SCITER_X_MSG_CODE) -> Self {
|
||||
Self { msg: code }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to create the specific Sciter backend.
|
||||
pub struct SCITER_X_MSG_CREATE
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
pub backend: GFX_LAYER,
|
||||
pub transparent: BOOL,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to destroy the current Sciter backend.
|
||||
pub struct SCITER_X_MSG_DESTROY
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about view resize.
|
||||
pub struct SCITER_X_MSG_SIZE
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
pub width: UINT,
|
||||
pub height: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about screen resolution change.
|
||||
pub struct SCITER_X_MSG_RESOLUTION
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
/// Pixels per inch.
|
||||
pub ppi: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about mouse input.
|
||||
pub struct SCITER_X_MSG_MOUSE
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
pub event: MOUSE_EVENTS,
|
||||
pub button: MOUSE_BUTTONS,
|
||||
pub modifiers: UINT,
|
||||
pub pos: POINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about keyboard input.
|
||||
pub struct SCITER_X_MSG_KEY
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
pub event: KEY_EVENTS,
|
||||
pub code: UINT,
|
||||
pub modifiers: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Message to notify Sciter about window focus change.
|
||||
pub struct SCITER_X_MSG_FOCUS
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
pub enter: BOOL,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
/// Give Sciter a chance to process animations, timers and other timed things.
|
||||
pub struct SCITER_X_MSG_HEARTBIT
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
|
||||
/// Absolute time in milliseconds.
|
||||
pub time: UINT,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// `SCITER_X_MSG_PAINT` rendering targets.
|
||||
pub enum SCITER_PAINT_TARGET_TYPE
|
||||
{
|
||||
/// Default target - OpenGL window surface.
|
||||
SPT_DEFAULT = 0,
|
||||
|
||||
/// Bitmap target.
|
||||
SPT_RECEIVER = 1,
|
||||
|
||||
/// `IDXGISurface` target (since 4.4.3.27).
|
||||
SPT_SURFACE = 2,
|
||||
}
|
||||
|
||||
/// Message to paint view to the provided target (HDC or callback).
|
||||
#[repr(C)]
|
||||
pub struct SCITER_X_MSG_PAINT
|
||||
{
|
||||
pub header: SCITER_X_MSG,
|
||||
pub element: HELEMENT,
|
||||
pub isFore: BOOL,
|
||||
pub targetType: SCITER_PAINT_TARGET_TYPE,
|
||||
|
||||
// union {
|
||||
// HDC or LPVOID
|
||||
pub context: LPVOID,
|
||||
pub callback: Option<ELEMENT_BITMAP_RECEIVER>,
|
||||
// }
|
||||
}
|
||||
|
||||
/// Sciter.Lite key codes.
|
||||
///
|
||||
/// The table matches the [GLFW keyboard keys](https://www.glfw.org/docs/3.3/group__keys.html).
|
||||
pub mod key_codes
|
||||
{
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
/// The same keys, but wrapped as a enum.
|
||||
pub enum KEYBOARD_CODES {
|
||||
KB_SPACE = 32,
|
||||
KB_APOSTROPHE = 39, /* ' */
|
||||
KB_COMMA = 44, /* , */
|
||||
// KB_QUOTE = KB_COMMA,
|
||||
KB_MINUS = 45, /* - */
|
||||
KB_PERIOD = 46, /* . */
|
||||
KB_SLASH = 47, /* / */
|
||||
KB_0 = 48,
|
||||
KB_1 = 49,
|
||||
KB_2 = 50,
|
||||
KB_3 = 51,
|
||||
KB_4 = 52,
|
||||
KB_5 = 53,
|
||||
KB_6 = 54,
|
||||
KB_7 = 55,
|
||||
KB_8 = 56,
|
||||
KB_9 = 57,
|
||||
KB_SEMICOLON = 59, /* ; */
|
||||
KB_EQUAL = 61, /* = */
|
||||
KB_A = 65,
|
||||
KB_B = 66,
|
||||
KB_C = 67,
|
||||
KB_D = 68,
|
||||
KB_E = 69,
|
||||
KB_F = 70,
|
||||
KB_G = 71,
|
||||
KB_H = 72,
|
||||
KB_I = 73,
|
||||
KB_J = 74,
|
||||
KB_K = 75,
|
||||
KB_L = 76,
|
||||
KB_M = 77,
|
||||
KB_N = 78,
|
||||
KB_O = 79,
|
||||
KB_P = 80,
|
||||
KB_Q = 81,
|
||||
KB_R = 82,
|
||||
KB_S = 83,
|
||||
KB_T = 84,
|
||||
KB_U = 85,
|
||||
KB_V = 86,
|
||||
KB_W = 87,
|
||||
KB_X = 88,
|
||||
KB_Y = 89,
|
||||
KB_Z = 90,
|
||||
KB_LEFT_BRACKET = 91, /* [ */
|
||||
// KB_LEFTBRACKET = KB_LEFT_BRACKET,
|
||||
KB_BACKSLASH = 92, /* \ */
|
||||
KB_RIGHT_BRACKET = 93, /* ] */
|
||||
// KB_RIGHTBRACKET = KB_RIGHT_BRACKET,
|
||||
KB_GRAVE_ACCENT = 96, /* ` */
|
||||
KB_WORLD_1 = 161, /* non-US #1 */
|
||||
// KB_DOT = KB_WORLD_1,
|
||||
KB_WORLD_2 = 162, /* non-US #2 */
|
||||
|
||||
/* Function keys */
|
||||
KB_ESCAPE = 256,
|
||||
KB_ENTER = 257,
|
||||
// KB_RETURN = KB_ENTER,
|
||||
KB_TAB = 258,
|
||||
KB_BACKSPACE = 259,
|
||||
// KB_BACK = KB_BACKSPACE,
|
||||
KB_INSERT = 260,
|
||||
KB_DELETE = 261,
|
||||
KB_RIGHT = 262,
|
||||
KB_LEFT = 263,
|
||||
KB_DOWN = 264,
|
||||
KB_UP = 265,
|
||||
KB_PAGE_UP = 266,
|
||||
// KB_PRIOR = KB_PAGE_UP,
|
||||
KB_PAGE_DOWN = 267,
|
||||
// KB_NEXT = KB_PAGE_DOWN,
|
||||
KB_HOME = 268,
|
||||
KB_END = 269,
|
||||
KB_CAPS_LOCK = 280,
|
||||
// KB_CAPITAL = KB_CAPS_LOCK,
|
||||
KB_SCROLL_LOCK = 281,
|
||||
// KB_SCROLL = KB_SCROLL_LOCK,
|
||||
KB_NUM_LOCK = 282,
|
||||
// KB_NUMLOCK = KB_NUM_LOCK,
|
||||
KB_PRINT_SCREEN = 283,
|
||||
KB_PAUSE = 284,
|
||||
KB_F1 = 290,
|
||||
KB_F2 = 291,
|
||||
KB_F3 = 292,
|
||||
KB_F4 = 293,
|
||||
KB_F5 = 294,
|
||||
KB_F6 = 295,
|
||||
KB_F7 = 296,
|
||||
KB_F8 = 297,
|
||||
KB_F9 = 298,
|
||||
KB_F10 = 299,
|
||||
KB_F11 = 300,
|
||||
KB_F12 = 301,
|
||||
KB_F13 = 302,
|
||||
KB_F14 = 303,
|
||||
KB_F15 = 304,
|
||||
KB_F16 = 305,
|
||||
KB_F17 = 306,
|
||||
KB_F18 = 307,
|
||||
KB_F19 = 308,
|
||||
KB_F20 = 309,
|
||||
KB_F21 = 310,
|
||||
KB_F22 = 311,
|
||||
KB_F23 = 312,
|
||||
KB_F24 = 313,
|
||||
KB_F25 = 314,
|
||||
KB_NUMPAD0 = 320,
|
||||
KB_NUMPAD1 = 321,
|
||||
KB_NUMPAD2 = 322,
|
||||
KB_NUMPAD3 = 323,
|
||||
KB_NUMPAD4 = 324,
|
||||
KB_NUMPAD5 = 325,
|
||||
KB_NUMPAD6 = 326,
|
||||
KB_NUMPAD7 = 327,
|
||||
KB_NUMPAD8 = 328,
|
||||
KB_NUMPAD9 = 329,
|
||||
KB_NUMPAD_DECIMAL = 330,
|
||||
// KB_DECIMAL = KB_NUMPAD_DECIMAL, KB_SEPARATOR = KB_DECIMAL,
|
||||
KB_NUMPAD_DIVIDE = 331,
|
||||
// KB_DIVIDE = KB_NUMPAD_DIVIDE,
|
||||
KB_NUMPAD_MULTIPLY = 332,
|
||||
// KB_MULTIPLY = KB_NUMPAD_MULTIPLY,
|
||||
KB_NUMPAD_SUBTRACT = 333,
|
||||
// KB_SUBTRACT = KB_NUMPAD_SUBTRACT,
|
||||
KB_NUMPAD_ADD = 334,
|
||||
// KB_ADD = KB_NUMPAD_ADD, KB_PLUS = KB_ADD,
|
||||
KB_NUMPAD_ENTER = 335,
|
||||
KB_NUMPAD_EQUAL = 336,
|
||||
KB_LEFT_SHIFT = 340,
|
||||
// KB_SHIFT = KB_LEFT_SHIFT,
|
||||
KB_LEFT_CONTROL = 341,
|
||||
// KB_CONTROL = KB_LEFT_CONTROL, KB_SHORTCUT = KB_CONTROL,
|
||||
KB_LEFT_ALT = 342,
|
||||
KB_LEFT_SUPER = 343,
|
||||
KB_RIGHT_SHIFT = 344,
|
||||
KB_RIGHT_CONTROL = 345,
|
||||
KB_RIGHT_ALT = 346,
|
||||
KB_RIGHT_SUPER = 347,
|
||||
KB_MENU = 348,
|
||||
}
|
||||
|
||||
pub const KB_SPACE : u32 = 32;
|
||||
pub const KB_APOSTROPHE : u32 = 39; /* ' */
|
||||
pub const KB_COMMA : u32 = 44; /* , */
|
||||
pub const KB_QUOTE : u32 = KB_COMMA;
|
||||
pub const KB_MINUS : u32 = 45; /* - */
|
||||
pub const KB_PERIOD : u32 = 46; /* . */
|
||||
pub const KB_SLASH : u32 = 47; /* / */
|
||||
|
||||
pub const KB_0 : u32 = 48;
|
||||
pub const KB_1 : u32 = 49;
|
||||
pub const KB_2 : u32 = 50;
|
||||
pub const KB_3 : u32 = 51;
|
||||
pub const KB_4 : u32 = 52;
|
||||
pub const KB_5 : u32 = 53;
|
||||
pub const KB_6 : u32 = 54;
|
||||
pub const KB_7 : u32 = 55;
|
||||
pub const KB_8 : u32 = 56;
|
||||
pub const KB_9 : u32 = 57;
|
||||
|
||||
pub const KB_SEMICOLON : u32 = 59; /* ; */
|
||||
pub const KB_EQUAL : u32 = 61; /* = */
|
||||
|
||||
pub const KB_A : u32 = 65;
|
||||
pub const KB_B : u32 = 66;
|
||||
pub const KB_C : u32 = 67;
|
||||
pub const KB_D : u32 = 68;
|
||||
pub const KB_E : u32 = 69;
|
||||
pub const KB_F : u32 = 70;
|
||||
pub const KB_G : u32 = 71;
|
||||
pub const KB_H : u32 = 72;
|
||||
pub const KB_I : u32 = 73;
|
||||
pub const KB_J : u32 = 74;
|
||||
pub const KB_K : u32 = 75;
|
||||
pub const KB_L : u32 = 76;
|
||||
pub const KB_M : u32 = 77;
|
||||
pub const KB_N : u32 = 78;
|
||||
pub const KB_O : u32 = 79;
|
||||
pub const KB_P : u32 = 80;
|
||||
pub const KB_Q : u32 = 81;
|
||||
pub const KB_R : u32 = 82;
|
||||
pub const KB_S : u32 = 83;
|
||||
pub const KB_T : u32 = 84;
|
||||
pub const KB_U : u32 = 85;
|
||||
pub const KB_V : u32 = 86;
|
||||
pub const KB_W : u32 = 87;
|
||||
pub const KB_X : u32 = 88;
|
||||
pub const KB_Y : u32 = 89;
|
||||
pub const KB_Z : u32 = 90;
|
||||
|
||||
pub const KB_LEFT_BRACKET : u32 = 91; /* [ */
|
||||
pub const KB_LEFTBRACKET : u32 = KB_LEFT_BRACKET;
|
||||
pub const KB_BACKSLASH : u32 = 92; /* \ */
|
||||
pub const KB_RIGHT_BRACKET : u32 = 93; /* ] */
|
||||
pub const KB_RIGHTBRACKET : u32 = KB_RIGHT_BRACKET;
|
||||
pub const KB_GRAVE_ACCENT : u32 = 96; /* ` */
|
||||
pub const KB_WORLD_1 : u32 = 161; /* non-US #1 */
|
||||
pub const KB_DOT : u32 = KB_WORLD_1;
|
||||
pub const KB_WORLD_2 : u32 = 162; /* non-US #2 */
|
||||
|
||||
/* Function keys */
|
||||
pub const KB_ESCAPE : u32 = 256;
|
||||
pub const KB_ENTER : u32 = 257;
|
||||
pub const KB_RETURN : u32 = KB_ENTER;
|
||||
pub const KB_TAB : u32 = 258;
|
||||
pub const KB_BACKSPACE : u32 = 259;
|
||||
pub const KB_BACK : u32 = KB_BACKSPACE;
|
||||
pub const KB_INSERT : u32 = 260;
|
||||
pub const KB_DELETE : u32 = 261;
|
||||
pub const KB_RIGHT : u32 = 262;
|
||||
pub const KB_LEFT : u32 = 263;
|
||||
pub const KB_DOWN : u32 = 264;
|
||||
pub const KB_UP : u32 = 265;
|
||||
pub const KB_PAGE_UP : u32 = 266;
|
||||
pub const KB_PRIOR : u32 = KB_PAGE_UP;
|
||||
pub const KB_PAGE_DOWN : u32 = 267;
|
||||
pub const KB_NEXT : u32 = KB_PAGE_DOWN;
|
||||
pub const KB_HOME : u32 = 268;
|
||||
pub const KB_END : u32 = 269;
|
||||
pub const KB_CAPS_LOCK : u32 = 280;
|
||||
pub const KB_CAPITAL : u32 = KB_CAPS_LOCK;
|
||||
pub const KB_SCROLL_LOCK : u32 = 281;
|
||||
pub const KB_SCROLL : u32 = KB_SCROLL_LOCK;
|
||||
pub const KB_NUM_LOCK : u32 = 282;
|
||||
pub const KB_NUMLOCK : u32 = KB_NUM_LOCK;
|
||||
pub const KB_PRINT_SCREEN : u32 = 283;
|
||||
pub const KB_PAUSE : u32 = 284;
|
||||
|
||||
pub const KB_F1 : u32 = 290;
|
||||
pub const KB_F2 : u32 = 291;
|
||||
pub const KB_F3 : u32 = 292;
|
||||
pub const KB_F4 : u32 = 293;
|
||||
pub const KB_F5 : u32 = 294;
|
||||
pub const KB_F6 : u32 = 295;
|
||||
pub const KB_F7 : u32 = 296;
|
||||
pub const KB_F8 : u32 = 297;
|
||||
pub const KB_F9 : u32 = 298;
|
||||
pub const KB_F10 : u32 = 299;
|
||||
pub const KB_F11 : u32 = 300;
|
||||
pub const KB_F12 : u32 = 301;
|
||||
pub const KB_F13 : u32 = 302;
|
||||
pub const KB_F14 : u32 = 303;
|
||||
pub const KB_F15 : u32 = 304;
|
||||
pub const KB_F16 : u32 = 305;
|
||||
pub const KB_F17 : u32 = 306;
|
||||
pub const KB_F18 : u32 = 307;
|
||||
pub const KB_F19 : u32 = 308;
|
||||
pub const KB_F20 : u32 = 309;
|
||||
pub const KB_F21 : u32 = 310;
|
||||
pub const KB_F22 : u32 = 311;
|
||||
pub const KB_F23 : u32 = 312;
|
||||
pub const KB_F24 : u32 = 313;
|
||||
pub const KB_F25 : u32 = 314;
|
||||
|
||||
pub const KB_NUMPAD0 : u32 = 320;
|
||||
pub const KB_NUMPAD1 : u32 = 321;
|
||||
pub const KB_NUMPAD2 : u32 = 322;
|
||||
pub const KB_NUMPAD3 : u32 = 323;
|
||||
pub const KB_NUMPAD4 : u32 = 324;
|
||||
pub const KB_NUMPAD5 : u32 = 325;
|
||||
pub const KB_NUMPAD6 : u32 = 326;
|
||||
pub const KB_NUMPAD7 : u32 = 327;
|
||||
pub const KB_NUMPAD8 : u32 = 328;
|
||||
pub const KB_NUMPAD9 : u32 = 329;
|
||||
|
||||
pub const KB_NUMPAD_DECIMAL : u32 = 330;
|
||||
pub const KB_DECIMAL : u32 = KB_NUMPAD_DECIMAL;
|
||||
pub const KB_SEPARATOR : u32 = KB_DECIMAL;
|
||||
pub const KB_NUMPAD_DIVIDE : u32 = 331;
|
||||
pub const KB_DIVIDE : u32 = KB_NUMPAD_DIVIDE;
|
||||
pub const KB_NUMPAD_MULTIPLY : u32 = 332;
|
||||
pub const KB_MULTIPLY : u32 = KB_NUMPAD_MULTIPLY;
|
||||
pub const KB_NUMPAD_SUBTRACT : u32 = 333;
|
||||
pub const KB_SUBTRACT : u32 = KB_NUMPAD_SUBTRACT;
|
||||
pub const KB_NUMPAD_ADD : u32 = 334;
|
||||
pub const KB_ADD : u32 = KB_NUMPAD_ADD;
|
||||
pub const KB_PLUS : u32 = KB_ADD;
|
||||
pub const KB_NUMPAD_ENTER : u32 = 335;
|
||||
pub const KB_NUMPAD_EQUAL : u32 = 336;
|
||||
|
||||
pub const KB_LEFT_SHIFT : u32 = 340;
|
||||
pub const KB_SHIFT : u32 = KB_LEFT_SHIFT;
|
||||
pub const KB_LEFT_CONTROL : u32 = 341;
|
||||
pub const KB_CONTROL : u32 = KB_LEFT_CONTROL;
|
||||
pub const KB_SHORTCUT : u32 = KB_CONTROL;
|
||||
pub const KB_LEFT_ALT : u32 = 342;
|
||||
pub const KB_LEFT_SUPER : u32 = 343;
|
||||
pub const KB_RIGHT_SHIFT : u32 = 344;
|
||||
pub const KB_RIGHT_CONTROL : u32 = 345;
|
||||
pub const KB_RIGHT_ALT : u32 = 346;
|
||||
pub const KB_RIGHT_SUPER : u32 = 347;
|
||||
pub const KB_MENU : u32 = 348;
|
||||
}
|
||||
223
libs/rust-sciter/src/capi/scom.rs
Normal file
223
libs/rust-sciter/src/capi/scom.rs
Normal file
@@ -0,0 +1,223 @@
|
||||
/*! Sciter Object Model (SOM passport), native C interface.
|
||||
|
||||
See https://sciter.com/native-code-exposure-to-script/
|
||||
and https://sciter.com/developers/for-native-gui-programmers/sciter-object-model/.
|
||||
|
||||
*/
|
||||
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
use capi::scvalue::VALUE;
|
||||
|
||||
/// An atom value that uniquely identifies the name being registered.
|
||||
pub type som_atom_t = u64;
|
||||
|
||||
|
||||
/// `som_asset_t` is a structure that a custom native object must be derived from.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct som_asset_t {
|
||||
pub(crate) isa: &'static som_asset_class_t,
|
||||
}
|
||||
|
||||
impl som_asset_t {
|
||||
pub(crate) fn get_passport(&self) -> *const som_passport_t {
|
||||
(self.isa.get_passport)(self as *const _ as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Is a pack of 4 pointers to functions that define the life time of an asset.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct som_asset_class_t {
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(thing: *mut som_asset_t) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(thing: *mut som_asset_t) -> i32,
|
||||
|
||||
/// Retrieves a pointer to a supported interface of an object.
|
||||
pub get_interface: extern "C" fn(thing: *mut som_asset_t, name: LPCSTR, out: *mut *mut som_asset_t) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut som_asset_t) -> *const som_passport_t,
|
||||
}
|
||||
|
||||
|
||||
/// Defines properties and methods of an asset.
|
||||
#[repr(C)]
|
||||
pub struct som_passport_t {
|
||||
/// Flags of an asset, see [`som_passport_flags`](enum.som_passport_flags.html).
|
||||
pub flags: u64,
|
||||
|
||||
/// The name of the class (asset type).
|
||||
pub name: som_atom_t,
|
||||
|
||||
/// Properties: `asset.prop`.
|
||||
///
|
||||
/// Must be a pointer to an array of structures:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use sciter::om::*;
|
||||
/// let mut pst = Box::new(som_passport_t::default());
|
||||
///
|
||||
/// type ObjectProps = [som_property_def_t; 2];
|
||||
/// let mut props = Box::new(ObjectProps::default());
|
||||
///
|
||||
/// let mut prop1 = &mut props[0];
|
||||
/// prop1.name = atom("age");
|
||||
///
|
||||
/// let mut prop2 = &mut props[1];
|
||||
/// prop2.name = atom("name");
|
||||
///
|
||||
/// pst.n_properties = 2;
|
||||
/// pst.properties = Box::into_raw(props) as *const _;
|
||||
/// ```
|
||||
|
||||
pub properties: *const som_property_def_t,
|
||||
|
||||
/// Properties count.
|
||||
pub n_properties: usize,
|
||||
|
||||
/// Methods: `asset.func()`
|
||||
///
|
||||
/// Must be a pointer to an array of structures,
|
||||
/// see [`properties`](struct.som_passport_t.html#structfield.properties) for an example.
|
||||
pub methods: *const som_method_def_t,
|
||||
|
||||
/// Methods count.
|
||||
pub n_methods: usize,
|
||||
|
||||
/// Index access: `var item = asset[key]`.
|
||||
pub item_getter: Option<som_item_getter_t>,
|
||||
|
||||
/// Index access: `asset[key] = item`.
|
||||
pub item_setter: Option<som_item_setter_t>,
|
||||
|
||||
/// Enumeration: `for(var item in asset)`.
|
||||
pub item_next: Option<som_item_next_t>,
|
||||
|
||||
/// Property access interceptor: `var val = asset.prop`.
|
||||
pub prop_getter: Option<som_any_prop_getter_t>,
|
||||
|
||||
/// Property set interceptor: `asset.prop = val`.
|
||||
pub prop_setter: Option<som_any_prop_setter_t>,
|
||||
}
|
||||
|
||||
/// Empty passport.
|
||||
impl Default for som_passport_t {
|
||||
fn default() -> Self {
|
||||
use std::ptr;
|
||||
Self {
|
||||
flags: 0,
|
||||
name: 0,
|
||||
|
||||
prop_getter: None,
|
||||
prop_setter: None,
|
||||
|
||||
item_getter: None,
|
||||
item_setter: None,
|
||||
item_next: None,
|
||||
|
||||
properties: ptr::null(),
|
||||
n_properties: 0,
|
||||
|
||||
methods: ptr::null(),
|
||||
n_methods: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// [`som_passport_t`](struct.som_passport_t.html#structfield.flags) flags.
|
||||
#[repr(u64)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum som_passport_flags {
|
||||
/// Not extendable.
|
||||
SEALED = 0,
|
||||
|
||||
/// Extendable.
|
||||
///
|
||||
/// An asset may have new properties added by script.
|
||||
EXTENDABLE = 1,
|
||||
}
|
||||
|
||||
|
||||
/// Property of an asset.
|
||||
#[repr(C)]
|
||||
pub struct som_property_def_t {
|
||||
pub reserved: LPVOID,
|
||||
|
||||
/// Property name.
|
||||
pub name: som_atom_t,
|
||||
|
||||
/// Property getter: `var val = asset.prop`.
|
||||
pub getter: Option<som_prop_getter_t>,
|
||||
|
||||
/// Property setter: `asset.prop = val`.
|
||||
pub setter: Option<som_prop_setter_t>,
|
||||
}
|
||||
|
||||
/// Empty property.
|
||||
impl Default for som_property_def_t {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
reserved: std::ptr::null_mut(),
|
||||
name: 0,
|
||||
getter: None,
|
||||
setter: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Method of an asset.
|
||||
#[repr(C)]
|
||||
pub struct som_method_def_t {
|
||||
pub reserved: LPVOID,
|
||||
|
||||
/// Method name.
|
||||
pub name: som_atom_t,
|
||||
|
||||
/// Parameters count.
|
||||
///
|
||||
/// The actual arguments count can be lesser then specified here:
|
||||
///
|
||||
/// ```tiscript,ignore
|
||||
/// function asset.func(a,b,c); // native asset method accepts 3 parameters
|
||||
///
|
||||
/// asset.func("one"); // call with only one parameter.
|
||||
/// ```
|
||||
pub params: usize,
|
||||
|
||||
/// Method body.
|
||||
pub func: Option<som_method_t>,
|
||||
}
|
||||
|
||||
/// Empty method.
|
||||
impl Default for som_method_def_t {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
reserved: std::ptr::null_mut(),
|
||||
name: 0,
|
||||
params: 0,
|
||||
func: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type som_dispose_t = extern "C" fn(thing: *mut som_asset_t);
|
||||
|
||||
type som_prop_getter_t = extern "C" fn(thing: *mut som_asset_t, p_value: &mut VALUE) -> BOOL;
|
||||
type som_prop_setter_t = extern "C" fn(thing: *mut som_asset_t, p_value: &VALUE) -> BOOL;
|
||||
|
||||
type som_any_prop_getter_t = extern "C" fn(thing: *mut som_asset_t, propSymbol: som_atom_t, p_value: &mut VALUE) -> BOOL;
|
||||
type som_any_prop_setter_t = extern "C" fn(thing: *mut som_asset_t, propSymbol: som_atom_t, p_value: &VALUE) -> BOOL;
|
||||
|
||||
type som_item_getter_t = extern "C" fn(thing: *mut som_asset_t, p_key: &VALUE, p_value: &mut VALUE) -> BOOL;
|
||||
type som_item_setter_t = extern "C" fn(thing: *mut som_asset_t, p_key: &VALUE, p_value: &VALUE) -> BOOL;
|
||||
|
||||
type som_item_next_t = extern "C" fn(thing: *mut som_asset_t, p_idx: &mut VALUE, p_value: &mut VALUE) -> BOOL;
|
||||
|
||||
type som_method_t = extern "C" fn(thing: *mut som_asset_t, argc: u32, argv: *const VALUE, p_result: &mut VALUE) -> BOOL;
|
||||
184
libs/rust-sciter/src/capi/screquest.rs
Normal file
184
libs/rust-sciter/src/capi/screquest.rs
Normal file
@@ -0,0 +1,184 @@
|
||||
/*! Handling all attributes of requests (GET/POST/PUT/DELETE) sent by
|
||||
[`Element.request()`](https://sciter.com/docs/content/sciter/Element.htm) and
|
||||
[`View.request()`](https://sciter.com/docs/content/sciter/View.htm)
|
||||
functions and other load requests.
|
||||
|
||||
*/
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
use capi::sctypes::{UINT, LPVOID, LPCBYTE, LPCSTR, LPCWSTR};
|
||||
use capi::scdef::{LPCSTR_RECEIVER, LPCWSTR_RECEIVER, LPCBYTE_RECEIVER};
|
||||
pub use capi::scdef::RESOURCE_TYPE;
|
||||
|
||||
MAKE_HANDLE!(#[doc = "Request native handle."] HREQUEST, _HREQUEST);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// Type of the result value for Sciter Request functions.
|
||||
pub enum REQUEST_RESULT {
|
||||
/// E.g. not enough memory.
|
||||
PANIC = -1,
|
||||
/// Success.
|
||||
OK = 0,
|
||||
/// Bad parameter.
|
||||
BAD_PARAM = 1,
|
||||
/// Operation failed, e.g. index out of bounds.
|
||||
FAILURE = 2,
|
||||
/// The platform does not support requested feature.
|
||||
NOTSUPPORTED = 3,
|
||||
}
|
||||
|
||||
impl std::error::Error for REQUEST_RESULT {}
|
||||
|
||||
impl std::fmt::Display for REQUEST_RESULT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// Request methods.
|
||||
pub enum REQUEST_METHOD {
|
||||
/// Sends a plain HTTP GET request.
|
||||
///
|
||||
/// Url-encoded params (if any) are appended to the url in order to form the request.
|
||||
GET = 1,
|
||||
/// Sends an HTTP POST request.
|
||||
///
|
||||
/// The params are serialized as `Content-Type: application/x-www-form-urlencoded;charset=utf-8`.
|
||||
POST = 2,
|
||||
/// Sends an HTTP PUT request.
|
||||
///
|
||||
/// The params are serialized as `Content-Type: multipart/form-data; boundary= ...`.
|
||||
PUT = 3,
|
||||
/// Sends an HTTP DELETE request.
|
||||
DELETE = 4,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// HTTP methods for the [`Element::send_request`](../dom/struct.Element.html#method.send_request).
|
||||
pub enum REQUEST_TYPE {
|
||||
/// Asynchronous GET.
|
||||
AsyncGet,
|
||||
/// Asynchronous POST.
|
||||
AsyncPost,
|
||||
/// Synchronous GET.
|
||||
Get,
|
||||
/// Synchronous POST.
|
||||
Post,
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// Completion state of a request.
|
||||
pub enum REQUEST_STATE {
|
||||
/// The request is pending.
|
||||
PENDING = 0,
|
||||
/// Completed successfully.
|
||||
SUCCESS = 1,
|
||||
/// Completed with failure.
|
||||
FAILURE = 2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct REQUEST_PARAM {
|
||||
pub name: LPCWSTR,
|
||||
pub value: LPCWSTR,
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct SciterRequestAPI
|
||||
{
|
||||
/// a.k.a AddRef()
|
||||
pub RequestUse: extern "system" fn (rq: HREQUEST) -> REQUEST_RESULT,
|
||||
|
||||
/// a.k.a Release()
|
||||
pub RequestUnUse: extern "system" fn (rq: HREQUEST) -> REQUEST_RESULT,
|
||||
|
||||
/// get requested URL
|
||||
pub RequestUrl: extern "system" fn (rq: HREQUEST, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get real, content URL (after possible redirection)
|
||||
pub RequestContentUrl: extern "system" fn (rq: HREQUEST, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get requested data type
|
||||
pub RequestGetRequestType: extern "system" fn (rq: HREQUEST, pType: &mut REQUEST_METHOD) -> REQUEST_RESULT,
|
||||
|
||||
/// get requested data type
|
||||
pub RequestGetRequestedDataType: extern "system" fn (rq: HREQUEST, pData: &mut RESOURCE_TYPE) -> REQUEST_RESULT,
|
||||
|
||||
/// get received data type, string, mime type
|
||||
pub RequestGetReceivedDataType: extern "system" fn (rq: HREQUEST, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
|
||||
/// get number of request parameters passed
|
||||
pub RequestGetNumberOfParameters: extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth request parameter name
|
||||
pub RequestGetNthParameterName: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth request parameter value
|
||||
pub RequestGetNthParameterValue: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get request times , ended - started = milliseconds to get the requst
|
||||
pub RequestGetTimes: extern "system" fn (rq: HREQUEST, pStarted: &mut UINT, pEnded: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get number of request headers
|
||||
pub RequestGetNumberOfRqHeaders: extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth request header name
|
||||
pub RequestGetNthRqHeaderName: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth request header value
|
||||
pub RequestGetNthRqHeaderValue: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get number of response headers
|
||||
pub RequestGetNumberOfRspHeaders: extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth response header name
|
||||
pub RequestGetNthRspHeaderName: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get nth response header value
|
||||
pub RequestGetNthRspHeaderValue: extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get completion status (CompletionStatus - http response code : 200, 404, etc.)
|
||||
pub RequestGetCompletionStatus: extern "system" fn (rq: HREQUEST, pState: &mut REQUEST_STATE, pCompletionStatus: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// get proxy host
|
||||
pub RequestGetProxyHost: extern "system" fn (rq: HREQUEST, rcv: LPCSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
|
||||
/// get proxy port
|
||||
pub RequestGetProxyPort: extern "system" fn (rq: HREQUEST, pPort: &mut UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// mark reequest as complete with status and data
|
||||
pub RequestSetSucceeded: extern "system" fn (rq: HREQUEST, status: UINT, dataOrNull: LPCBYTE, dataLength: UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// mark reequest as complete with failure and optional data
|
||||
pub RequestSetFailed: extern "system" fn (rq: HREQUEST, status: UINT, dataOrNull: LPCBYTE, dataLength: UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// append received data chunk
|
||||
pub RequestAppendDataChunk: extern "system" fn (rq: HREQUEST, data: LPCBYTE, dataLength: UINT) -> REQUEST_RESULT,
|
||||
|
||||
/// set request header (single item)
|
||||
pub RequestSetRqHeader: extern "system" fn (rq: HREQUEST, name: LPCWSTR, value: LPCWSTR) -> REQUEST_RESULT,
|
||||
|
||||
/// set respone header (single item)
|
||||
pub RequestSetRspHeader: extern "system" fn (rq: HREQUEST, name: LPCWSTR, value: LPCWSTR) -> REQUEST_RESULT,
|
||||
|
||||
/// set received data type, string, mime type
|
||||
pub RequestSetReceivedDataType: extern "system" fn (rq: HREQUEST, _type: LPCSTR) -> REQUEST_RESULT,
|
||||
|
||||
/// set received data encoding, string
|
||||
pub RequestSetReceivedDataEncoding: extern "system" fn (rq: HREQUEST, encoding: LPCSTR) -> REQUEST_RESULT,
|
||||
|
||||
/// get received (so far) data
|
||||
pub RequestGetData: extern "system" fn (rq: HREQUEST, rcv: LPCBYTE_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT,
|
||||
}
|
||||
15
libs/rust-sciter/src/capi/sctiscript.rs
Normal file
15
libs/rust-sciter/src/capi/sctiscript.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
//! TIScript Virtual Machine Runtime.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
use capi::sctypes::{LPVOID, UINT64};
|
||||
|
||||
MAKE_HANDLE!(#[doc = "TIScript VM native handle."] HVM, _HVM);
|
||||
|
||||
pub type tiscript_value = UINT64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct tiscript_native_interface
|
||||
{
|
||||
create_vm: LPVOID,
|
||||
}
|
||||
127
libs/rust-sciter/src/capi/sctypes.rs
Normal file
127
libs/rust-sciter/src/capi/sctypes.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
//! Sciter platform-dependent types.
|
||||
|
||||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use self::libc::*;
|
||||
|
||||
|
||||
// common
|
||||
MAKE_HANDLE!(#[doc = "Window native handle."] HWINDOW, _HWINDOW); // HWND or NSView* or GtkWidget*
|
||||
MAKE_HANDLE!(#[doc = "Archive native handle."] HSARCHIVE, _HSARCHIVE);
|
||||
|
||||
pub type BYTE = u8;
|
||||
pub type INT = i32;
|
||||
pub type LONG = i32;
|
||||
pub type UINT = u32;
|
||||
pub type INT64 = i64;
|
||||
pub type UINT64 = u64;
|
||||
|
||||
pub type FLOAT_VALUE = f64;
|
||||
|
||||
pub type WPARAM = size_t;
|
||||
pub type LPARAM = ssize_t;
|
||||
|
||||
pub type UINT_PTR = uintptr_t;
|
||||
pub type LRESULT = ssize_t;
|
||||
|
||||
pub type CHAR = c_char;
|
||||
pub type LPSTR = *mut CHAR;
|
||||
pub type LPCSTR = *const CHAR;
|
||||
|
||||
pub type WCHAR = u16;
|
||||
pub type LPWSTR = *mut WCHAR;
|
||||
pub type LPCWSTR = *const WCHAR;
|
||||
|
||||
pub type LPCBYTE = *const BYTE;
|
||||
pub type LPUINT = *mut UINT;
|
||||
|
||||
pub type VOID = c_void;
|
||||
pub type LPVOID = *mut VOID;
|
||||
pub type LPCVOID = *const VOID;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub type BOOL = i32;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub type BOOL = i8;
|
||||
|
||||
pub type PBOOL = *mut BOOL;
|
||||
|
||||
/// Defines the coordinates of the upper-left and lower-right corners of a rectangle.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct RECT {
|
||||
pub left: LONG,
|
||||
pub top: LONG,
|
||||
pub right: LONG,
|
||||
pub bottom: LONG,
|
||||
}
|
||||
pub type LPRECT = *mut RECT;
|
||||
pub type LPCRECT = *const RECT;
|
||||
|
||||
impl RECT {
|
||||
/// Calculate the height of the rect.
|
||||
pub fn height(&self) -> LONG {
|
||||
self.bottom - self.top
|
||||
}
|
||||
|
||||
/// Calculate the width of the rect.
|
||||
pub fn width(&self) -> LONG {
|
||||
self.right - self.left
|
||||
}
|
||||
|
||||
/// Return the size of the rect in width and height form.
|
||||
pub fn size(&self) -> SIZE {
|
||||
SIZE {
|
||||
cx: self.width(),
|
||||
cy: self.height(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the top-left point of the rect.
|
||||
pub fn topleft(&self) -> POINT {
|
||||
POINT {
|
||||
x: self.left,
|
||||
y: self.top,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the `x` and `y` coordinates of a point.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct POINT {
|
||||
pub x: LONG,
|
||||
pub y: LONG,
|
||||
}
|
||||
pub type LPPOINT = *mut POINT;
|
||||
|
||||
/// Specifies the width and height of a rectangle.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct SIZE {
|
||||
pub cx: LONG,
|
||||
pub cy: LONG,
|
||||
}
|
||||
pub type LPSIZE = *mut SIZE;
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct MSG {
|
||||
pub hwnd: HWINDOW,
|
||||
pub message: UINT,
|
||||
pub wParam: WPARAM,
|
||||
pub lParam: LPARAM,
|
||||
pub time: UINT,
|
||||
pub pt: POINT,
|
||||
}
|
||||
#[cfg(windows)]
|
||||
pub type LPMSG = *mut MSG;
|
||||
|
||||
124
libs/rust-sciter/src/capi/scvalue.rs
Normal file
124
libs/rust-sciter/src/capi/scvalue.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
//! Sciter value, native C interface.
|
||||
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use capi::sctypes::*;
|
||||
|
||||
/// A JSON value.
|
||||
///
|
||||
/// An opaque union that can hold different types of values: numbers, strings, arrays, objects, etc.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VALUE
|
||||
{
|
||||
/// Value type.
|
||||
pub t: VALUE_TYPE,
|
||||
|
||||
/// Value unit type.
|
||||
pub u: UINT,
|
||||
|
||||
/// Value data.
|
||||
pub d: UINT64,
|
||||
}
|
||||
|
||||
impl Default for VALUE {
|
||||
fn default() -> Self {
|
||||
VALUE { t: VALUE_TYPE::T_UNDEFINED, u: 0, d: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_RESULT
|
||||
{
|
||||
OK_TRUE = -1,
|
||||
OK = 0,
|
||||
BAD_PARAMETER = 1,
|
||||
INCOMPATIBLE_TYPE = 2,
|
||||
}
|
||||
|
||||
impl std::error::Error for VALUE_RESULT {}
|
||||
|
||||
impl std::fmt::Display for VALUE_RESULT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_STRING_CVT_TYPE {
|
||||
SIMPLE = 0,
|
||||
JSON_LITERAL = 1,
|
||||
JSON_MAP = 2,
|
||||
XJSON_LITERAL = 3,
|
||||
}
|
||||
|
||||
|
||||
/// Type identifier of the value.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_TYPE {
|
||||
T_UNDEFINED = 0,
|
||||
T_NULL = 1,
|
||||
T_BOOL,
|
||||
T_INT,
|
||||
T_FLOAT,
|
||||
T_STRING,
|
||||
T_DATE,
|
||||
T_CURRENCY,
|
||||
T_LENGTH,
|
||||
T_ARRAY,
|
||||
T_MAP,
|
||||
T_FUNCTION,
|
||||
T_BYTES,
|
||||
T_OBJECT,
|
||||
T_DOM_OBJECT,
|
||||
T_RESOURCE,
|
||||
T_RANGE,
|
||||
T_DURATION,
|
||||
T_ANGLE,
|
||||
T_COLOR,
|
||||
T_ENUM,
|
||||
T_ASSET,
|
||||
|
||||
T_UNKNOWN,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_UNIT_UNDEFINED
|
||||
{
|
||||
UT_NOTHING = 1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_UNIT_TYPE_STRING
|
||||
{
|
||||
STRING = 0, // string
|
||||
ERROR = 1, // is an error string
|
||||
SECURE = 2, // secure string ("wiped" on destroy)
|
||||
URL = 3, // url(...)
|
||||
SELECTOR = 4, // selector(...)
|
||||
FILE = 0xfffe, // file name
|
||||
SYMBOL = 0xffff, // symbol in tiscript sense
|
||||
}
|
||||
|
||||
// Sciter or TIScript specific
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialOrd, PartialEq)]
|
||||
pub enum VALUE_UNIT_TYPE_OBJECT
|
||||
{
|
||||
ARRAY = 0, // type T_OBJECT of type Array
|
||||
OBJECT = 1, // type T_OBJECT of type Object
|
||||
CLASS = 2, // type T_OBJECT of type Class (class or namespace)
|
||||
NATIVE = 3, // type T_OBJECT of native Type with data slot (LPVOID)
|
||||
FUNCTION = 4, // type T_OBJECT of type Function
|
||||
ERROR = 5, // type T_OBJECT of type Error
|
||||
}
|
||||
|
||||
pub type NATIVE_FUNCTOR_INVOKE = extern "C" fn (tag: LPVOID, argc: UINT, argv: *const VALUE, retval: * mut VALUE);
|
||||
pub type NATIVE_FUNCTOR_RELEASE = extern "C" fn (tag: LPVOID);
|
||||
1570
libs/rust-sciter/src/dom.rs
Normal file
1570
libs/rust-sciter/src/dom.rs
Normal file
File diff suppressed because it is too large
Load Diff
306
libs/rust-sciter/src/eventhandler.rs
Normal file
306
libs/rust-sciter/src/eventhandler.rs
Normal file
@@ -0,0 +1,306 @@
|
||||
use capi::sctypes::*;
|
||||
use capi::scbehavior::*;
|
||||
use capi::scdom::{HELEMENT};
|
||||
use value::Value;
|
||||
use dom::event::EventHandler;
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct WindowHandler<T>
|
||||
{
|
||||
pub hwnd: HWINDOW,
|
||||
pub handler: T,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct BoxedHandler {
|
||||
pub handler: Box<dyn EventHandler>,
|
||||
}
|
||||
|
||||
fn is_detach_event(evtg: UINT, params: LPVOID) -> bool {
|
||||
let evtg : EVENT_GROUPS = unsafe { ::std::mem::transmute(evtg) };
|
||||
if evtg == EVENT_GROUPS::HANDLE_INITIALIZATION {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const INITIALIZATION_EVENTS;
|
||||
let cmd = unsafe { *scnm };
|
||||
if cmd == INITIALIZATION_EVENTS::BEHAVIOR_DETACH {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) extern "system" fn _event_handler_window_proc<T: EventHandler>(tag: LPVOID, _he: ::capi::scdom::HELEMENT, evtg: UINT, params: LPVOID) -> BOOL
|
||||
{
|
||||
let boxed = tag as *mut WindowHandler<T>;
|
||||
let tuple: &mut WindowHandler<T> = unsafe { &mut *boxed };
|
||||
|
||||
let hroot: HELEMENT = if let Ok(root) = ::dom::Element::from_window(tuple.hwnd) {
|
||||
root.as_ptr()
|
||||
} else {
|
||||
::std::ptr::null_mut()
|
||||
};
|
||||
|
||||
// custom initialization (because there is no DOM in plain window)
|
||||
if is_detach_event(evtg, params) {
|
||||
tuple.handler.detached(hroot);
|
||||
|
||||
// here we drop our tuple
|
||||
let ptr = unsafe { Box::from_raw(boxed) };
|
||||
drop(ptr);
|
||||
|
||||
return true as BOOL;
|
||||
}
|
||||
|
||||
process_events(&mut tuple.handler, hroot, evtg, params)
|
||||
}
|
||||
|
||||
pub(crate) extern "system" fn _event_handler_behavior_proc(tag: LPVOID, he: HELEMENT, evtg: UINT, params: LPVOID) -> BOOL {
|
||||
// reconstruct pointer to Handler
|
||||
let boxed = tag as *mut BoxedHandler;
|
||||
let me = unsafe { &mut *boxed };
|
||||
let me = &mut *me.handler;
|
||||
|
||||
if is_detach_event(evtg, params) {
|
||||
me.detached(he);
|
||||
|
||||
// here we drop our handler
|
||||
let ptr = unsafe { Box::from_raw(boxed) };
|
||||
drop(ptr);
|
||||
|
||||
return true as BOOL;
|
||||
}
|
||||
|
||||
process_events(me, he, evtg, params)
|
||||
}
|
||||
|
||||
pub(crate) extern "system" fn _event_handler_proc<T: EventHandler>(tag: LPVOID, he: HELEMENT, evtg: UINT, params: LPVOID) -> BOOL
|
||||
{
|
||||
// reconstruct pointer to Handler
|
||||
let boxed = tag as *mut T;
|
||||
let me = unsafe { &mut *boxed };
|
||||
|
||||
if is_detach_event(evtg, params) {
|
||||
me.detached(he);
|
||||
|
||||
// here we drop our handler
|
||||
let ptr = unsafe { Box::from_raw(boxed) };
|
||||
drop(ptr);
|
||||
|
||||
return true as BOOL;
|
||||
}
|
||||
|
||||
process_events(me, he, evtg, params)
|
||||
}
|
||||
|
||||
fn process_events(me: &mut dyn EventHandler, he: HELEMENT, evtg: UINT, params: LPVOID) -> BOOL
|
||||
{
|
||||
let evtg : EVENT_GROUPS = unsafe { ::std::mem::transmute(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);
|
||||
}
|
||||
|
||||
let result = match evtg {
|
||||
|
||||
EVENT_GROUPS::SUBSCRIPTIONS_REQUEST => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *mut EVENT_GROUPS;
|
||||
let nm = unsafe {&mut *scnm};
|
||||
let handled = me.get_subscription();
|
||||
if let Some(needed) = handled {
|
||||
*nm = needed;
|
||||
}
|
||||
handled.is_some()
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_INITIALIZATION => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *mut INITIALIZATION_PARAMS;
|
||||
let nm = unsafe { &mut *scnm };
|
||||
match nm.cmd {
|
||||
INITIALIZATION_EVENTS::BEHAVIOR_DETACH => {
|
||||
me.detached(he);
|
||||
},
|
||||
|
||||
INITIALIZATION_EVENTS::BEHAVIOR_ATTACH => {
|
||||
me.attached(he);
|
||||
},
|
||||
};
|
||||
true
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_SOM => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *mut SOM_PARAMS;
|
||||
let nm = unsafe { &mut *scnm };
|
||||
match nm.cmd {
|
||||
SOM_EVENTS::SOM_GET_PASSPORT => {
|
||||
if let Some(asset) = me.get_asset() {
|
||||
nm.result.passport = asset.get_passport();
|
||||
return true as BOOL;
|
||||
}
|
||||
},
|
||||
|
||||
SOM_EVENTS::SOM_GET_ASSET => {
|
||||
if let Some(asset) = me.get_asset() {
|
||||
nm.result.asset = asset;
|
||||
return true as BOOL;
|
||||
}
|
||||
},
|
||||
};
|
||||
false
|
||||
},
|
||||
|
||||
|
||||
EVENT_GROUPS::HANDLE_BEHAVIOR_EVENT => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const BEHAVIOR_EVENT_PARAMS;
|
||||
let nm = unsafe { &*scnm };
|
||||
|
||||
use dom::event::EventReason;
|
||||
let code :BEHAVIOR_EVENTS = unsafe{ ::std::mem::transmute(nm.cmd & 0x0_0FFF) };
|
||||
let phase: PHASE_MASK = unsafe { ::std::mem::transmute(nm.cmd & 0xFFFF_F000) };
|
||||
let reason = match code {
|
||||
BEHAVIOR_EVENTS::EDIT_VALUE_CHANGED | BEHAVIOR_EVENTS::EDIT_VALUE_CHANGING => {
|
||||
let reason: EDIT_CHANGED_REASON = unsafe{ ::std::mem::transmute(nm.reason as UINT) };
|
||||
EventReason::EditChanged(reason)
|
||||
},
|
||||
|
||||
BEHAVIOR_EVENTS::VIDEO_BIND_RQ => {
|
||||
EventReason::VideoBind(nm.reason as LPVOID)
|
||||
}
|
||||
|
||||
_ => {
|
||||
let reason: CLICK_REASON = unsafe{ ::std::mem::transmute(nm.reason as UINT) };
|
||||
EventReason::General(reason)
|
||||
}
|
||||
};
|
||||
|
||||
if he.is_null() && code != BEHAVIOR_EVENTS::MEDIA_CHANGED {
|
||||
eprintln!("[sciter] warning! null element for {:?}:{:?}", evtg, code);
|
||||
}
|
||||
|
||||
if phase == PHASE_MASK::SINKING { // catch this only once
|
||||
match code {
|
||||
BEHAVIOR_EVENTS::DOCUMENT_COMPLETE => {
|
||||
me.document_complete(he, nm.heTarget);
|
||||
},
|
||||
BEHAVIOR_EVENTS::DOCUMENT_CLOSE => {
|
||||
me.document_close(he, nm.heTarget);
|
||||
},
|
||||
_ => ()
|
||||
};
|
||||
}
|
||||
|
||||
let handled = me.on_event(he, nm.he, nm.heTarget, code, phase, reason);
|
||||
handled
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_SCRIPTING_METHOD_CALL => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *mut SCRIPTING_METHOD_PARAMS;
|
||||
let nm = unsafe { &mut *scnm };
|
||||
let name = u2s!(nm.name);
|
||||
let argv = unsafe { Value::unpack_from(nm.argv, nm.argc) };
|
||||
let rv = me.on_script_call(he, &name, &argv);
|
||||
let handled = if let Some(v) = rv {
|
||||
v.pack_to(&mut nm.result);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
handled
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_METHOD_CALL => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const METHOD_PARAMS;
|
||||
let nm = unsafe { & *scnm };
|
||||
let code: BEHAVIOR_METHOD_IDENTIFIERS = unsafe { ::std::mem::transmute((*nm).method) };
|
||||
use capi::scbehavior::BEHAVIOR_METHOD_IDENTIFIERS::*;
|
||||
|
||||
// output values
|
||||
let mut method_value = Value::new();
|
||||
let mut is_empty = false;
|
||||
|
||||
let handled = {
|
||||
|
||||
// unpack method parameters
|
||||
use dom::event::MethodParams;
|
||||
let reason = match code {
|
||||
DO_CLICK => {
|
||||
MethodParams::Click
|
||||
},
|
||||
IS_EMPTY => {
|
||||
MethodParams::IsEmpty(&mut is_empty)
|
||||
},
|
||||
GET_VALUE => {
|
||||
MethodParams::GetValue(&mut method_value)
|
||||
},
|
||||
SET_VALUE => {
|
||||
// Value from Sciter.
|
||||
let payload = params as *const VALUE_PARAMS;
|
||||
let pm = unsafe { & *payload };
|
||||
MethodParams::SetValue(Value::from(&pm.value))
|
||||
},
|
||||
|
||||
_ => {
|
||||
MethodParams::Custom((*nm).method, params)
|
||||
},
|
||||
};
|
||||
|
||||
// call event handler
|
||||
let handled = me.on_method_call(he, reason);
|
||||
handled
|
||||
};
|
||||
|
||||
if handled {
|
||||
// Pack values back to Sciter.
|
||||
match code {
|
||||
GET_VALUE => {
|
||||
let payload = params as *mut VALUE_PARAMS;
|
||||
let pm = unsafe { &mut *payload };
|
||||
method_value.pack_to(&mut pm.value);
|
||||
},
|
||||
|
||||
IS_EMPTY => {
|
||||
let payload = params as *mut IS_EMPTY_PARAMS;
|
||||
let pm = unsafe { &mut *payload };
|
||||
pm.is_empty = is_empty as UINT;
|
||||
},
|
||||
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
// we've done here
|
||||
handled
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_TIMER => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const TIMER_PARAMS;
|
||||
let nm = unsafe { & *scnm };
|
||||
let handled = me.on_timer(he, nm.timerId as u64);
|
||||
handled
|
||||
},
|
||||
|
||||
EVENT_GROUPS::HANDLE_DRAW => {
|
||||
assert!(!params.is_null());
|
||||
let scnm = params as *const DRAW_PARAMS;
|
||||
let nm = unsafe { & *scnm };
|
||||
let handled = me.on_draw(he, nm.gfx, &nm.area, nm.layer);
|
||||
handled
|
||||
},
|
||||
|
||||
// unknown `EVENT_GROUPS` notification
|
||||
_ => {
|
||||
eprintln!("[sciter] warning! unknown event group {:04X}", evtg as u32);
|
||||
false
|
||||
},
|
||||
};
|
||||
return result as BOOL;
|
||||
}
|
||||
1101
libs/rust-sciter/src/graphics.rs
Normal file
1101
libs/rust-sciter/src/graphics.rs
Normal file
File diff suppressed because it is too large
Load Diff
585
libs/rust-sciter/src/host.rs
Normal file
585
libs/rust-sciter/src/host.rs
Normal file
@@ -0,0 +1,585 @@
|
||||
//! Sciter host application helpers.
|
||||
|
||||
use ::{_API};
|
||||
use capi::scdef::SCITER_RT_OPTIONS;
|
||||
use capi::sctypes::*;
|
||||
use capi::screquest::HREQUEST;
|
||||
use capi::schandler::NativeHandler;
|
||||
use dom::event::EventHandler;
|
||||
use eventhandler::*;
|
||||
use value::{Value};
|
||||
|
||||
pub use capi::scdef::{LOAD_RESULT, OUTPUT_SUBSYTEMS, OUTPUT_SEVERITY};
|
||||
pub use capi::scdef::{SCN_LOAD_DATA, SCN_DATA_LOADED, SCN_ATTACH_BEHAVIOR, SCN_INVALIDATE_RECT};
|
||||
|
||||
|
||||
/// A specialized `Result` type for Sciter host operations.
|
||||
pub type Result<T> = ::std::result::Result<T, ()>;
|
||||
|
||||
macro_rules! ok_or {
|
||||
($ok:ident) => {
|
||||
if $ok != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
};
|
||||
|
||||
($ok:ident, $rv:expr) => {
|
||||
if $ok != 0 {
|
||||
Ok($rv)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
};
|
||||
|
||||
($ok:ident, $rv:expr, $err:expr) => {
|
||||
if $ok != 0 {
|
||||
Ok($rv)
|
||||
} else {
|
||||
Err($err)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/** Sciter notification handler for [`Window.sciter_handler()`](../window/struct.Window.html#method.sciter_handler).
|
||||
|
||||
## Resource handling and custom resource loader
|
||||
|
||||
HTML loaded into Sciter may contain external resources: CSS (Cascading Style Sheets),
|
||||
images, fonts, cursors and scripts.
|
||||
To get any of such resources Sciter will first send a `on_data_load(SCN_LOAD_DATA)` notification
|
||||
to your application using the callback handler registered with `sciter::Window.sciter_handler()` function.
|
||||
|
||||
Your application can provide your own data for such resources
|
||||
(for example, from the resource section, database or other storage of your choice)
|
||||
or delegate the resource loading to the built-in HTTP client or file loader, or discard the loading at all.
|
||||
|
||||
Note: This handler should be registered before any
|
||||
[`load_html()`](struct.Host.html#method.load_html) or
|
||||
[`load_file()`](struct.Host.html#method.load_file) calls
|
||||
in order to send notifications while loading.
|
||||
|
||||
*/
|
||||
#[allow(unused_variables)]
|
||||
pub trait HostHandler {
|
||||
|
||||
/// Notifies that Sciter is about to download the referred resource.
|
||||
///
|
||||
/// You can load or overload data immediately by calling `self.data_ready()` with parameters provided by `SCN_LOAD_DATA`,
|
||||
/// or save them (including `request_id`) for later usage and answer here with `LOAD_RESULT::LOAD_DELAYED` code.
|
||||
///
|
||||
/// Also you can discard the request (data will not be loaded at the document)
|
||||
/// or take care about this request completely by yourself (via the [request API](../request/index.html)).
|
||||
fn on_data_load(&mut self, pnm: &mut SCN_LOAD_DATA) -> Option<LOAD_RESULT> { return None; }
|
||||
|
||||
/// This notification indicates that external data (for example, image) download process completed.
|
||||
fn on_data_loaded(&mut self, pnm: &SCN_DATA_LOADED) { }
|
||||
|
||||
/// This notification is sent on parsing the document and while processing elements
|
||||
/// having non empty `behavior: ` style attribute value.
|
||||
fn on_attach_behavior(&mut self, pnm: &mut SCN_ATTACH_BEHAVIOR) -> bool { return false; }
|
||||
|
||||
/// This notification is sent when instance of the engine is destroyed.
|
||||
fn on_engine_destroyed(&mut self) { }
|
||||
|
||||
/// This notification is sent when the engine encounters critical rendering error: e.g. DirectX gfx driver error.
|
||||
/// Most probably bad gfx drivers.
|
||||
fn on_graphics_critical_failure(&mut self) { }
|
||||
|
||||
/// This notification is sent when the engine needs some area to be redrawn.
|
||||
fn on_invalidate(&mut self, pnm: &SCN_INVALIDATE_RECT) {}
|
||||
|
||||
/// This output function will be used for reporting problems found while loading html and css documents.
|
||||
fn on_debug_output(&mut self, subsystem: OUTPUT_SUBSYTEMS, severity: OUTPUT_SEVERITY, message: &str) {
|
||||
if !message.is_empty() {
|
||||
if severity == OUTPUT_SEVERITY::INFO {
|
||||
// e.g. `stdout.println` in TIScript
|
||||
println!("{:?}:{:?}: {}", severity, subsystem, message);
|
||||
} else {
|
||||
// e.g. `stderr.println` or CSS/script errors and warnings.
|
||||
eprintln!("{:?}:{:?}: {}", severity, subsystem, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function is used as response to [`on_data_load`](#method.on_data_load) request.
|
||||
///
|
||||
/// Parameters here must be taken from [`SCN_LOAD_DATA`](struct.SCN_LOAD_DATA.html) structure. You can store them for later usage,
|
||||
/// but you must answer as [`LOAD_DELAYED`](enum.LOAD_RESULT.html#variant.LOAD_DELAYED) code and provide an `request_id` here.
|
||||
fn data_ready(&self, hwnd: HWINDOW, uri: &str, data: &[u8], request_id: Option<HREQUEST>) {
|
||||
let s = s2w!(uri);
|
||||
match request_id {
|
||||
Some(req) => {
|
||||
(_API.SciterDataReadyAsync)(hwnd, s.as_ptr(), data.as_ptr(), data.len() as UINT, req)
|
||||
},
|
||||
None => {
|
||||
(_API.SciterDataReady)(hwnd, s.as_ptr(), data.as_ptr(), data.len() as UINT)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// This function is used as a response to the [`on_attach_behavior`](#method.on_attach_behavior) request
|
||||
/// to attach a newly created behavior `handler` to the requested element.
|
||||
fn attach_behavior<Handler: EventHandler>(&self, pnm: &mut SCN_ATTACH_BEHAVIOR, handler: Handler) {
|
||||
// make native handler
|
||||
let boxed = Box::new(handler);
|
||||
let ptr = Box::into_raw(boxed); // dropped in `_event_handler_proc`
|
||||
pnm.elementProc = ::eventhandler::_event_handler_proc::<Handler>;
|
||||
pnm.elementTag = ptr as LPVOID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Default `HostHandler` implementation
|
||||
#[derive(Default)]
|
||||
struct DefaultHandler;
|
||||
|
||||
/// Default `HostHandler` implementation
|
||||
impl HostHandler for DefaultHandler {
|
||||
|
||||
}
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
type BehaviorList = Vec<(String, Box<dyn Fn() -> Box<dyn EventHandler>>)>;
|
||||
type SharedBehaviorList = Rc<RefCell<BehaviorList>>;
|
||||
type SharedArchive = Rc<RefCell<Option<Archive>>>;
|
||||
|
||||
#[repr(C)]
|
||||
struct HostCallback<Callback> {
|
||||
sig: u32,
|
||||
behaviors: SharedBehaviorList,
|
||||
handler: Callback,
|
||||
archive: SharedArchive,
|
||||
}
|
||||
|
||||
/// Sciter host runtime support.
|
||||
pub struct Host {
|
||||
hwnd: HWINDOW,
|
||||
behaviors: SharedBehaviorList,
|
||||
handler: RefCell<NativeHandler>,
|
||||
archive: SharedArchive,
|
||||
}
|
||||
|
||||
impl Host {
|
||||
|
||||
/// Attach Sciter host to existing window.
|
||||
///
|
||||
/// Usually Sciter window created by a [`sciter::Window::create()`](../window/struct.Window.html#method.create),
|
||||
/// but you can attach Sciter to an existing native window.
|
||||
/// In this case you need to mix-in window events processing with `SciterProcND` (Windows only).
|
||||
/// Sciter engine will be initialized either on `WM_CREATE` or `WM_INITDIALOG` response
|
||||
/// or by calling `SciterCreateOnDirectXWindow` (again, Windows only).
|
||||
pub fn attach(hwnd: HWINDOW) -> Host {
|
||||
// Host with default debug handler installed
|
||||
let host = Host {
|
||||
hwnd,
|
||||
behaviors: Default::default(),
|
||||
handler: Default::default(),
|
||||
archive: Default::default(),
|
||||
};
|
||||
host.setup_callback(DefaultHandler::default());
|
||||
return host;
|
||||
}
|
||||
|
||||
/// Attach Sciter host to an existing window with the given Host handler.
|
||||
pub fn attach_with<Handler: HostHandler>(hwnd: HWINDOW, handler: Handler) -> Host {
|
||||
let host = Host {
|
||||
hwnd,
|
||||
behaviors: Default::default(),
|
||||
handler: Default::default(),
|
||||
archive: Default::default(),
|
||||
};
|
||||
host.setup_callback(handler);
|
||||
return host;
|
||||
}
|
||||
|
||||
/// Attach [`dom::EventHandler`](../dom/event/trait.EventHandler.html) to the Sciter window.
|
||||
pub fn event_handler<Handler: EventHandler>(&self, handler: Handler) {
|
||||
self.attach_handler(handler)
|
||||
}
|
||||
|
||||
/// Attach [`dom::EventHandler`](../dom/event/trait.EventHandler.html) to the Sciter window.
|
||||
#[doc(hidden)]
|
||||
pub fn attach_handler<Handler: EventHandler>(&self, handler: Handler) {
|
||||
let hwnd = self.get_hwnd();
|
||||
let boxed = Box::new( WindowHandler { hwnd, handler } );
|
||||
let ptr = Box::into_raw(boxed); // dropped in `_event_handler_window_proc`
|
||||
// eprintln!("{}: {:?}", std::any::type_name::<Handler>(), ptr);
|
||||
|
||||
let func = _event_handler_window_proc::<Handler>;
|
||||
let flags = ::dom::event::default_events();
|
||||
(_API.SciterWindowAttachEventHandler)(hwnd, func, ptr as LPVOID, flags as UINT);
|
||||
}
|
||||
|
||||
/// Set callback for Sciter engine events.
|
||||
pub(crate) fn setup_callback<Callback: HostHandler>(&self, handler: Callback) {
|
||||
|
||||
let payload: HostCallback<Callback> = HostCallback {
|
||||
sig: 17,
|
||||
behaviors: Rc::clone(&self.behaviors),
|
||||
archive: Rc::clone(&self.archive),
|
||||
handler: handler,
|
||||
};
|
||||
|
||||
*self.handler.borrow_mut() = NativeHandler::from(payload);
|
||||
let ptr = self.handler.borrow().as_mut_ptr();
|
||||
|
||||
(_API.SciterSetCallback)(self.get_hwnd(), _on_handle_notification::<Callback>, ptr);
|
||||
(_API.SciterSetupDebugOutput)(0 as HWINDOW, ptr, _on_debug_notification::<Callback>);
|
||||
}
|
||||
|
||||
/// Register a native event handler for the specified behavior name.
|
||||
///
|
||||
/// See the [`Window::register_behavior`](../window/struct.Window.html#method.register_behavior) for an example.
|
||||
pub fn register_behavior<Factory>(&self, name: &str, factory: Factory)
|
||||
where
|
||||
Factory: Fn() -> Box<dyn EventHandler> + 'static
|
||||
{
|
||||
let make: Box<dyn Fn() -> Box<dyn EventHandler>> = Box::new(factory);
|
||||
let pair = (name.to_owned(), make);
|
||||
self.behaviors.borrow_mut().push(pair);
|
||||
}
|
||||
|
||||
/// Register an archive produced by `packfolder`.
|
||||
///
|
||||
/// See documentation of the [`Archive`](struct.Archive.html).
|
||||
pub fn register_archive(&self, resource: &[u8]) -> Result<()> {
|
||||
*self.archive.borrow_mut() = Some(Archive::open(resource)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set debug mode for this window.
|
||||
pub fn enable_debug(&self, enable: bool) {
|
||||
(_API.SciterSetOption)(self.hwnd, SCITER_RT_OPTIONS::SCITER_SET_DEBUG_MODE, enable as UINT_PTR);
|
||||
}
|
||||
|
||||
/// Get native window handle.
|
||||
pub fn get_hwnd(&self) -> HWINDOW {
|
||||
self.hwnd
|
||||
}
|
||||
|
||||
/// Get window root DOM element.
|
||||
pub fn get_root(&self) -> Option<::dom::Element> {
|
||||
::dom::Element::from_window(self.hwnd).ok()
|
||||
}
|
||||
|
||||
/// Load an HTML document from file.
|
||||
pub fn load_file(&self, uri: &str) -> bool {
|
||||
// TODO: it should be `Result<()>` instead `bool`
|
||||
let s = s2w!(uri);
|
||||
(_API.SciterLoadFile)(self.hwnd, s.as_ptr()) != 0
|
||||
}
|
||||
|
||||
/// Load an HTML document from memory.
|
||||
pub fn load_html(&self, html: &[u8], uri: Option<&str>) -> bool {
|
||||
match uri {
|
||||
Some(uri) => {
|
||||
let s = s2w!(uri);
|
||||
(_API.SciterLoadHtml)(self.hwnd, html.as_ptr(), html.len() as UINT, s.as_ptr()) != 0
|
||||
},
|
||||
None => {
|
||||
(_API.SciterLoadHtml)(self.hwnd, html.as_ptr(), html.len() as UINT, 0 as LPCWSTR) != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function is used as response to [`HostHandler::on_data_load`](trait.HostHandler.html#method.on_data_load) request.
|
||||
pub fn data_ready(&self, uri: &str, data: &[u8]) {
|
||||
let s = s2w!(uri);
|
||||
(_API.SciterDataReady)(self.hwnd, s.as_ptr(), data.as_ptr(), data.len() as UINT);
|
||||
}
|
||||
|
||||
/// Use this function outside of [`HostHandler::on_data_load`](trait.HostHandler.html#method.on_data_load) request.
|
||||
///
|
||||
/// It can be used for two purposes:
|
||||
///
|
||||
/// 1. Asynchronious resource loading in respect of [`on_data_load`](trait.HostHandler.html#method.on_data_load)
|
||||
/// requests (you must use `request_id` in this case).
|
||||
/// 2. Refresh of an already loaded resource (for example, dynamic image updates).
|
||||
pub fn data_ready_async(&self, uri: &str, data: &[u8], request_id: Option<HREQUEST>) {
|
||||
let s = s2w!(uri);
|
||||
let req = request_id.unwrap_or(::std::ptr::null_mut());
|
||||
(_API.SciterDataReadyAsync)(self.hwnd, s.as_ptr(), data.as_ptr(), data.len() as UINT, req);
|
||||
}
|
||||
|
||||
/// Evaluate the given script in context of the current document.
|
||||
///
|
||||
/// This function returns `Result<Value,Value>` with script function result value or with Sciter script error.
|
||||
pub fn eval_script(&self, script: &str) -> ::std::result::Result<Value, Value> {
|
||||
let (s,n) = s2wn!(script);
|
||||
let mut rv = Value::new();
|
||||
let ok = (_API.SciterEval)(self.hwnd, s.as_ptr(), n, rv.as_ptr());
|
||||
ok_or!(ok, rv, rv)
|
||||
}
|
||||
|
||||
/// Call a script function defined in the global namespace.
|
||||
///
|
||||
/// This function returns `Result<Value,Value>` with script function result value or with Sciter script error.
|
||||
///
|
||||
/// You can use the [`&make_args!(args...)`](../macro.make_args.html) macro which helps you
|
||||
/// to construct script arguments from Rust types.
|
||||
pub fn call_function(&self, name: &str, args: &[Value]) -> ::std::result::Result<Value, Value> {
|
||||
let mut rv = Value::new();
|
||||
let s = s2u!(name);
|
||||
let argv = Value::pack_args(args);
|
||||
let ok = (_API.SciterCall)(self.hwnd, s.as_ptr(), argv.len() as UINT, argv.as_ptr(), rv.as_ptr());
|
||||
ok_or!(ok, rv, rv)
|
||||
}
|
||||
|
||||
/// Set home url for Sciter resources.
|
||||
///
|
||||
/// If you set it like `set_home_url("https://sciter.com/modules/")` then
|
||||
///
|
||||
/// `<script src="sciter:lib/root-extender.tis">` will load
|
||||
/// root-extender.tis from
|
||||
///
|
||||
/// `https://sciter.com/modules/lib/root-extender.tis`.
|
||||
pub fn set_home_url(&self, url: &str) -> Result<()> {
|
||||
let s = s2w!(url);
|
||||
let ok = (_API.SciterSetHomeURL)(self.hwnd, s.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set media type of this Sciter instance.
|
||||
///
|
||||
/// For example, media type can be "handheld", "projection", "screen", "screen-hires", etc.
|
||||
/// By default, Sciter window has the `"screen"` media type.
|
||||
///
|
||||
/// Media type name is used while loading and parsing style sheets in the engine,
|
||||
/// so you should call this function **before** loading document in it.
|
||||
///
|
||||
pub fn set_media_type(&self, media_type: &str) -> Result<()> {
|
||||
let s = s2w!(media_type);
|
||||
let ok = (_API.SciterSetMediaType)(self.hwnd, s.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set media variables (dictionary) for this Sciter instance.
|
||||
///
|
||||
/// By default Sciter window has `"screen:true"` and `"desktop:true"/"handheld:true"` media variables.
|
||||
///
|
||||
/// Media variables can be changed in runtime. This will cause styles of the document to be reset.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use sciter::vmap;
|
||||
/// # let mut host = sciter::Host::attach(0 as sciter::types::HWINDOW);
|
||||
/// host.set_media_vars( &vmap! {
|
||||
/// "screen" => true,
|
||||
/// "handheld" => true,
|
||||
/// }).unwrap();
|
||||
/// ```
|
||||
pub fn set_media_vars(&self, media: &Value) -> Result<()> {
|
||||
let ok = (_API.SciterSetMediaVars)(self.hwnd, media.as_cptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set or append the [master](https://sciter.com/css-extensions-in-h-smile-engine-part-i-style-sets/)
|
||||
/// style sheet styles (**globally**, for all windows).
|
||||
pub fn set_master_css(&self, css: &str, append: bool) -> Result<()> {
|
||||
let s = s2u!(css);
|
||||
let b = s.as_bytes();
|
||||
let n = b.len() as UINT;
|
||||
let ok = if append {
|
||||
(_API.SciterAppendMasterCSS)(b.as_ptr(), n)
|
||||
} else {
|
||||
(_API.SciterSetMasterCSS)(b.as_ptr(), n)
|
||||
};
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set (reset) style sheet of the **current** document.
|
||||
///
|
||||
/// Will reset styles for all elements according to given CSS.
|
||||
pub fn set_window_css(&self, css: &str, base_url: &str, media_type: &str) -> Result<()> {
|
||||
let s = s2u!(css);
|
||||
let url = s2w!(base_url);
|
||||
let media = s2w!(media_type);
|
||||
let b = s.as_bytes();
|
||||
let n = b.len() as UINT;
|
||||
let ok = (_API.SciterSetCSS)(self.hwnd, b.as_ptr(), n, url.as_ptr(), media.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Sciter notification handler.
|
||||
// This comes as free function due to https://github.com/rust-lang/rust/issues/32364
|
||||
extern "system" fn _on_handle_notification<T: HostHandler>(pnm: *mut ::capi::scdef::SCITER_CALLBACK_NOTIFICATION, param: LPVOID) -> UINT
|
||||
{
|
||||
use capi::scdef::{SCITER_NOTIFICATION, SCITER_CALLBACK_NOTIFICATION};
|
||||
|
||||
// reconstruct pointer to Handler
|
||||
let callback = NativeHandler::get_data::<HostCallback<T>>(¶m);
|
||||
let me: &mut T = &mut callback.handler;
|
||||
|
||||
// process notification
|
||||
let nm: &mut SCITER_CALLBACK_NOTIFICATION = unsafe { &mut *pnm };
|
||||
let code: SCITER_NOTIFICATION = unsafe { ::std::mem::transmute(nm.code) };
|
||||
|
||||
|
||||
let result: UINT = match code {
|
||||
SCITER_NOTIFICATION::SC_LOAD_DATA => {
|
||||
let scnm = pnm as *mut SCN_LOAD_DATA;
|
||||
let scnm = unsafe { &mut *scnm };
|
||||
let mut re = me.on_data_load(scnm);
|
||||
if re.is_none() {
|
||||
if let Some(archive) = callback.archive.borrow().as_ref() {
|
||||
let uri = w2s!(scnm.uri);
|
||||
if uri.starts_with("this://app/") {
|
||||
if let Some(data) = archive.get(&uri) {
|
||||
me.data_ready(scnm.hwnd, &uri, data, None);
|
||||
} else {
|
||||
eprintln!("[sciter] error: can't load {:?}", uri);
|
||||
}
|
||||
}
|
||||
re = Some(LOAD_RESULT::LOAD_DEFAULT);
|
||||
}
|
||||
}
|
||||
re.unwrap_or(LOAD_RESULT::LOAD_DEFAULT) as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_DATA_LOADED => {
|
||||
let scnm = pnm as *mut SCN_DATA_LOADED;
|
||||
me.on_data_loaded(unsafe { &mut *scnm } );
|
||||
0 as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_ATTACH_BEHAVIOR => {
|
||||
let scnm = pnm as *mut SCN_ATTACH_BEHAVIOR;
|
||||
let scnm = unsafe { &mut *scnm };
|
||||
let mut re = me.on_attach_behavior(scnm);
|
||||
if !re {
|
||||
let name = u2s!(scnm.name);
|
||||
let behavior = callback.behaviors
|
||||
.borrow()
|
||||
.iter()
|
||||
.find(|x| x.0 == name)
|
||||
.map(|x| x.1());
|
||||
|
||||
if let Some(behavior) = behavior {
|
||||
let boxed = Box::new( BoxedHandler { handler: behavior } );
|
||||
let ptr = Box::into_raw(boxed); // dropped in `_event_handler_behavior_proc`
|
||||
|
||||
scnm.elementProc = ::eventhandler::_event_handler_behavior_proc;
|
||||
scnm.elementTag = ptr as LPVOID;
|
||||
re = true;
|
||||
}
|
||||
}
|
||||
re as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_ENGINE_DESTROYED => {
|
||||
me.on_engine_destroyed();
|
||||
0 as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_GRAPHICS_CRITICAL_FAILURE => {
|
||||
me.on_graphics_critical_failure();
|
||||
0 as UINT
|
||||
},
|
||||
|
||||
SCITER_NOTIFICATION::SC_INVALIDATE_RECT => {
|
||||
let scnm = pnm as *const SCN_INVALIDATE_RECT;
|
||||
me.on_invalidate(unsafe { &*scnm });
|
||||
0 as UINT
|
||||
}
|
||||
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Sciter debug output handler.
|
||||
extern "system" fn _on_debug_notification<T: HostHandler>(param: LPVOID, subsystem: OUTPUT_SUBSYTEMS, severity: OUTPUT_SEVERITY,
|
||||
text: LPCWSTR, _text_length: UINT)
|
||||
{
|
||||
// reconstruct pointer to Handler
|
||||
// let me = unsafe { &mut *(param as *mut HostCallback<T>) };
|
||||
let me = NativeHandler::get_data::<HostCallback<T>>(¶m);
|
||||
let message = ::utf::w2s(text).replace("\r", "\n");
|
||||
me.handler.on_debug_output(subsystem, severity, message.trim_end());
|
||||
}
|
||||
|
||||
|
||||
/// Sciter compressed archive.
|
||||
///
|
||||
/// An archive is produced by `packfolder` tool (from SDK) that creates a single blob with compressed resources.
|
||||
/// It allows to use the same resource pack uniformly across different platforms.
|
||||
///
|
||||
/// For example, app resource files (HTML/CSS/scripts) can be stored in an `assets` folder
|
||||
/// that can be packed into a single archive by calling `packfolder.exe assets target/assets.rc -binary`.
|
||||
/// And later it can be accessed via the Archive API explicitly:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let archived = include_bytes!("target/assets.rc");
|
||||
/// let assets = sciter::host::Archive::open(archived).expect("Unable to load archive.");
|
||||
///
|
||||
/// // access `assets/index.htm`
|
||||
/// let html_data = assets.get("index.htm").unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// or implicitly via the `this://app/` URL after registering the archive via
|
||||
/// [`Window::archive_handler`](../window/struct.Window.html#method.archive_handler):
|
||||
///
|
||||
/// ```rust,ignore
|
||||
///
|
||||
/// let archived = include_bytes!("target/assets.rc");
|
||||
/// let mut frame = sciter::Window::new();
|
||||
/// frame.archive_handler(archived).expect("Unable to load archive");
|
||||
/// frame.load("this://app/index.htm");
|
||||
/// ```
|
||||
pub struct Archive(HSARCHIVE);
|
||||
|
||||
/// Close the archive.
|
||||
impl Drop for Archive {
|
||||
fn drop(&mut self) {
|
||||
(_API.SciterCloseArchive)(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl Archive {
|
||||
/// Open an archive blob.
|
||||
pub fn open(archived: &[u8]) -> Result<Self> {
|
||||
let p = (_API.SciterOpenArchive)(archived.as_ptr(), archived.len() as u32);
|
||||
if !p.is_null() {
|
||||
Ok(Archive(p))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an archive item.
|
||||
///
|
||||
/// Given a path, returns a reference to the contents of an archived item.
|
||||
pub fn get(&self, path: &str) -> Option<&[u8]> {
|
||||
// skip initial part of the path
|
||||
let skip = if path.starts_with("this://app/") {
|
||||
"this://app/".len()
|
||||
} else if path.starts_with("//") {
|
||||
"//".len()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let wname = s2w!(path);
|
||||
let name = &wname[skip..];
|
||||
|
||||
let mut pb = ::std::ptr::null();
|
||||
let mut cb = 0;
|
||||
let ok = (_API.SciterGetArchiveItem)(self.0, name.as_ptr(), &mut pb, &mut cb);
|
||||
if ok != 0 && !pb.is_null() {
|
||||
let data = unsafe { ::std::slice::from_raw_parts(pb, cb as usize) };
|
||||
Some(data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
590
libs/rust-sciter/src/lib.rs
Normal file
590
libs/rust-sciter/src/lib.rs
Normal file
@@ -0,0 +1,590 @@
|
||||
// This component uses Sciter Engine,
|
||||
// copyright Terra Informatica Software, Inc.
|
||||
// (http://terrainformatica.com/).
|
||||
|
||||
/*!
|
||||
# Rust bindings library for Sciter engine.
|
||||
|
||||
[Sciter](http://sciter.com) is an embeddable [multiplatform](https://sciter.com/sciter/crossplatform/) HTML/CSS/script engine
|
||||
with GPU accelerated rendering designed to render modern desktop application UI.
|
||||
It's a compact, single dll/dylib/so file (4-8 mb) engine without any additional dependencies.
|
||||
|
||||
Check the [screenshot gallery](https://github.com/oskca/sciter#sciter-desktop-ui-examples)
|
||||
of the desktop UI examples.
|
||||
|
||||
Sciter supports all standard elements defined in HTML5 specification
|
||||
[with some additions](https://sciter.com/developers/for-web-programmers/).
|
||||
CSS is extended to better support the Desktop UI development,
|
||||
e.g. flow and flex units, vertical and horizontal alignment, OS theming.
|
||||
|
||||
[Sciter SDK](https://sciter.com/download/) comes with a demo "browser" with builtin DOM inspector,
|
||||
script debugger and documentation viewer:
|
||||
|
||||

|
||||
|
||||
Check <https://sciter.com> website and its [documentation resources](https://sciter.com/developers/)
|
||||
for engine principles, architecture and more.
|
||||
|
||||
|
||||
## Brief look:
|
||||
|
||||
Here is a minimal sciter app:
|
||||
|
||||
```no_run
|
||||
extern crate sciter;
|
||||
|
||||
fn main() {
|
||||
let mut frame = sciter::Window::new();
|
||||
frame.load_file("minimal.htm");
|
||||
frame.run_app();
|
||||
}
|
||||
```
|
||||
|
||||
It looks similar like this:
|
||||
|
||||

|
||||
|
||||
Check [rust-sciter/examples](https://github.com/sciter-sdk/rust-sciter/tree/master/examples)
|
||||
folder for more complex usage and module-level sections for the guides about:
|
||||
|
||||
* [Window](window/index.html) creation.
|
||||
* [Behaviors](dom/event/index.html) and event handling.
|
||||
* [DOM](dom/index.html) access methods.
|
||||
* Sciter [Value](value/index.html) interface.
|
||||
|
||||
*/
|
||||
|
||||
#![doc(html_logo_url = "https://sciter.com/screenshots/slide-sciter-osx.png",
|
||||
html_favicon_url = "https://sciter.com/wp-content/themes/sciter/!images/favicon.ico")]
|
||||
|
||||
// documentation test:
|
||||
// #![warn(missing_docs)]
|
||||
|
||||
|
||||
/* Clippy lints */
|
||||
|
||||
#![allow(clippy::needless_return, clippy::let_and_return)] // past habits
|
||||
#![allow(clippy::redundant_field_names)] // since Rust 1.17 and less readable
|
||||
#![allow(clippy::unreadable_literal)] // C++ SDK constants
|
||||
// #![allow(clippy::cast_ptr_alignment)] // 0.0.195 only
|
||||
|
||||
|
||||
/* Macros */
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[macro_use] extern crate objc;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
|
||||
|
||||
#[macro_use] pub mod macros;
|
||||
|
||||
mod capi;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use capi::scdom::{HELEMENT};
|
||||
pub use capi::scdef::{GFX_LAYER, SCRIPT_RUNTIME_FEATURES};
|
||||
|
||||
/* Rust interface */
|
||||
mod platform;
|
||||
mod eventhandler;
|
||||
|
||||
pub mod dom;
|
||||
pub mod graphics;
|
||||
pub mod host;
|
||||
pub mod om;
|
||||
pub mod request;
|
||||
pub mod types;
|
||||
pub mod utf;
|
||||
pub mod value;
|
||||
pub mod video;
|
||||
pub mod window;
|
||||
pub mod windowless;
|
||||
|
||||
pub use dom::Element;
|
||||
pub use dom::event::EventHandler;
|
||||
pub use host::{Archive, Host, HostHandler};
|
||||
pub use value::{Value, FromValue};
|
||||
pub use window::Window;
|
||||
|
||||
|
||||
/// Builder pattern for window creation. See [`window::Builder`](window/struct.Builder.html) documentation.
|
||||
///
|
||||
/// For example,
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// let mut frame = sciter::WindowBuilder::main_window()
|
||||
/// .with_size((800,600))
|
||||
/// .glassy()
|
||||
/// .fixed()
|
||||
/// .create();
|
||||
/// ```
|
||||
pub type WindowBuilder = window::Builder;
|
||||
|
||||
|
||||
/* Loader */
|
||||
pub use capi::scapi::{ISciterAPI};
|
||||
use capi::scgraphics::SciterGraphicsAPI;
|
||||
use capi::screquest::SciterRequestAPI;
|
||||
|
||||
#[cfg(all(windows, not(feature = "dynamic")))]
|
||||
mod ext {
|
||||
#[link(name = "sciter.static")]
|
||||
extern "system" { pub fn SciterAPI() -> *const ::capi::scapi::ISciterAPI; }
|
||||
}
|
||||
|
||||
#[cfg(all(windows, feature = "dynamic"))]
|
||||
mod ext {
|
||||
// Note:
|
||||
// Sciter 4.x shipped with universal "sciter.dll" library for different builds:
|
||||
// bin/32, bin/64, bin/skia32, bin/skia64
|
||||
// However it is quite inconvenient now (e.g. we can not put x64 and x86 builds in %PATH%)
|
||||
//
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
use capi::scapi::{ISciterAPI};
|
||||
use capi::sctypes::{LPCSTR, LPCVOID, BOOL};
|
||||
|
||||
type ApiType = *const ISciterAPI;
|
||||
type FuncType = extern "system" fn () -> *const ISciterAPI;
|
||||
|
||||
pub static mut CUSTOM_DLL_PATH: Option<String> = None;
|
||||
|
||||
extern "system"
|
||||
{
|
||||
fn LoadLibraryA(lpFileName: LPCSTR) -> LPCVOID;
|
||||
fn FreeLibrary(dll: LPCVOID) -> BOOL;
|
||||
fn GetProcAddress(hModule: LPCVOID, lpProcName: LPCSTR) -> LPCVOID;
|
||||
}
|
||||
|
||||
pub fn try_load_library(permanent: bool) -> ::std::result::Result<ApiType, String> {
|
||||
use std::ffi::CString;
|
||||
use std::path::Path;
|
||||
|
||||
fn try_load(path: &Path) -> Option<LPCVOID> {
|
||||
let path = CString::new(format!("{}", path.display())).expect("invalid library path");
|
||||
let dll = unsafe { LoadLibraryA(path.as_ptr()) };
|
||||
if !dll.is_null() {
|
||||
Some(dll)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn in_global() -> Option<LPCVOID> {
|
||||
// modern dll name
|
||||
let mut dll = unsafe { LoadLibraryA(b"sciter.dll\0".as_ptr() as LPCSTR) };
|
||||
if dll.is_null() {
|
||||
// try to load with old names
|
||||
let alternate = if cfg!(target_arch = "x86_64") { b"sciter64.dll\0" } else { b"sciter32.dll\0" };
|
||||
dll = unsafe { LoadLibraryA(alternate.as_ptr() as LPCSTR) };
|
||||
}
|
||||
if !dll.is_null() {
|
||||
Some(dll)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// try specified path first (and only if present)
|
||||
// and several paths to lookup then
|
||||
let dll = if let Some(path) = unsafe { CUSTOM_DLL_PATH.as_ref() } {
|
||||
try_load(Path::new(path))
|
||||
} else {
|
||||
in_global()
|
||||
};
|
||||
|
||||
if let Some(dll) = dll {
|
||||
// get the "SciterAPI" exported symbol
|
||||
let sym = unsafe { GetProcAddress(dll, b"SciterAPI\0".as_ptr() as LPCSTR) };
|
||||
if sym.is_null() {
|
||||
return Err("\"SciterAPI\" function was expected in the loaded library.".to_owned());
|
||||
}
|
||||
|
||||
if !permanent {
|
||||
unsafe { FreeLibrary(dll) };
|
||||
return Ok(0 as ApiType);
|
||||
}
|
||||
|
||||
let get_api: FuncType = unsafe { std::mem::transmute(sym) };
|
||||
return Ok(get_api());
|
||||
}
|
||||
let sdkbin = if cfg!(target_arch = "x86_64") { "bin/64" } else { "bin/32" };
|
||||
let msg = format!("Please verify that Sciter SDK is installed and its binaries (from SDK/{}) are available in PATH.", sdkbin);
|
||||
Err(format!("error: '{}' was not found neither in PATH nor near the current executable.\n {}", "sciter.dll", msg))
|
||||
}
|
||||
|
||||
pub unsafe fn SciterAPI() -> *const ISciterAPI {
|
||||
match try_load_library(true) {
|
||||
Ok(api) => api,
|
||||
Err(error) => panic!(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "dynamic", unix))]
|
||||
mod ext {
|
||||
#![allow(non_snake_case, non_camel_case_types)]
|
||||
extern crate libc;
|
||||
|
||||
pub static mut CUSTOM_DLL_PATH: Option<String> = None;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
const DLL_NAMES: &'static [&'static str] = &[ "libsciter-gtk.so" ];
|
||||
|
||||
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
||||
const DLL_NAMES: &'static [&'static str] = &[ "sciter-osx-64.dylib" ];
|
||||
|
||||
use capi::scapi::ISciterAPI;
|
||||
use capi::sctypes::{LPVOID, LPCSTR};
|
||||
|
||||
type FuncType = extern "system" fn () -> *const ISciterAPI;
|
||||
type ApiType = *const ISciterAPI;
|
||||
|
||||
|
||||
pub fn try_load_library(permanent: bool) -> ::std::result::Result<ApiType, String> {
|
||||
use std::ffi::CString;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
|
||||
// Try to load the library from a specified absolute path.
|
||||
fn try_load(path: &Path) -> Option<LPVOID> {
|
||||
let bytes = path.as_os_str().as_bytes();
|
||||
if let Ok(cstr) = CString::new(bytes) {
|
||||
let dll = unsafe { libc::dlopen(cstr.as_ptr(), libc::RTLD_LOCAL | libc::RTLD_LAZY) };
|
||||
if !dll.is_null() {
|
||||
return Some(dll)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Try to find a library (by one of its names) in a specified path.
|
||||
fn try_load_from(dir: Option<&Path>) -> Option<LPVOID> {
|
||||
|
||||
let dll = DLL_NAMES.iter()
|
||||
.map(|name| {
|
||||
let mut path = dir.map(Path::to_owned).unwrap_or(PathBuf::new());
|
||||
path.push(name);
|
||||
path
|
||||
})
|
||||
.map(|path| try_load(&path))
|
||||
.filter(|dll| dll.is_some())
|
||||
.nth(0)
|
||||
.map(|o| o.unwrap());
|
||||
|
||||
if dll.is_some() {
|
||||
return dll;
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// Try to load from the current directory.
|
||||
fn in_current_dir() -> Option<LPVOID> {
|
||||
if let Ok(dir) = ::std::env::current_exe() {
|
||||
if let Some(dir) = dir.parent() {
|
||||
let dll = try_load_from(Some(dir));
|
||||
if dll.is_some() {
|
||||
return dll;
|
||||
}
|
||||
|
||||
if cfg!(target_os = "macos") {
|
||||
// "(bundle folder)/Contents/Frameworks/"
|
||||
let mut path = dir.to_owned();
|
||||
path.push("../Frameworks/sciter-osx-64.dylib");
|
||||
return try_load(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Try to load indirectly via `dlopen("dll.so")`.
|
||||
fn in_global() -> Option<LPVOID> {
|
||||
try_load_from(None)
|
||||
}
|
||||
|
||||
// Try to find in $PATH.
|
||||
fn in_paths() -> Option<LPVOID> {
|
||||
use std::env;
|
||||
if let Some(paths) = env::var_os("PATH") {
|
||||
for path in env::split_paths(&paths) {
|
||||
if let Some(dll) = try_load_from(Some(&path)) {
|
||||
return Some(dll);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// try specified path first (and only if present)
|
||||
// and several paths to lookup then
|
||||
let dll = if let Some(path) = unsafe { CUSTOM_DLL_PATH.as_ref() } {
|
||||
try_load(Path::new(path))
|
||||
} else {
|
||||
in_current_dir().or_else(in_paths).or_else(in_global)
|
||||
};
|
||||
|
||||
if let Some(dll) = dll {
|
||||
// get the "SciterAPI" exported symbol
|
||||
let sym = unsafe { libc::dlsym(dll, b"SciterAPI\0".as_ptr() as LPCSTR) };
|
||||
if sym.is_null() {
|
||||
return Err("\"SciterAPI\" function was expected in the loaded library.".to_owned());
|
||||
}
|
||||
|
||||
if !permanent {
|
||||
unsafe { libc::dlclose(dll) };
|
||||
return Ok(0 as ApiType);
|
||||
}
|
||||
|
||||
let get_api: FuncType = unsafe { std::mem::transmute(sym) };
|
||||
return Ok(get_api());
|
||||
}
|
||||
|
||||
let sdkbin = if cfg!(target_os = "macos") { "bin.osx" } else { "bin.lnx" };
|
||||
let msg = format!("Please verify that Sciter SDK is installed and its binaries (from {}) are available in PATH.", sdkbin);
|
||||
Err(format!("error: '{}' was not found neither in PATH nor near the current executable.\n {}", DLL_NAMES[0], msg))
|
||||
}
|
||||
|
||||
pub fn SciterAPI() -> *const ISciterAPI {
|
||||
match try_load_library(true) {
|
||||
Ok(api) => api,
|
||||
Err(error) => panic!(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(all(target_os = "linux", not(feature = "dynamic")))]
|
||||
mod ext {
|
||||
// Note:
|
||||
// Since 4.1.4 library name has been changed to "libsciter-gtk" (without 32/64 suffix).
|
||||
// Since 3.3.1.6 library name was changed to "libsciter".
|
||||
// However CC requires `-l sciter` form.
|
||||
#[link(name = "sciter-gtk")]
|
||||
extern "system" { pub fn SciterAPI() -> *const ::capi::scapi::ISciterAPI; }
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "macos", target_arch = "x86_64", not(feature = "dynamic")))]
|
||||
mod ext {
|
||||
#[link(name = "sciter-osx-64", kind = "dylib")]
|
||||
extern "system" { pub fn SciterAPI() -> *const ::capi::scapi::ISciterAPI; }
|
||||
}
|
||||
|
||||
/// Getting ISciterAPI reference, can be used for manual API calling.
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn SciterAPI<'a>() -> &'a ISciterAPI {
|
||||
let ap = unsafe {
|
||||
if cfg!(feature="extension") {
|
||||
// TODO: it's not good to raise a panic inside `lazy_static!`,
|
||||
// because it wents into recursive panicing.
|
||||
//
|
||||
// Somehow, `cargo test --all` tests all the features,
|
||||
// also sometimes it comes even without `cfg!(test)`.
|
||||
// Well, the culprit is "examples/extensions" which uses the "extension" feature,
|
||||
// but how on earth it builds without `cfg(test)`?
|
||||
//
|
||||
if cfg!(test) {
|
||||
&*ext::SciterAPI()
|
||||
} else {
|
||||
EXT_API
|
||||
//.or_else(|| Some(&*ext::SciterAPI()))
|
||||
.expect("Sciter API is not available yet, call `sciter::set_api()` first.")
|
||||
}
|
||||
} else {
|
||||
&*ext::SciterAPI()
|
||||
}
|
||||
};
|
||||
|
||||
let abi_version = ap.version;
|
||||
|
||||
if cfg!(feature = "windowless") {
|
||||
assert!(abi_version >= 0x0001_0001, "Incompatible Sciter build and \"windowless\" feature");
|
||||
}
|
||||
if cfg!(not(feature = "windowless")) {
|
||||
assert!(abi_version < 0x0001_0000, "Incompatible Sciter build and \"windowless\" feature");
|
||||
}
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
/// Getting ISciterAPI reference, can be used for manual API calling.
|
||||
///
|
||||
/// Bypasses ABI compatability checks.
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn SciterAPI_unchecked<'a>() -> &'a ISciterAPI {
|
||||
let ap = unsafe {
|
||||
if cfg!(feature="extension") {
|
||||
EXT_API.expect("Sciter API is not available yet, call `sciter::set_api()` first.")
|
||||
} else {
|
||||
&*ext::SciterAPI()
|
||||
}
|
||||
};
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref _API: &'static ISciterAPI = SciterAPI();
|
||||
static ref _GAPI: &'static SciterGraphicsAPI = {
|
||||
if version_num() < 0x0401_0A00 {
|
||||
panic!("Graphics API is incompatible since 4.1.10 (your version is {})", version());
|
||||
}
|
||||
unsafe { &*(SciterAPI().GetSciterGraphicsAPI)() }
|
||||
};
|
||||
static ref _RAPI: &'static SciterRequestAPI = unsafe { &*(SciterAPI().GetSciterRequestAPI)() };
|
||||
}
|
||||
|
||||
/// Set a custom path to the Sciter dynamic library.
|
||||
///
|
||||
/// Note: Must be called first before any other function.
|
||||
///
|
||||
/// Returns error if the specified library can not be loaded.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// if sciter::set_library("~/lib/sciter/bin.gtk/x64/libsciter-gtk.so").is_ok() {
|
||||
/// println!("loaded Sciter version {}", sciter::version());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn set_library(custom_path: &str) -> ::std::result::Result<(), String> {
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
fn set_impl(_: &str) -> ::std::result::Result<(), String> {
|
||||
Err("Don't use `sciter::set_library()` in static builds.\n Build with the feature \"dynamic\" instead.".to_owned())
|
||||
}
|
||||
|
||||
#[cfg(feature = "dynamic")]
|
||||
fn set_impl(path: &str) -> ::std::result::Result<(), String> {
|
||||
unsafe {
|
||||
ext::CUSTOM_DLL_PATH = Some(path.to_owned());
|
||||
}
|
||||
ext::try_load_library(false).map(|_| ())
|
||||
}
|
||||
|
||||
set_impl(custom_path)
|
||||
}
|
||||
|
||||
static mut EXT_API: Option<&'static ISciterAPI> = None;
|
||||
|
||||
/// Set the Sciter API coming from `SciterLibraryInit`.
|
||||
///
|
||||
/// Note: Must be called first before any other function.
|
||||
pub fn set_host_api(api: &'static ISciterAPI) {
|
||||
if cfg!(feature="extension") {
|
||||
unsafe {
|
||||
EXT_API.replace(api);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sciter engine version number (e.g. `0x03030200`).
|
||||
///
|
||||
/// Note: does not return the `build` part because it doesn't fit in `0..255` byte range.
|
||||
/// Use [`sciter::version()`](fn.version.html) instead which returns the complete version string.
|
||||
pub fn version_num() -> u32 {
|
||||
use types::BOOL;
|
||||
let v1 = (_API.SciterVersion)(true as BOOL);
|
||||
let v2 = (_API.SciterVersion)(false as BOOL);
|
||||
let (major, minor, revision, _build) = (v1 >> 16 & 0xFF, v1 & 0xFF, v2 >> 16 & 0xFF, v2 & 0xFF);
|
||||
let num = (major << 24) | (minor << 16) | (revision << 8);
|
||||
// let num = ((v1 >> 16) << 24) | ((v1 & 0xFFFF) << 16) | ((v2 >> 16) << 8) | (v2 & 0xFFFF);
|
||||
return num;
|
||||
}
|
||||
|
||||
/// Sciter engine version string (e.g. "`3.3.2.0`").
|
||||
pub fn version() -> String {
|
||||
use types::BOOL;
|
||||
let v1 = (_API.SciterVersion)(true as BOOL);
|
||||
let v2 = (_API.SciterVersion)(false as BOOL);
|
||||
let num = [v1 >> 16, v1 & 0xFFFF, v2 >> 16, v2 & 0xFFFF];
|
||||
let version = format!("{}.{}.{}.{}", num[0], num[1], num[2], num[3]);
|
||||
return version;
|
||||
}
|
||||
|
||||
/// Sciter API version.
|
||||
///
|
||||
/// Returns:
|
||||
///
|
||||
/// * `0x0000_0001` for regular builds, `0x0001_0001` for windowless builds.
|
||||
/// * `0x0000_0002` since 4.4.2.14 (a breaking change in assets with [SOM builds](https://sciter.com/native-code-exposure-to-script/))
|
||||
/// * `0x0000_0003` since 4.4.2.16
|
||||
/// * `0x0000_0004` since 4.4.2.17 (a breaking change in SOM passport)
|
||||
/// * `0x0000_0005` since 4.4.3.20 (a breaking change in `INITIALIZATION_PARAMS`, SOM in event handlers fix)
|
||||
/// * `0x0000_0006` since 4.4.3.24 (TIScript native API is gone, use SOM instead)
|
||||
///
|
||||
/// Since 4.4.0.3.
|
||||
pub fn api_version() -> u32 {
|
||||
_API.version
|
||||
}
|
||||
|
||||
/// Returns true for windowless builds.
|
||||
pub fn is_windowless() -> bool {
|
||||
api_version() >= 0x0001_0001
|
||||
}
|
||||
|
||||
/// Various global Sciter engine options.
|
||||
///
|
||||
/// Used by [`sciter::set_options()`](fn.set_options.html).
|
||||
///
|
||||
/// See also [per-window options](window/enum.Options.html).
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum RuntimeOptions<'a> {
|
||||
|
||||
/// global; value: the full path to the Sciter dynamic library (dll/dylib/so),
|
||||
/// must be called before any other Sciter function.
|
||||
LibraryPath(&'a str),
|
||||
/// global; value: [`GFX_LAYER`](enum.GFX_LAYER.html), must be called before any window creation.
|
||||
GfxLayer(GFX_LAYER),
|
||||
/// global; value: `true` - the engine will use a "unisex" theme that is common for all platforms.
|
||||
/// That UX theme is not using OS primitives for rendering input elements.
|
||||
/// Use it if you want exactly the same (modulo fonts) look-n-feel on all platforms.
|
||||
UxTheming(bool),
|
||||
/// global or per-window; enables Sciter Inspector for all windows, must be called before any window creation.
|
||||
DebugMode(bool),
|
||||
/// global or per-window; value: combination of [`SCRIPT_RUNTIME_FEATURES`](enum.SCRIPT_RUNTIME_FEATURES.html) flags.
|
||||
///
|
||||
/// Note that these features have been disabled by default
|
||||
/// since [4.2.5.0](https://rawgit.com/c-smile/sciter-sdk/7036a9c7912ac30d9f369d9abb87b278d2d54c6d/logfile.htm).
|
||||
ScriptFeatures(u8),
|
||||
/// global; value: milliseconds, connection timeout of http client.
|
||||
ConnectionTimeout(u32),
|
||||
/// global; value: `0` - drop connection, `1` - use builtin dialog, `2` - accept connection silently.
|
||||
OnHttpsError(u8),
|
||||
// global; value: json with GPU black list, see the `gpu-blacklist.json` resource.
|
||||
// Not used in Sciter 4, in fact: https://sciter.com/forums/topic/how-to-use-the-gpu-blacklist/#post-59338
|
||||
// GpuBlacklist(&'a str),
|
||||
/// global; value: script source to be loaded into each view before any other script execution.
|
||||
InitScript(&'a str),
|
||||
/// global; value - max request length in megabytes (1024*1024 bytes), since 4.3.0.15.
|
||||
MaxHttpDataLength(usize),
|
||||
}
|
||||
|
||||
/// Set various global Sciter engine options, see the [`RuntimeOptions`](enum.RuntimeOptions.html).
|
||||
pub fn set_options(options: RuntimeOptions) -> std::result::Result<(), ()> {
|
||||
use RuntimeOptions::*;
|
||||
use capi::scdef::SCITER_RT_OPTIONS::*;
|
||||
let (option, value) = match options {
|
||||
ConnectionTimeout(ms) => (SCITER_CONNECTION_TIMEOUT, ms as usize),
|
||||
OnHttpsError(behavior) => (SCITER_HTTPS_ERROR, behavior as usize),
|
||||
// GpuBlacklist(json) => (SCITER_SET_GPU_BLACKLIST, json.as_bytes().as_ptr() as usize),
|
||||
InitScript(script) => (SCITER_SET_INIT_SCRIPT, script.as_bytes().as_ptr() as usize),
|
||||
ScriptFeatures(mask) => (SCITER_SET_SCRIPT_RUNTIME_FEATURES, mask as usize),
|
||||
GfxLayer(backend) => (SCITER_SET_GFX_LAYER, backend as usize),
|
||||
DebugMode(enable) => (SCITER_SET_DEBUG_MODE, enable as usize),
|
||||
UxTheming(enable) => (SCITER_SET_UX_THEMING, enable as usize),
|
||||
MaxHttpDataLength(value) => (SCITER_SET_MAX_HTTP_DATA_LENGTH, value),
|
||||
LibraryPath(path) => {
|
||||
return set_library(path).map_err(|_|());
|
||||
}
|
||||
};
|
||||
let ok = (_API.SciterSetOption)(std::ptr::null_mut(), option, value);
|
||||
if ok != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
264
libs/rust-sciter/src/macros.rs
Normal file
264
libs/rust-sciter/src/macros.rs
Normal file
@@ -0,0 +1,264 @@
|
||||
//! Macros
|
||||
|
||||
/// Rust string to UTF-8 conversion. See also `utf::u2s`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let cstr = s2u!("hello"); // ffi::CString
|
||||
/// libc::printf("%hs", cstr.as_ptr());
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! s2u {
|
||||
($s:expr) => ( $crate::utf::s2un($s.as_ref()).0 )
|
||||
}
|
||||
|
||||
/// Rust string to UTF-8 conversion. See also `utf::u2s`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let (cstr, len) = s2un!("hello"); // ffi::CString
|
||||
/// libc::printf("%.*hs", len, cstr.as_ptr());
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! s2un {
|
||||
($s:expr) => ( $crate::utf::s2un($s.as_ref()) )
|
||||
}
|
||||
|
||||
|
||||
/// Rust string to UTF-16 conversion. See also `utf::w2s`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let cwstr = s2w!("hello"); // Vec<u16>
|
||||
/// libc::printf("%ws", cwstr.as_ptr());
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! s2w {
|
||||
($s:expr) => ( $crate::utf::s2vec($s.as_ref()) )
|
||||
}
|
||||
|
||||
/// Rust string to UTF-16 conversion. See also `utf::w2s`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let (cwstr, len) = s2wn!("hello"); // Vec<u16>
|
||||
/// libc::printf("%.*ws", len, cwstr.as_ptr());
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! s2wn {
|
||||
($s:expr) => ( $crate::utf::s2vecn($s.as_ref()) )
|
||||
}
|
||||
|
||||
|
||||
/// UTF-16 to `String` conversion.
|
||||
#[macro_export]
|
||||
macro_rules! w2s {
|
||||
($s:expr) => ( $crate::utf::w2s($s) )
|
||||
}
|
||||
|
||||
|
||||
/// UTF-8 to `String` conversion.
|
||||
#[macro_export]
|
||||
macro_rules! u2s {
|
||||
($s:expr) => ( $crate::utf::u2s($s) )
|
||||
}
|
||||
|
||||
|
||||
/// Pack arguments to call the Sciter script function.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! pack_args {
|
||||
() => { $crate::value::Value::pack_args(&[]) };
|
||||
|
||||
( $($s:expr),* ) => {
|
||||
{
|
||||
let args = [
|
||||
$(
|
||||
$crate::value::Value::from($s)
|
||||
),*
|
||||
];
|
||||
$crate::value::Value::pack_args(&args)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Pack arguments into a `[Value]` array to call Sciter script functions.
|
||||
///
|
||||
/// Used in [`Element.call_function()`](dom/struct.Element.html#method.call_function),
|
||||
/// [`Element.call_method()`](dom/struct.Element.html#method.call_method),
|
||||
/// [`Host.call_function()`](host/struct.Host.html#method.call_function),
|
||||
/// [`Value.call()`](value/struct.Value.html#method.call).
|
||||
///
|
||||
/// ## Example:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// # #![doc(test(no_crate_inject))]
|
||||
/// # #[macro_use] extern crate sciter;
|
||||
/// let value = sciter::Value::new();
|
||||
/// let result = value.call(None, &make_args!(1, "2", 3.0), Some(file!())).unwrap();
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! make_args {
|
||||
() => { { let args : [$crate::value::Value; 0] = []; args } };
|
||||
|
||||
( $($s:expr),* ) => {
|
||||
{
|
||||
let args = [
|
||||
$(
|
||||
$crate::value::Value::from($s)
|
||||
),*
|
||||
];
|
||||
args
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
/// Declare handle type (native pointer).
|
||||
macro_rules! MAKE_HANDLE {
|
||||
($(#[$attrs:meta])* $name:ident, $inner:ident) => {
|
||||
#[repr(C)] #[doc(hidden)]
|
||||
pub struct $inner { _unused: usize }
|
||||
$(#[$attrs])*
|
||||
pub type $name = *mut $inner;
|
||||
};
|
||||
}
|
||||
|
||||
/// Dispatch script calls to native code. Used in [`dom::EventHandler`](dom/event/trait.EventHandler.html) implementations.
|
||||
///
|
||||
/// This macro generates a new function which dispatches incoming script calls to the corresponding native functions
|
||||
/// with arguments unpacking and type checking.
|
||||
///
|
||||
/// Note: unstable, will be improved.
|
||||
#[macro_export]
|
||||
macro_rules! dispatch_script_call {
|
||||
|
||||
(
|
||||
$(
|
||||
fn $name:ident ( $( $argt:ident ),* );
|
||||
)*
|
||||
) => {
|
||||
|
||||
fn dispatch_script_call(&mut self, _root: $crate::HELEMENT, name: &str, argv: &[$crate::Value]) -> Option<$crate::Value>
|
||||
{
|
||||
match name {
|
||||
$(
|
||||
stringify!($name) => {
|
||||
|
||||
// args count
|
||||
let mut _i = 0;
|
||||
$(
|
||||
let _: $argt;
|
||||
_i += 1;
|
||||
)*
|
||||
let argc = _i;
|
||||
|
||||
if argv.len() != argc {
|
||||
return Some($crate::Value::error(&format!("{} error: {} of {} arguments provided.", stringify!($name), argv.len(), argc)));
|
||||
}
|
||||
|
||||
// call function
|
||||
let mut _i = 0;
|
||||
let rv = self.$name(
|
||||
$(
|
||||
{
|
||||
match $crate::FromValue::from_value(&argv[_i]) {
|
||||
Some(arg) => { _i += 1; arg },
|
||||
None => {
|
||||
// invalid type
|
||||
return Some($crate::Value::error(&format!("{} error: invalid type of {} argument ({} expected, {:?} provided).",
|
||||
stringify!($name), _i, stringify!($argt), argv[_i])));
|
||||
},
|
||||
}
|
||||
}
|
||||
),*
|
||||
);
|
||||
|
||||
// return result value
|
||||
return Some($crate::Value::from(rv));
|
||||
},
|
||||
)*
|
||||
|
||||
_ => ()
|
||||
};
|
||||
|
||||
// script call not handled
|
||||
return None;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// Create a `sciter::Value` (of map type) from a list of key-value pairs.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate sciter;
|
||||
/// # fn main() {
|
||||
/// let v: sciter::Value = vmap! {
|
||||
/// "one" => 1,
|
||||
/// "two" => 2.0,
|
||||
/// "three" => "",
|
||||
/// };
|
||||
/// assert!(v.is_map());
|
||||
/// assert_eq!(v.len(), 3);
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! vmap {
|
||||
( $($key:expr => $value:expr,)+ ) => { vmap!($($key => $value),+) };
|
||||
( $($key:expr => $value:expr),* ) => {
|
||||
{
|
||||
let mut _v = $crate::Value::map();
|
||||
$(
|
||||
_v.set_item($key, $value);
|
||||
)*
|
||||
_v
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates a `sciter::Value` (of array type) containing the arguments.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate sciter;
|
||||
/// # fn main() {
|
||||
/// let v: sciter::Value = varray![1, 2.0, "three"];
|
||||
/// assert!(v.is_array());
|
||||
/// assert_eq!(v.len(), 3);
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! varray {
|
||||
( $($value:expr,)+ ) => { varray!($($value),+) };
|
||||
( $($value:expr),* ) => {
|
||||
{
|
||||
// args count
|
||||
let mut _i = 0;
|
||||
$(
|
||||
let _ = &$value;
|
||||
_i += 1;
|
||||
)*
|
||||
let argc = _i;
|
||||
let mut _v = $crate::Value::array(argc);
|
||||
let mut _i = 0;
|
||||
$(
|
||||
_v.set(_i, $value);
|
||||
_i += 1;
|
||||
)*
|
||||
_v
|
||||
}
|
||||
};
|
||||
}
|
||||
271
libs/rust-sciter/src/om.rs
Normal file
271
libs/rust-sciter/src/om.rs
Normal file
@@ -0,0 +1,271 @@
|
||||
/*! Sciter Object Model (SOM passport).
|
||||
|
||||
See [Native code exposure to script](http://sciter.com/native-code-exposure-to-script/)
|
||||
and [Sciter Object Model](http://sciter.com/developers/for-native-gui-programmers/sciter-object-model/) blog articles.
|
||||
|
||||
*/
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
use capi::sctypes::{LPVOID, LPCSTR};
|
||||
pub use capi::scom::*;
|
||||
|
||||
|
||||
/// Get the index of an interned string.
|
||||
pub fn atom(name: &str) -> som_atom_t {
|
||||
let s = s2u!(name);
|
||||
(crate::_API.SciterAtomValue)(s.as_ptr())
|
||||
}
|
||||
|
||||
/// Get the value of an interned string.
|
||||
pub fn atom_name(id: som_atom_t) -> Option<String> {
|
||||
let mut s = String::new();
|
||||
let ok = (crate::_API.SciterAtomNameCB)(id, crate::utf::store_astr, &mut s as *mut _ as LPVOID);
|
||||
if ok != 0 {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Something that has a SOM passport.
|
||||
///
|
||||
/// However, since we can't call extern functions in static object initialization,
|
||||
/// in order to use [`atom("name")`](fn.atom.html) we have to initializa the passport in run time
|
||||
/// and return a reference to it via [`Box::leak()`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.leak).
|
||||
pub trait Passport {
|
||||
/// A static reference to the passport that describes an asset.
|
||||
fn get_passport(&self) -> &'static som_passport_t;
|
||||
}
|
||||
|
||||
|
||||
/// A non-owning pointer to a native object.
|
||||
pub struct IAssetRef<T> {
|
||||
asset: *mut som_asset_t,
|
||||
ty: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for IAssetRef<T> {
|
||||
fn clone(&self) -> Self {
|
||||
self.add_ref();
|
||||
Self {
|
||||
asset: self.asset,
|
||||
ty: self.ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for IAssetRef<T> {
|
||||
fn drop(&mut self) {
|
||||
self.release();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::fmt::Debug for IAssetRef<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
// the current reference count
|
||||
self.add_ref();
|
||||
let rc = self.release();
|
||||
|
||||
let name = self::atom_name(self.get_passport().name);
|
||||
write!(f, "Asset({}):{}", name.unwrap_or_default(), rc)
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a reference from a managed asset.
|
||||
impl<T> From<Box<IAsset<T>>> for IAssetRef<T> {
|
||||
fn from(asset: Box<IAsset<T>>) -> Self {
|
||||
Self::from_raw(IAsset::into_raw(asset))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IAssetRef<T> {
|
||||
/// Get the vtable of an asset.
|
||||
fn isa(&self) -> &'static som_asset_class_t {
|
||||
unsafe { (*self.asset).isa }
|
||||
}
|
||||
|
||||
/// Increment the reference count of an asset and returns the new value.
|
||||
fn add_ref(&self) -> i32 {
|
||||
(self.isa().add_ref)(self.asset)
|
||||
}
|
||||
|
||||
/// Decrement the reference count of an asset and returns the new value.
|
||||
fn release(&self) -> i32 {
|
||||
(self.isa().release)(self.asset)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IAssetRef<T> {
|
||||
/// Construct from a raw pointer, incrementing the reference count.
|
||||
pub fn from_raw(asset: *mut som_asset_t) -> Self {
|
||||
eprintln!("IAssetRef<{}>::from({:?})", std::any::type_name::<T>(), asset);
|
||||
assert!(asset.is_null() == false);
|
||||
let me = Self {
|
||||
asset,
|
||||
ty: std::marker::PhantomData,
|
||||
};
|
||||
me.add_ref();
|
||||
me
|
||||
}
|
||||
|
||||
/// Return the raw pointer, releasing the reference count.
|
||||
pub fn into_raw(asset: IAssetRef<T>) -> *mut som_asset_t {
|
||||
// decrement reference count
|
||||
asset.release();
|
||||
|
||||
// get the pointer and forget about this wrapper
|
||||
let ptr = asset.asset;
|
||||
std::mem::forget(asset);
|
||||
|
||||
ptr
|
||||
}
|
||||
|
||||
/// Get the underlaying pointer.
|
||||
pub fn as_ptr(&self) -> *mut som_asset_t {
|
||||
self.asset
|
||||
}
|
||||
|
||||
/// Get a reference to the underlaying pointer.
|
||||
#[doc(hidden)]
|
||||
pub fn as_ref(&self) -> &som_asset_t {
|
||||
// TODO: do we need this?
|
||||
unsafe { & *self.asset }
|
||||
}
|
||||
|
||||
/// Get the passport of the asset.
|
||||
pub fn get_passport(&self) -> &som_passport_t {
|
||||
// TODO: do we need this?
|
||||
let ptr = (self.isa().get_passport)(self.asset);
|
||||
unsafe { & *ptr }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// An owned pointer to a wrapped native object.
|
||||
#[repr(C)]
|
||||
pub struct IAsset<T> {
|
||||
// NB: should be the first member here
|
||||
// in order to `*mut IAsset as *mut som_asset_t` work
|
||||
asset: som_asset_t,
|
||||
refc: AtomicI32,
|
||||
passport: Option<&'static som_passport_t>,
|
||||
data: T,
|
||||
}
|
||||
|
||||
/// Make the object to be accessible as other global objects in TIScript.
|
||||
pub fn set_global<T>(asset: IAssetRef<T>) {
|
||||
let ptr = asset.as_ptr();
|
||||
// eprintln!("IAsset<{}>: {:?}", std::any::type_name::<T>(), ptr);
|
||||
(crate::_API.SciterSetGlobalAsset)(ptr);
|
||||
}
|
||||
|
||||
/// Make the object to be accessible as other global objects in TIScript.
|
||||
pub fn into_global<T>(asset: Box<IAsset<T>>) {
|
||||
let ptr = IAsset::into_raw(asset);
|
||||
// eprintln!("IAsset<{}>: {:?}", std::any::type_name::<T>(), ptr);
|
||||
(crate::_API.SciterSetGlobalAsset)(ptr);
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for IAsset<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::DerefMut for IAsset<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for IAsset<T> {
|
||||
fn drop(&mut self) {
|
||||
let rc = self.refc.load(Ordering::SeqCst);
|
||||
if rc != 0 {
|
||||
eprintln!("asset<{}>::drop with {} references alive", std::any::type_name::<T>(), rc);
|
||||
}
|
||||
assert_eq!(rc, 0);
|
||||
// allocated in `iasset::new()`
|
||||
let ptr = self.asset.isa as *const som_asset_class_t;
|
||||
let ptr = unsafe { Box::from_raw(ptr as *mut som_asset_class_t) };
|
||||
drop(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IAsset<T> {
|
||||
/// Cast the pointer to a managed asset reference.
|
||||
pub fn from_raw(thing: &*mut som_asset_t) -> &mut IAsset<T> {
|
||||
assert!(thing.is_null() == false);
|
||||
unsafe { &mut *(*thing as *mut IAsset<T>) }
|
||||
}
|
||||
|
||||
/// Release the pointer.
|
||||
fn into_raw(asset: Box<IAsset<T>>) -> *mut som_asset_t {
|
||||
let p = Box::into_raw(asset);
|
||||
p as *mut som_asset_t
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Passport> IAsset<T> {
|
||||
/// Wrap the object into a managed asset.
|
||||
pub fn new(data: T) -> Box<Self> {
|
||||
// will be freed in `iasset<T>::drop()`
|
||||
let isa = Box::new(Self::class());
|
||||
|
||||
let me = Self {
|
||||
asset: som_asset_t { isa: Box::leak(isa) },
|
||||
refc: Default::default(),
|
||||
passport: None,
|
||||
data,
|
||||
};
|
||||
Box::new(me)
|
||||
}
|
||||
|
||||
fn class() -> som_asset_class_t {
|
||||
extern "C" fn asset_add_ref<T>(thing: *mut som_asset_t) -> i32 {
|
||||
{
|
||||
let me = IAsset::<T>::from_raw(&thing);
|
||||
let t = me.refc.fetch_add(1, Ordering::SeqCst) + 1;
|
||||
// eprintln!("iasset<T>::add_ref() -> {}", t);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
extern "C" fn asset_release<T>(thing: *mut som_asset_t) -> i32 {
|
||||
let t = {
|
||||
let me = IAsset::<T>::from_raw(&thing);
|
||||
me.refc.fetch_sub(1, Ordering::SeqCst) - 1
|
||||
};
|
||||
// eprintln!("iasset<T>::release() -> {}", t);
|
||||
if t == 0 {
|
||||
// eprintln!("iasset<T>::drop()");
|
||||
let me = unsafe { Box::from_raw(thing as *mut IAsset<T>) };
|
||||
drop(me);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
extern "C" fn asset_get_interface<T>(_thing: *mut som_asset_t, name: LPCSTR, _out: *mut *mut som_asset_t) -> bool {
|
||||
let name = u2s!(name);
|
||||
eprintln!("iasset<T>::get_interface({}) is not implemented.", name);
|
||||
return false;
|
||||
}
|
||||
extern "C" fn asset_get_passport<T: Passport>(thing: *mut som_asset_t) -> *const som_passport_t
|
||||
{
|
||||
// here we cache the returned reference in order not to allocate things again
|
||||
let me = IAsset::<T>::from_raw(&thing);
|
||||
if me.passport.is_none() {
|
||||
// eprintln!("asset_get_passport<{}>: {:?}", std::any::type_name::<T>(), thing);
|
||||
me.passport = Some(me.data.get_passport());
|
||||
}
|
||||
let ps = me.passport.as_ref().unwrap();
|
||||
return *ps;
|
||||
}
|
||||
|
||||
som_asset_class_t {
|
||||
add_ref: asset_add_ref::<T>,
|
||||
release: asset_release::<T>,
|
||||
get_interface: asset_get_interface::<T>,
|
||||
get_passport: asset_get_passport::<T>,
|
||||
}
|
||||
}
|
||||
}
|
||||
480
libs/rust-sciter/src/platform.rs
Normal file
480
libs/rust-sciter/src/platform.rs
Normal file
@@ -0,0 +1,480 @@
|
||||
//! Platform-dependent windows support.
|
||||
|
||||
use capi::sctypes::*;
|
||||
|
||||
|
||||
pub trait BaseWindow {
|
||||
|
||||
fn create(&mut self, rc: RECT, flags: UINT, parent: HWINDOW) -> HWINDOW;
|
||||
|
||||
fn get_hwnd(&self) -> HWINDOW;
|
||||
|
||||
fn collapse(&self, hide: bool);
|
||||
fn expand(&self, maximize: bool);
|
||||
fn dismiss(&self);
|
||||
|
||||
fn set_title(&mut self, title: &str);
|
||||
fn get_title(&self) -> String;
|
||||
|
||||
fn run_app(&self);
|
||||
fn quit_app(&self);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
mod windows {
|
||||
|
||||
use ::{_API};
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::*;
|
||||
|
||||
|
||||
#[link(name="user32")]
|
||||
extern "system"
|
||||
{
|
||||
fn ShowWindow(hwnd: HWINDOW, show: INT) -> BOOL;
|
||||
fn PostMessageW(hwnd: HWINDOW, msg: UINT, w: WPARAM, l: LPARAM) -> BOOL;
|
||||
fn SetWindowTextW(hwnd: HWINDOW, s: LPCWSTR) -> BOOL;
|
||||
fn GetWindowTextLengthW(hwnd: HWINDOW) -> INT;
|
||||
fn GetWindowTextW(hwnd: HWINDOW, s: LPWSTR, l: INT) -> INT;
|
||||
fn GetMessageW(msg: LPMSG, hwnd: HWINDOW, min: UINT, max: UINT) -> BOOL;
|
||||
fn DispatchMessageW(msg: LPMSG) -> LRESULT;
|
||||
fn TranslateMessage(msg: LPMSG) -> BOOL;
|
||||
fn PostQuitMessage(code: INT);
|
||||
}
|
||||
|
||||
#[link(name="ole32")]
|
||||
extern "system"
|
||||
{
|
||||
fn OleInitialize(pv: LPCVOID) -> i32; // HRESULT
|
||||
}
|
||||
|
||||
pub struct OsWindow
|
||||
{
|
||||
hwnd: HWINDOW,
|
||||
flags: UINT,
|
||||
}
|
||||
|
||||
impl OsWindow {
|
||||
|
||||
pub fn new() -> OsWindow {
|
||||
OsWindow { hwnd: 0 as HWINDOW, flags: 0 }
|
||||
}
|
||||
|
||||
pub fn from(hwnd: HWINDOW) -> OsWindow {
|
||||
OsWindow { hwnd: hwnd, flags: 0 }
|
||||
}
|
||||
|
||||
fn init_app() {
|
||||
unsafe { OleInitialize(::std::ptr::null()) };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl super::BaseWindow for OsWindow {
|
||||
|
||||
/// Get native window handle.
|
||||
fn get_hwnd(&self) -> HWINDOW {
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
OsWindow::init_app();
|
||||
}
|
||||
|
||||
self.flags = flags;
|
||||
|
||||
#[cfg(not(feature = "windowless"))]
|
||||
{
|
||||
let cb = ::std::ptr::null();
|
||||
self.hwnd = (_API.SciterCreateWindow)(flags, &rc, cb, 0 as LPVOID, parent);
|
||||
if self.hwnd.is_null() {
|
||||
panic!("Failed to create window!");
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "windowless")]
|
||||
{
|
||||
let _ = rc;
|
||||
let _ = parent;
|
||||
let _ = &(_API.SciterVersion);
|
||||
}
|
||||
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Minimize or hide window.
|
||||
fn collapse(&self, hide: bool) {
|
||||
let n: INT = if hide { 0 } else { 6 };
|
||||
unsafe { ShowWindow(self.hwnd, n) };
|
||||
}
|
||||
|
||||
/// Show or maximize window.
|
||||
fn expand(&self, maximize: bool) {
|
||||
let n: INT = if maximize { 3 } else { 1 };
|
||||
unsafe { ShowWindow(self.hwnd, n) };
|
||||
}
|
||||
|
||||
/// Close window.
|
||||
fn dismiss(&self) {
|
||||
unsafe { PostMessageW(self.hwnd, 0x0010, 0, 0) };
|
||||
}
|
||||
|
||||
/// Set native window title.
|
||||
fn set_title(&mut self, title: &str) {
|
||||
let s = s2w!(title);
|
||||
unsafe { SetWindowTextW(self.hwnd, s.as_ptr()) };
|
||||
}
|
||||
|
||||
/// Get native window title.
|
||||
fn get_title(&self) -> String {
|
||||
|
||||
let n = unsafe { GetWindowTextLengthW(self.hwnd) + 1 };
|
||||
let mut title: Vec<u16> = Vec::new();
|
||||
title.resize(n as usize, 0);
|
||||
unsafe { GetWindowTextW(self.hwnd, title.as_mut_ptr(), n) };
|
||||
return ::utf::w2s(title.as_ptr());
|
||||
}
|
||||
|
||||
/// Run the main app message loop until window been closed.
|
||||
fn run_app(&self) {
|
||||
let mut msg = MSG { hwnd: 0 as HWINDOW, message: 0, wParam: 0, lParam: 0, time: 0, pt: POINT { x: 0, y: 0 } };
|
||||
let pmsg: LPMSG = &mut msg;
|
||||
let null: HWINDOW = ::std::ptr::null_mut();
|
||||
unsafe {
|
||||
while GetMessageW(pmsg, null, 0, 0) != 0 {
|
||||
TranslateMessage(pmsg);
|
||||
DispatchMessageW(pmsg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Post app quit message.
|
||||
fn quit_app(&self) {
|
||||
unsafe { PostQuitMessage(0) };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
mod windows {
|
||||
|
||||
use ::{_API};
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::*;
|
||||
use super::BaseWindow;
|
||||
|
||||
use ::std::ptr;
|
||||
|
||||
#[link(name="gtk-3")]
|
||||
extern "C"
|
||||
{
|
||||
fn gtk_init(argc: *const i32, argv: *const *const LPCSTR);
|
||||
fn gtk_main();
|
||||
fn gtk_main_quit();
|
||||
fn gtk_widget_get_toplevel(view: HWINDOW) -> HWINDOW;
|
||||
fn gtk_window_present(hwnd: HWINDOW);
|
||||
fn gtk_widget_hide(hwnd: HWINDOW);
|
||||
fn gtk_window_maximize(hwnd: HWINDOW);
|
||||
fn gtk_window_iconify(hwnd: HWINDOW);
|
||||
fn gtk_window_close(hwnd: HWINDOW);
|
||||
fn gtk_window_set_title(hwnd: HWINDOW, title: LPCSTR);
|
||||
fn gtk_window_get_title(hwnd: HWINDOW) -> LPCSTR;
|
||||
}
|
||||
|
||||
pub struct OsWindow
|
||||
{
|
||||
hwnd: HWINDOW,
|
||||
flags: UINT,
|
||||
}
|
||||
|
||||
impl OsWindow {
|
||||
|
||||
pub fn new() -> OsWindow {
|
||||
OsWindow { hwnd: 0 as HWINDOW, flags: 0 }
|
||||
}
|
||||
|
||||
pub fn from(hwnd: HWINDOW) -> OsWindow {
|
||||
OsWindow { hwnd: hwnd, flags: 0 }
|
||||
}
|
||||
|
||||
fn init_app() {
|
||||
unsafe { gtk_init(ptr::null(), ptr::null()) };
|
||||
}
|
||||
|
||||
fn window(&self) -> HWINDOW {
|
||||
let hwnd = self.get_hwnd();
|
||||
if hwnd.is_null() {
|
||||
hwnd
|
||||
} else {
|
||||
unsafe { gtk_widget_get_toplevel(hwnd) }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl super::BaseWindow for OsWindow {
|
||||
|
||||
/// Get native window handle.
|
||||
fn get_hwnd(&self) -> HWINDOW {
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
OsWindow::init_app();
|
||||
}
|
||||
|
||||
self.flags = flags;
|
||||
|
||||
#[cfg(not(feature = "windowless"))]
|
||||
{
|
||||
let cb = ptr::null();
|
||||
self.hwnd = (_API.SciterCreateWindow)(flags, &rc, cb, 0 as LPVOID, parent);
|
||||
if self.hwnd.is_null() {
|
||||
panic!("Failed to create window!");
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "windowless")]
|
||||
{
|
||||
let _ = rc;
|
||||
let _ = parent;
|
||||
let _ = &(_API.SciterVersion);
|
||||
}
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Minimize or hide window.
|
||||
fn collapse(&self, hide: bool) {
|
||||
unsafe {
|
||||
if hide {
|
||||
gtk_widget_hide(self.get_hwnd())
|
||||
} else {
|
||||
gtk_window_iconify(self.window())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Show or maximize window.
|
||||
fn expand(&self, maximize: bool) {
|
||||
let wnd = self.window();
|
||||
unsafe {
|
||||
if maximize {
|
||||
gtk_window_maximize(wnd)
|
||||
} else {
|
||||
gtk_window_present(wnd)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Close window.
|
||||
fn dismiss(&self) {
|
||||
unsafe { gtk_window_close(self.window()) };
|
||||
}
|
||||
|
||||
/// Set native window title.
|
||||
fn set_title(&mut self, title: &str) {
|
||||
let s = s2u!(title);
|
||||
unsafe { gtk_window_set_title(self.window(), s.as_ptr()) };
|
||||
}
|
||||
|
||||
/// Get native window title.
|
||||
fn get_title(&self) -> String {
|
||||
let s = unsafe { gtk_window_get_title(self.window()) };
|
||||
return u2s!(s);
|
||||
}
|
||||
|
||||
/// Run the main app message loop until window been closed.
|
||||
fn run_app(&self) {
|
||||
unsafe { gtk_main() };
|
||||
}
|
||||
|
||||
/// Post app quit message.
|
||||
fn quit_app(&self) {
|
||||
unsafe { gtk_main_quit() };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
mod windows {
|
||||
|
||||
extern crate objc_foundation;
|
||||
|
||||
use objc::runtime::{Class, Object};
|
||||
use self::objc_foundation::{NSString, INSString};
|
||||
|
||||
|
||||
/// Activation policies that control whether and how an app may be activated.
|
||||
#[repr(C)]
|
||||
#[allow(dead_code)]
|
||||
enum NSApplicationActivationPolicy {
|
||||
Regular = 0,
|
||||
Accessory,
|
||||
Prohibited,
|
||||
}
|
||||
|
||||
|
||||
// Note: Starting some OSX version (perhaps, 10.13),
|
||||
// the AppKit framework isn't loaded implicitly.
|
||||
#[link(name="CoreFoundation", kind="framework")]
|
||||
extern {}
|
||||
|
||||
#[link(name="AppKit", kind="framework")]
|
||||
extern {}
|
||||
|
||||
use ::{_API};
|
||||
use capi::sctypes::*;
|
||||
use capi::scdef::*;
|
||||
use super::BaseWindow;
|
||||
|
||||
pub struct OsWindow
|
||||
{
|
||||
hwnd: HWINDOW,
|
||||
flags: UINT,
|
||||
}
|
||||
|
||||
impl OsWindow {
|
||||
|
||||
pub fn new() -> OsWindow {
|
||||
OsWindow { hwnd: 0 as HWINDOW, flags: 0, }
|
||||
}
|
||||
|
||||
pub fn from(hwnd: HWINDOW) -> OsWindow {
|
||||
OsWindow { hwnd: hwnd, flags: 0 }
|
||||
}
|
||||
|
||||
fn get_app() -> *mut Object {
|
||||
let cls = Class::get("NSApplication").expect("`NSApplication` is not registered.");
|
||||
let obj = unsafe { msg_send!(cls, sharedApplication) };
|
||||
return obj;
|
||||
}
|
||||
|
||||
fn init_app() {
|
||||
// By default, unbundled apps start with `NSApplicationActivationPolicyProhibited` (no dock, no menu).
|
||||
let app = OsWindow::get_app();
|
||||
let _: () = unsafe { msg_send!(app, setActivationPolicy:NSApplicationActivationPolicy::Regular) };
|
||||
}
|
||||
|
||||
fn view(&self) -> *mut Object {
|
||||
let hwnd = self.get_hwnd();
|
||||
let hwnd: *mut Object = unsafe { ::std::mem::transmute(hwnd) };
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
fn window(&self) -> *mut Object {
|
||||
let hwnd = self.view();
|
||||
let obj: *mut Object = unsafe { msg_send!(hwnd, window) };
|
||||
assert!(!obj.is_null());
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
impl super::BaseWindow for OsWindow {
|
||||
|
||||
/// Get native window handle.
|
||||
fn get_hwnd(&self) -> HWINDOW {
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
OsWindow::init_app();
|
||||
}
|
||||
|
||||
self.flags = flags;
|
||||
|
||||
#[cfg(not(feature = "windowless"))]
|
||||
{
|
||||
let w = rc.right - rc.left;
|
||||
let h = rc.bottom - rc.top;
|
||||
let prc: *const RECT = if w > 0 && h > 0 {
|
||||
&rc
|
||||
} else {
|
||||
0 as *const RECT
|
||||
};
|
||||
|
||||
let cb = 0 as *const SciterWindowDelegate;
|
||||
self.hwnd = (_API.SciterCreateWindow)(flags, prc, cb, 0 as LPVOID, parent);
|
||||
if self.hwnd.is_null() {
|
||||
panic!("Failed to create window!");
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "windowless")]
|
||||
{
|
||||
let _ = rc;
|
||||
let _ = parent;
|
||||
let _ = &(_API.SciterVersion);
|
||||
}
|
||||
return self.hwnd;
|
||||
}
|
||||
|
||||
/// Minimize or hide window.
|
||||
fn collapse(&self, hide: bool) {
|
||||
let wnd = self.window();
|
||||
if hide {
|
||||
let _: () = unsafe { msg_send!(wnd, orderOut:0) };
|
||||
} else {
|
||||
let hwnd = self.view();
|
||||
let _: () = unsafe { msg_send!(wnd, performMiniaturize:hwnd) };
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
let app = OsWindow::get_app();
|
||||
let _: () = unsafe { msg_send!(app, activateIgnoringOtherApps:true) };
|
||||
}
|
||||
unsafe {
|
||||
let _: () = msg_send!(wnd, makeKeyAndOrderFront:0);
|
||||
// msg_send!(wnd, orderFrontRegardless);
|
||||
}
|
||||
if maximize {
|
||||
let _: () = unsafe { msg_send!(wnd, performZoom:0) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Close window.
|
||||
fn dismiss(&self) {
|
||||
let wnd = self.window();
|
||||
let _: () = unsafe { msg_send!(wnd, close) };
|
||||
}
|
||||
|
||||
/// Set native window title.
|
||||
fn set_title(&mut self, title: &str) {
|
||||
let s = NSString::from_str(title);
|
||||
let wnd = self.window();
|
||||
let _: () = unsafe { msg_send!(wnd, setTitle:s) };
|
||||
}
|
||||
|
||||
/// Get native window title.
|
||||
fn get_title(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
/// Run the main app message loop until window been closed.
|
||||
fn run_app(&self) {
|
||||
let app = OsWindow::get_app();
|
||||
let _: () = unsafe { msg_send!(app, finishLaunching) };
|
||||
let _: () = unsafe { msg_send!(app, run) };
|
||||
}
|
||||
|
||||
/// Post app quit message.
|
||||
fn quit_app(&self) {
|
||||
let app = OsWindow::get_app();
|
||||
let _: () = unsafe { msg_send!(app, terminate:app) };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub type OsWindow = windows::OsWindow;
|
||||
279
libs/rust-sciter/src/request.rs
Normal file
279
libs/rust-sciter/src/request.rs
Normal file
@@ -0,0 +1,279 @@
|
||||
/*! Sciter Request API.
|
||||
|
||||
Handling all attributes of requests (GET/POST/PUT/DELETE) sent by
|
||||
[`Element.request()`](https://sciter.com/docs/content/sciter/Element.htm) and
|
||||
[`View.request()`](https://sciter.com/docs/content/sciter/View.htm)
|
||||
functions and other load requests.
|
||||
|
||||
*/
|
||||
pub use capi::screquest::{HREQUEST, REQUEST_RESULT};
|
||||
pub use capi::screquest::{REQUEST_METHOD, REQUEST_STATE, REQUEST_TYPE, RESOURCE_TYPE};
|
||||
|
||||
use capi::sctypes::{LPVOID, UINT};
|
||||
use capi::scdef::{LPCWSTR_RECEIVER};
|
||||
|
||||
use utf::{store_astr, store_wstr, store_bstr};
|
||||
|
||||
use _RAPI;
|
||||
|
||||
|
||||
|
||||
macro_rules! ok_or {
|
||||
($ok:ident) => {
|
||||
ok_or!((), $ok)
|
||||
};
|
||||
|
||||
($rv:expr, $ok:ident) => {
|
||||
if $ok == REQUEST_RESULT::OK {
|
||||
Ok($rv)
|
||||
} else {
|
||||
Err($ok)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A specialized `Result` type for request operations.
|
||||
pub type Result<T> = ::std::result::Result<T, REQUEST_RESULT>;
|
||||
|
||||
type GetCountFn = extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT;
|
||||
type GetNameFn = extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT;
|
||||
type GetValueFn = extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT;
|
||||
|
||||
/// Request object.
|
||||
///
|
||||
/// Can be constructed from a `HREQUEST` handle only:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use sciter::request::Request;
|
||||
/// # use sciter::host::{SCN_LOAD_DATA, LOAD_RESULT};
|
||||
/// fn on_data_load(pnm: &mut SCN_LOAD_DATA) -> Option<LOAD_RESULT> {
|
||||
/// let mut rq = Request::from(pnm.request_id);
|
||||
/// // ...
|
||||
/// # None
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Request(HREQUEST);
|
||||
|
||||
/// Destroy the object.
|
||||
impl Drop for Request {
|
||||
fn drop(&mut self) {
|
||||
(_RAPI.RequestUnUse)(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies the object.
|
||||
///
|
||||
/// All allocated objects are reference counted so copying is just a matter of increasing reference counts.
|
||||
impl Clone for Request {
|
||||
fn clone(&self) -> Self {
|
||||
let dst = Request(self.0);
|
||||
(_RAPI.RequestUse)(dst.0);
|
||||
dst
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a Request object from `HREQUEST` handle.
|
||||
impl From<HREQUEST> for Request {
|
||||
fn from(hrq: HREQUEST) -> Request {
|
||||
assert!(!hrq.is_null());
|
||||
(_RAPI.RequestUse)(hrq);
|
||||
Request(hrq)
|
||||
}
|
||||
}
|
||||
|
||||
impl Request {
|
||||
/// Mark the request as complete with status and optional data.
|
||||
pub fn succeeded(&mut self, status: u32, data: Option<&[u8]>) -> Result<()> {
|
||||
let (ptr, size) = if let Some(data) = data {
|
||||
(data.as_ptr(), data.len() as u32)
|
||||
} else {
|
||||
(std::ptr::null(), 0_u32)
|
||||
};
|
||||
let ok = (_RAPI.RequestSetSucceeded)(self.0, status, ptr, size);
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Mark the request as complete with failure.
|
||||
pub fn failed(&mut self, status: u32, data: Option<&[u8]>) -> Result<()> {
|
||||
let (ptr, size) = if let Some(data) = data {
|
||||
(data.as_ptr(), data.len() as u32)
|
||||
} else {
|
||||
(std::ptr::null(), 0_u32)
|
||||
};
|
||||
let ok = (_RAPI.RequestSetSucceeded)(self.0, status, ptr, size);
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Append a data chunk to the received data.
|
||||
pub fn append_received_data(&mut self, data: &[u8]) -> Result<()> {
|
||||
let (ptr, size) = (data.as_ptr(), data.len() as u32);
|
||||
let ok = (_RAPI.RequestAppendDataChunk)(self.0, ptr, size);
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Get received (so far) data.
|
||||
pub fn get_received_data(&self) -> Result<Vec<u8>> {
|
||||
let mut data = Vec::new();
|
||||
let ok = (_RAPI.RequestGetData)(self.0, store_bstr, &mut data as *mut _ as LPVOID);
|
||||
ok_or!(data, ok)
|
||||
}
|
||||
|
||||
/// Get the URL of the request.
|
||||
pub fn url(&self) -> Result<String> {
|
||||
let mut s = String::new();
|
||||
let ok = (_RAPI.RequestUrl)(self.0, store_astr, &mut s as *mut _ as LPVOID);
|
||||
ok_or!(s, ok)
|
||||
}
|
||||
|
||||
/// Get a real URL of the content (e.g., after possible redirection).
|
||||
pub fn content_url(&self) -> Result<String> {
|
||||
let mut s = String::new();
|
||||
let ok = (_RAPI.RequestContentUrl)(self.0, store_astr, &mut s as *mut _ as LPVOID);
|
||||
ok_or!(s, ok)
|
||||
}
|
||||
|
||||
/// Get the data type of the request.
|
||||
pub fn method(&self) -> Result<REQUEST_METHOD> {
|
||||
let mut t = REQUEST_METHOD::GET;
|
||||
let ok = (_RAPI.RequestGetRequestType)(self.0, &mut t);
|
||||
ok_or!(t, ok)
|
||||
}
|
||||
|
||||
/// Get the resource data type of the request.
|
||||
pub fn request_type(&self) -> Result<RESOURCE_TYPE> {
|
||||
let mut t = RESOURCE_TYPE::RAW;
|
||||
let ok = (_RAPI.RequestGetRequestedDataType)(self.0, &mut t);
|
||||
ok_or!(t, ok)
|
||||
}
|
||||
|
||||
/// Get the MIME type of the received data.
|
||||
pub fn response_type(&self) -> Result<String> {
|
||||
let mut s = String::new();
|
||||
let ok = (_RAPI.RequestGetReceivedDataType)(self.0, store_astr, &mut s as *mut _ as LPVOID);
|
||||
ok_or!(s, ok)
|
||||
}
|
||||
|
||||
/// Set the MIME type of the received data.
|
||||
pub fn set_response_type(&mut self, mime_type: &str) -> Result<()> {
|
||||
let text = s2u!(mime_type);
|
||||
let ok = (_RAPI.RequestSetReceivedDataType)(self.0, text.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Set the data encoding for the received data.
|
||||
pub fn set_response_encoding(&mut self, encoding_type: &str) -> Result<()> {
|
||||
let text = s2u!(encoding_type);
|
||||
let ok = (_RAPI.RequestSetReceivedDataEncoding)(self.0, text.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
fn get_collection_impl(&self, get_count: GetCountFn, get_name: GetNameFn, get_value: GetValueFn) -> Result<std::collections::HashMap<String, String>> {
|
||||
let mut count = 0;
|
||||
let ok = get_count(self.0, &mut count);
|
||||
if ok != REQUEST_RESULT::OK {
|
||||
return Err(ok);
|
||||
}
|
||||
|
||||
let mut args = std::collections::HashMap::with_capacity(count as usize);
|
||||
for i in 0..count {
|
||||
let mut name = String::new();
|
||||
let mut ok = get_name(self.0, i, store_wstr, &mut name as *mut _ as LPVOID);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
let mut value = String::new();
|
||||
ok = get_value(self.0, i, store_wstr, &mut value as *mut _ as LPVOID);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
args.insert(name, value);
|
||||
}
|
||||
}
|
||||
if ok != REQUEST_RESULT::OK {
|
||||
return Err(ok);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
/// Get the parameters of the request.
|
||||
pub fn parameters(&self) -> Result<std::collections::HashMap<String, String>> {
|
||||
self.get_collection_impl(_RAPI.RequestGetNumberOfParameters, _RAPI.RequestGetNthParameterName, _RAPI.RequestGetNthParameterValue)
|
||||
}
|
||||
|
||||
/// Get the headers of the request.
|
||||
pub fn request_headers(&self) -> Result<std::collections::HashMap<String, String>> {
|
||||
self.get_collection_impl(_RAPI.RequestGetNumberOfRqHeaders, _RAPI.RequestGetNthRqHeaderName, _RAPI.RequestGetNthRqHeaderValue)
|
||||
}
|
||||
|
||||
/// Set request header (a single item).
|
||||
pub fn set_request_header(&mut self, name: &str, value: &str) -> Result<()> {
|
||||
let wname = s2w!(name);
|
||||
let wtext = s2w!(value);
|
||||
let ok = (_RAPI.RequestSetRqHeader)(self.0, wname.as_ptr(), wtext.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Get the headers of the response.
|
||||
pub fn response_headers(&self) -> Result<std::collections::HashMap<String, String>> {
|
||||
self.get_collection_impl(_RAPI.RequestGetNumberOfRspHeaders, _RAPI.RequestGetNthRspHeaderName, _RAPI.RequestGetNthRspHeaderValue)
|
||||
}
|
||||
|
||||
/// Set respone header (a single item).
|
||||
pub fn set_response_header(&mut self, name: &str, value: &str) -> Result<()> {
|
||||
let wname = s2w!(name);
|
||||
let wtext = s2w!(value);
|
||||
let ok = (_RAPI.RequestSetRspHeader)(self.0, wname.as_ptr(), wtext.as_ptr());
|
||||
ok_or!(ok)
|
||||
}
|
||||
|
||||
/// Get proxy host and port (if any).
|
||||
pub fn proxy(&self) -> Result<(String, u16)> {
|
||||
let mut s = String::new();
|
||||
let mut ok = (_RAPI.RequestGetProxyHost)(self.0, store_astr, &mut s as *mut _ as LPVOID);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
let mut n = 0_u32;
|
||||
ok = (_RAPI.RequestGetProxyPort)(self.0, &mut n);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
return Ok((s, n as u16));
|
||||
}
|
||||
}
|
||||
Err(ok)
|
||||
}
|
||||
|
||||
/// Get the current completion status of the request.
|
||||
///
|
||||
/// Returns current state and HTTP response code.
|
||||
pub fn completion_status(&self) -> Result<(REQUEST_STATE, u32)> {
|
||||
let mut state = REQUEST_STATE::SUCCESS;
|
||||
let mut code = 0_u32;
|
||||
let ok = (_RAPI.RequestGetCompletionStatus)(self.0, &mut state, &mut code);
|
||||
ok_or!((state, code), ok)
|
||||
}
|
||||
|
||||
/// Get the execution duratiom of the request.
|
||||
pub fn request_duration(&self) -> Result<std::time::Duration> {
|
||||
let mut started = 0;
|
||||
let mut ended = 0;
|
||||
let ok = (_RAPI.RequestGetTimes)(self.0, &mut started, &mut ended);
|
||||
if ok == REQUEST_RESULT::OK && ended > started {
|
||||
let d = std::time::Duration::from_millis(ended as u64 - started as u64);
|
||||
Ok(d)
|
||||
} else {
|
||||
Err(ok)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the execution `started` and `ended` time of the request, in milliseconds.
|
||||
pub fn request_time(&self) -> Result<(std::time::Duration, std::time::Duration)> {
|
||||
let mut started = 0;
|
||||
let mut ended = 0;
|
||||
let ok = (_RAPI.RequestGetTimes)(self.0, &mut started, &mut ended);
|
||||
if ok == REQUEST_RESULT::OK {
|
||||
use std::time::Duration;
|
||||
let s = Duration::from_millis(started as u64);
|
||||
let e = Duration::from_millis(ended as u64);
|
||||
Ok((s, e))
|
||||
} else {
|
||||
Err(ok)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
5
libs/rust-sciter/src/types.rs
Normal file
5
libs/rust-sciter/src/types.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
//! Export platform-dependent types used by Sciter.
|
||||
|
||||
pub use capi::sctypes::*;
|
||||
pub use capi::scdef::*;
|
||||
pub use capi::scvalue::VALUE;
|
||||
281
libs/rust-sciter/src/utf.rs
Normal file
281
libs/rust-sciter/src/utf.rs
Normal file
@@ -0,0 +1,281 @@
|
||||
//! UTF-8 <> UTF-16 conversion support.
|
||||
|
||||
// Since Rust haven't stable support of UTF-16, I've ported this code
|
||||
// from Sciter SDK (aux-cvt.h)
|
||||
|
||||
// (C) 2003-2015, Andrew Fedoniouk (andrew@terrainformatica.com)
|
||||
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use capi::sctypes::{LPCSTR, LPCWSTR, LPCBYTE};
|
||||
|
||||
|
||||
/// UTF-8 to UTF-16* converter.
|
||||
#[allow(unused_parens)]
|
||||
fn towcs(utf: &[u8], outbuf: &mut Vec<u16>) -> bool
|
||||
{
|
||||
let errc = 0x003F; // '?'
|
||||
let mut num_errors = 0;
|
||||
|
||||
let last = utf.len();
|
||||
let mut pc = 0;
|
||||
while (pc < last) {
|
||||
let mut b = u32::from(utf[pc]); pc += 1;
|
||||
if (b == 0) { break; }
|
||||
|
||||
if ((b & 0x80) == 0) {
|
||||
// 1-BYTE sequence: 000000000xxxxxxx = 0xxxxxxx
|
||||
|
||||
} else if ((b & 0xE0) == 0xC0) {
|
||||
// 2-BYTE sequence: 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
|
||||
if (pc == last) {
|
||||
outbuf.push(errc);
|
||||
num_errors += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
b = (b & 0x1f) << 6;
|
||||
b |= (u32::from(utf[pc]) & 0x3f); pc += 1;
|
||||
|
||||
} else if ((b & 0xf0) == 0xe0) {
|
||||
// 3-BYTE sequence: zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
|
||||
if (pc >= last - 1) {
|
||||
outbuf.push(errc);
|
||||
num_errors += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
b = (b & 0x0f) << 12;
|
||||
b |= (u32::from(utf[pc]) & 0x3f) << 6; pc += 1;
|
||||
b |= (u32::from(utf[pc]) & 0x3f); pc += 1;
|
||||
|
||||
if (b == 0xFEFF && outbuf.is_empty()) { // bom at start
|
||||
continue; // skip it
|
||||
}
|
||||
|
||||
} else if ((b & 0xf8) == 0xf0) {
|
||||
// 4-BYTE sequence: 11101110wwwwzzzzyy + 110111yyyyxxxxxx = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
|
||||
if(pc >= last - 2) { outbuf.push(errc); break; }
|
||||
|
||||
b = (b & 0x07) << 18;
|
||||
b |= (u32::from(utf[pc]) & 0x3f) << 12; pc += 1;
|
||||
b |= (u32::from(utf[pc]) & 0x3f) << 6; pc += 1;
|
||||
b |= (u32::from(utf[pc]) & 0x3f); pc += 1;
|
||||
|
||||
// b shall contain now full 21-bit unicode code point.
|
||||
assert!((b & 0x1f_ffff) == b);
|
||||
if((b & 0x1f_ffff) != b) {
|
||||
outbuf.push(errc);
|
||||
num_errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
outbuf.push( (0xd7c0 + (b >> 10)) as u16 );
|
||||
outbuf.push( (0xdc00 | (b & 0x3ff)) as u16 );
|
||||
|
||||
} else {
|
||||
num_errors += 1;
|
||||
b = u32::from(errc);
|
||||
}
|
||||
|
||||
outbuf.push(b as u16);
|
||||
}
|
||||
return num_errors == 0;
|
||||
}
|
||||
|
||||
|
||||
/// UTF-16 to UTF-8 converter.
|
||||
#[allow(unused_parens)]
|
||||
fn fromwcs(wcs: &[u16], outbuf: &mut Vec<u8>) -> bool
|
||||
{
|
||||
let mut num_errors = 0;
|
||||
|
||||
let last = wcs.len();
|
||||
let mut pc = 0;
|
||||
while (pc < last) {
|
||||
let c = u32::from(wcs[pc]);
|
||||
if (c < (1 << 7)) {
|
||||
outbuf.push(c as u8);
|
||||
|
||||
} else if (c < (1 << 11)) {
|
||||
outbuf.push(((c >> 6) | 0xc0) as u8);
|
||||
outbuf.push(((c & 0x3f) | 0x80) as u8);
|
||||
|
||||
} else if (c < (1 << 16)) {
|
||||
outbuf.push(((c >> 12) | 0xe0) as u8);
|
||||
outbuf.push((((c >> 6) & 0x3f) | 0x80) as u8);
|
||||
outbuf.push(((c & 0x3f) | 0x80) as u8);
|
||||
|
||||
} else if (c < (1 << 21)) {
|
||||
outbuf.push(((c >> 18) | 0xf0) as u8);
|
||||
outbuf.push((((c >> 12) & 0x3f) | 0x80) as u8);
|
||||
outbuf.push((((c >> 6) & 0x3f) | 0x80) as u8);
|
||||
outbuf.push(((c & 0x3f) | 0x80) as u8);
|
||||
|
||||
} else {
|
||||
num_errors += 1;
|
||||
}
|
||||
pc += 1;
|
||||
}
|
||||
return num_errors == 0;
|
||||
}
|
||||
|
||||
|
||||
/// UTF-16 string length like `libc::wcslen`.
|
||||
fn wcslen(sz: LPCWSTR) -> usize
|
||||
{
|
||||
if sz.is_null() {
|
||||
return 0;
|
||||
}
|
||||
let mut i: isize = 0;
|
||||
loop {
|
||||
let c = unsafe { *sz.offset(i) };
|
||||
if c == 0 {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return i as usize;
|
||||
}
|
||||
|
||||
/// UTF8 to Rust string conversion. See also [`s2u!`](../macro.s2u.html).
|
||||
pub fn u2s(sz: LPCSTR) -> String
|
||||
{
|
||||
if sz.is_null() {
|
||||
return String::new();
|
||||
}
|
||||
let cs = unsafe { CStr::from_ptr(sz) };
|
||||
let cow = cs.to_string_lossy();
|
||||
return cow.into_owned();
|
||||
}
|
||||
|
||||
/// UTF8 to Rust string conversion. See also [`s2u!`](../macro.s2u.html).
|
||||
pub fn u2sn(sz: LPCSTR, len: usize) -> String
|
||||
{
|
||||
let chars = unsafe { ::std::slice::from_raw_parts(sz as LPCBYTE, len) };
|
||||
let s = String::from_utf8_lossy(chars).into_owned();
|
||||
return s;
|
||||
}
|
||||
|
||||
/// UTF-16 to Rust string conversion. See also [`s2w!`](../macro.s2w.html).
|
||||
pub fn w2s(sz: LPCWSTR) -> String
|
||||
{
|
||||
return w2sn(sz, wcslen(sz));
|
||||
}
|
||||
|
||||
/// UTF-16 to Rust string conversion. See also [`s2w!`](../macro.s2w.html).
|
||||
pub fn w2sn(sz: LPCWSTR, len: usize) -> String
|
||||
{
|
||||
if sz.is_null() {
|
||||
return String::new();
|
||||
}
|
||||
let chars = unsafe { ::std::slice::from_raw_parts(sz, len) };
|
||||
let s = String::from_utf16_lossy(chars);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Rust string to UTF-8 conversion.
|
||||
pub fn s2un(s: &str) -> (CString, u32) {
|
||||
let cs = CString::new(s.trim_end_matches('\0')).unwrap_or(CString::new("").unwrap());
|
||||
let n = cs.as_bytes().len() as u32;
|
||||
return (cs, n);
|
||||
}
|
||||
|
||||
/// Rust string to UTF-16 conversion.
|
||||
pub fn s2vec(s: &str) -> Vec<u16> {
|
||||
s2vecn(s).0
|
||||
}
|
||||
|
||||
/// Rust string to UTF-16 conversion.
|
||||
pub fn s2vecn(s: &str) -> (Vec<u16>, u32) {
|
||||
let cs = CString::new(s.trim_end_matches('\0')).unwrap_or(CString::new("").unwrap());
|
||||
let mut out = Vec::with_capacity(s.len() * 2);
|
||||
towcs(cs.to_bytes(), &mut out);
|
||||
let n = out.len() as u32;
|
||||
if n > 0 {
|
||||
out.push(0);
|
||||
}
|
||||
return (out, n);
|
||||
}
|
||||
|
||||
use capi::sctypes::{UINT, LPVOID};
|
||||
|
||||
/// Convert an incoming UTF-16 to `String`.
|
||||
pub(crate) extern "system" fn store_wstr(szstr: LPCWSTR, str_length: UINT, param: LPVOID) {
|
||||
let s = self::w2sn(szstr, str_length as usize);
|
||||
let out = param as *mut String;
|
||||
unsafe { *out = s };
|
||||
}
|
||||
|
||||
/// Convert an incoming UTF-8 to `String`.
|
||||
pub(crate) extern "system" fn store_astr(szstr: LPCSTR, str_length: UINT, param: LPVOID) {
|
||||
let s = self::u2sn(szstr, str_length as usize);
|
||||
let out = param as *mut String;
|
||||
unsafe { *out = s };
|
||||
}
|
||||
|
||||
/// Convert an incoming html string (UTF-8 in fact) to `String`.
|
||||
pub(crate) extern "system" fn store_bstr(szstr: LPCBYTE, str_length: UINT, param: LPVOID) {
|
||||
let s = unsafe { ::std::slice::from_raw_parts(szstr, str_length as usize) };
|
||||
let pout = param as *mut Vec<u8>;
|
||||
let out = unsafe {&mut *pout};
|
||||
out.extend_from_slice(s);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use capi::sctypes::{LPCWSTR, LPCSTR};
|
||||
use super::{wcslen, u2s, w2s, s2vec};
|
||||
|
||||
#[test]
|
||||
fn test_wcslen() {
|
||||
let nullptr: LPCWSTR = ::std::ptr::null();
|
||||
assert_eq!(wcslen(nullptr), 0);
|
||||
|
||||
let v = vec![0 as u16];
|
||||
assert_eq!(wcslen(v.as_ptr()), 0);
|
||||
|
||||
let v = vec![32, 32, 0];
|
||||
assert_eq!(wcslen(v.as_ptr()), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_u2s() {
|
||||
let nullptr: LPCSTR = ::std::ptr::null();
|
||||
assert_eq!(u2s(nullptr), String::new());
|
||||
|
||||
let s = "hi, there";
|
||||
assert_eq!(u2s(CString::new(s.trim_end_matches('\0')).unwrap_or(CString::new("").unwrap()).as_ptr()), s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_w2s() {
|
||||
let nullptr: LPCWSTR = ::std::ptr::null();
|
||||
assert_eq!(w2s(nullptr), String::new());
|
||||
|
||||
let v = vec![32, 32, 0]; // SP
|
||||
assert_eq!(w2s(v.as_ptr()), " ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn s2w_test() {
|
||||
let v = s2vec("");
|
||||
assert_eq!(v, []);
|
||||
|
||||
assert_eq!(s2vec(""), []);
|
||||
|
||||
assert_eq!(s2vec("A"), ['A' as u16, 0]);
|
||||
|
||||
assert_eq!(s2vec("AB"), ['A' as u16, 'B' as u16, 0]);
|
||||
|
||||
let (cs, n) = s2wn!("");
|
||||
assert_eq!(n, 0);
|
||||
assert_eq!(cs, []);
|
||||
}
|
||||
}
|
||||
1336
libs/rust-sciter/src/value.rs
Normal file
1336
libs/rust-sciter/src/value.rs
Normal file
File diff suppressed because it is too large
Load Diff
494
libs/rust-sciter/src/video.rs
Normal file
494
libs/rust-sciter/src/video.rs
Normal file
@@ -0,0 +1,494 @@
|
||||
/*! Sciter video rendering.
|
||||
|
||||
Host application can render custom video streams using `<video>` infrastructure.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
use capi::sctypes::{UINT, LPCBYTE, LPCSTR};
|
||||
use capi::scom::som_passport_t;
|
||||
|
||||
/// A type alias for Sciter functions that return `bool`.
|
||||
pub type Result<T> = ::std::result::Result<T, ()>;
|
||||
|
||||
|
||||
/// Color space for video frame.
|
||||
#[repr(C)]
|
||||
pub enum COLOR_SPACE {
|
||||
Unknown,
|
||||
|
||||
Yv12,
|
||||
/// I420
|
||||
Iyuv,
|
||||
Nv12,
|
||||
Yuy2,
|
||||
|
||||
Rgb24,
|
||||
Rgb555,
|
||||
Rgb565,
|
||||
Rgb32,
|
||||
}
|
||||
|
||||
macro_rules! cppcall {
|
||||
// self.func()
|
||||
($this:ident . $func:ident ()) => {
|
||||
unsafe {
|
||||
((*$this.vtbl).$func)($this as *mut _)
|
||||
}
|
||||
};
|
||||
(const $this:ident . $func:ident ()) => {
|
||||
unsafe {
|
||||
((*$this.vtbl).$func)($this as *const _)
|
||||
}
|
||||
};
|
||||
|
||||
// self.func(args...)
|
||||
($this:ident . $func:ident ( $( $arg:expr ),* )) => {
|
||||
unsafe {
|
||||
((*$this.vtbl).$func)($this as *mut _, $($arg),* )
|
||||
}
|
||||
};
|
||||
(const $this:ident . $func:ident ( $( $arg:expr ),* )) => {
|
||||
unsafe {
|
||||
((*$this.vtbl).$func)($this as *const _, $($arg),* )
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! cppresult {
|
||||
( $( $t:tt )* ) => {
|
||||
if cppcall!( $($t)* ) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait NamedInterface {
|
||||
fn get_interface_name() -> &'static [u8];
|
||||
|
||||
fn query_interface(from: &mut iasset) -> Option<* mut iasset> {
|
||||
let mut out: *mut iasset = ::std::ptr::null_mut();
|
||||
from.get_interface(Self::get_interface_name().as_ptr() as LPCSTR, &mut out as *mut _);
|
||||
if !out.is_null() {
|
||||
Some(out)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NamedInterface for video_source {
|
||||
fn get_interface_name() -> &'static [u8] {
|
||||
b"source.video.sciter.com\0"
|
||||
}
|
||||
}
|
||||
|
||||
impl NamedInterface for video_destination {
|
||||
fn get_interface_name() -> &'static [u8] {
|
||||
b"destination.video.sciter.com\0"
|
||||
}
|
||||
}
|
||||
|
||||
impl NamedInterface for fragmented_video_destination {
|
||||
fn get_interface_name() -> &'static [u8] {
|
||||
b"fragmented.destination.video.sciter.com\0"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// COM `IUnknown` alike thing.
|
||||
#[repr(C)]
|
||||
struct iasset_vtbl {
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(this: *mut iasset) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(this: *mut iasset) -> i32,
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub get_interface: extern "C" fn(this: *mut iasset, name: LPCSTR, out: *mut *mut iasset) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
|
||||
}
|
||||
|
||||
/// COM `IUnknown` alike thing.
|
||||
#[repr(C)]
|
||||
pub struct iasset {
|
||||
vtbl: *const iasset_vtbl,
|
||||
}
|
||||
|
||||
impl iasset {
|
||||
/// Increments the reference count for an interface on an object.
|
||||
fn add_ref(&mut self) -> i32 {
|
||||
cppcall!(self.add_ref())
|
||||
}
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
fn release(&mut self) -> i32 {
|
||||
cppcall!(self.release())
|
||||
}
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub fn get_interface(&mut self, name: LPCSTR, out: *mut *mut iasset) -> bool {
|
||||
cppcall!(self.get_interface(name, out))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Video source interface, used by engine to query video state.
|
||||
#[repr(C)]
|
||||
struct video_source_vtbl {
|
||||
// <-- iasset:
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(this: *mut video_source) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(this: *mut video_source) -> i32,
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub get_interface: extern "C" fn(this: *mut video_source, name: *const u8, out: *mut *mut iasset) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
|
||||
// -->
|
||||
|
||||
// <-- video_source
|
||||
pub play: extern "C" fn(this: *mut video_source) -> bool,
|
||||
pub pause: extern "C" fn(this: *mut video_source) -> bool,
|
||||
pub stop: extern "C" fn(this: *mut video_source) -> bool,
|
||||
|
||||
pub get_is_ended: extern "C" fn(this: *const video_source, is_end: *mut bool) -> bool,
|
||||
|
||||
pub get_position: extern "C" fn(this: *const video_source, seconds: *mut f64) -> bool,
|
||||
pub set_position: extern "C" fn(this: *mut video_source, seconds: f64) -> bool,
|
||||
|
||||
pub get_duration: extern "C" fn(this: *const video_source, seconds: *mut f64) -> bool,
|
||||
|
||||
pub get_volume: extern "C" fn(this: *const video_source, volume: *mut f64) -> bool,
|
||||
pub set_volume: extern "C" fn(this: *mut video_source, volume: f64) -> bool,
|
||||
|
||||
pub get_balance: extern "C" fn(this: *const video_source, balance: *mut f64) -> bool,
|
||||
pub set_balance: extern "C" fn(this: *mut video_source, balance: f64) -> bool,
|
||||
// -->
|
||||
}
|
||||
|
||||
/// Video source interface to query video state.
|
||||
#[repr(C)]
|
||||
pub struct video_source {
|
||||
vtbl: *const video_source_vtbl,
|
||||
}
|
||||
|
||||
impl video_source {
|
||||
/// Starts playback from the current position.
|
||||
pub fn play(&mut self) -> Result<()> {
|
||||
cppresult!(self.play())
|
||||
}
|
||||
|
||||
/// Pauses playback.
|
||||
pub fn pause(&mut self) -> Result<()> {
|
||||
cppresult!(self.pause())
|
||||
}
|
||||
|
||||
/// Stops playback.
|
||||
pub fn stop(&mut self) -> Result<()> {
|
||||
cppresult!(self.stop())
|
||||
}
|
||||
|
||||
/// Whether playback has reached the end of the video.
|
||||
pub fn is_ended(&self) -> Result<bool> {
|
||||
let mut r = false;
|
||||
cppresult!(const self.get_is_ended(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Reports the current playback position.
|
||||
pub fn get_position(&self) -> Result<f64> {
|
||||
let mut r = 0f64;
|
||||
cppresult!(const self.get_position(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Sets the current playback position.
|
||||
pub fn set_position(&mut self, seconds: f64) -> Result<()> {
|
||||
cppresult!(self.set_position(seconds))
|
||||
}
|
||||
|
||||
/// Reports the duration of the video in seconds.
|
||||
///
|
||||
/// If duration is not available, returns `0`.
|
||||
pub fn get_duration(&self) -> Result<f64> {
|
||||
let mut r = 0f64;
|
||||
cppresult!(const self.get_duration(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Reports the current volume level of an audio track of the movie.
|
||||
///
|
||||
/// `1.0` corresponds to `0db`, `0.0` (mute) to `-100db`.
|
||||
pub fn get_volume(&self) -> Result<f64> {
|
||||
let mut r = 0f64;
|
||||
cppresult!(const self.get_volume(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Sets the current volume level between `0.0` (mute) and `1.0` (`0db`).
|
||||
pub fn set_volume(&mut self, volume: f64) -> Result<()> {
|
||||
cppresult!(self.set_volume(volume))
|
||||
}
|
||||
|
||||
/// Reports the current stereo balance.
|
||||
pub fn get_balance(&self) -> Result<f64> {
|
||||
let mut r = 0f64;
|
||||
cppresult!(const self.get_balance(&mut r as *mut _)).map(|_| r)
|
||||
}
|
||||
|
||||
/// Sets a new value of the stereo balance.
|
||||
pub fn set_balance(&mut self, balance: f64) -> Result<()> {
|
||||
cppresult!(self.set_balance(balance))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Video destination interface, represents video rendering site.
|
||||
#[repr(C)]
|
||||
struct video_destination_vtbl {
|
||||
// <-- iasset:
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(this: *mut video_destination) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(this: *mut video_destination) -> i32,
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub get_interface: extern "C" fn(this: *mut video_destination, name: *const u8, out: *mut *mut iasset) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
|
||||
// -->
|
||||
|
||||
// <-- video_destination
|
||||
/// Whether this instance of `video_renderer` is attached to a DOM element and is capable of playing.
|
||||
pub is_alive: extern "C" fn(this: *const video_destination) -> bool,
|
||||
|
||||
/// Start streaming/rendering.
|
||||
pub start_streaming: extern "C" fn(this: *mut video_destination, frame_width: i32, frame_height: i32, color_space: COLOR_SPACE, src: *const video_source) -> bool,
|
||||
|
||||
/// Stop streaming.
|
||||
pub stop_streaming: extern "C" fn(this: *mut video_destination) -> bool,
|
||||
|
||||
/// Render the next frame.
|
||||
pub render_frame: extern "C" fn(this: *mut video_destination, data: LPCBYTE, size: UINT) -> bool,
|
||||
// -->
|
||||
}
|
||||
|
||||
/// Video destination interface, represents video rendering site.
|
||||
#[repr(C)]
|
||||
pub struct video_destination {
|
||||
vtbl: *const video_destination_vtbl,
|
||||
}
|
||||
|
||||
impl video_destination {
|
||||
|
||||
/// Whether this instance of `video_renderer` is attached to a DOM element and is capable of playing.
|
||||
pub fn is_alive(&self) -> bool {
|
||||
cppcall!(const self.is_alive())
|
||||
}
|
||||
|
||||
/// Start streaming/rendering.
|
||||
///
|
||||
/// * `frame_size` - the width and the height of the video frame.
|
||||
/// * `color_space` - the color space format of the video frame.
|
||||
/// * `src` - an optional custom [`video_source`](struct.video_source.html) interface implementation, provided by the application.
|
||||
pub fn start_streaming(&mut self, frame_size: (i32, i32), color_space: COLOR_SPACE, src: Option<&video_source>) -> Result<()> {
|
||||
let src_ptr = if let Some(ptr) = src { ptr as *const _ } else { ::std::ptr::null() };
|
||||
cppresult!(self.start_streaming(frame_size.0, frame_size.1, color_space, src_ptr))
|
||||
}
|
||||
|
||||
/// Stop streaming.
|
||||
pub fn stop_streaming(&mut self) -> Result<()> {
|
||||
cppresult!(self.stop_streaming())
|
||||
}
|
||||
|
||||
/// Render the next frame.
|
||||
pub fn render_frame(&mut self, data: &[u8]) -> Result<()> {
|
||||
cppresult!(self.render_frame(data.as_ptr(), data.len() as UINT))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Fragmented destination interface, used for partial updates.
|
||||
#[repr(C)]
|
||||
struct fragmented_video_destination_vtbl {
|
||||
// <-- iasset:
|
||||
/// Increments the reference count for an interface on an object.
|
||||
pub add_ref: extern "C" fn(this: *mut fragmented_video_destination) -> i32,
|
||||
|
||||
/// Decrements the reference count for an interface on an object.
|
||||
pub release: extern "C" fn(this: *mut fragmented_video_destination) -> i32,
|
||||
|
||||
/// Retrieves pointers to the supported interfaces on an object.
|
||||
pub get_interface: extern "C" fn(this: *mut fragmented_video_destination, name: *const u8, out: *mut *mut iasset) -> bool,
|
||||
|
||||
/// Retrieves a pointer to the passport declaration of an object.
|
||||
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
|
||||
// -->
|
||||
|
||||
// <-- video_destination
|
||||
/// Whether this instance of `video_renderer` is attached to a DOM element and is capable of playing.
|
||||
pub is_alive: extern "C" fn(this: *const fragmented_video_destination) -> bool,
|
||||
|
||||
/// Start streaming/rendering.
|
||||
pub start_streaming: extern "C" fn(this: *mut fragmented_video_destination, frame_width: i32, frame_height: i32, color_space: COLOR_SPACE, src: *const video_source) -> bool,
|
||||
|
||||
/// Stop streaming.
|
||||
pub stop_streaming: extern "C" fn(this: *mut fragmented_video_destination) -> bool,
|
||||
|
||||
/// Render the next frame.
|
||||
pub render_frame: extern "C" fn(this: *mut fragmented_video_destination, data: LPCBYTE, size: UINT) -> bool,
|
||||
// -->
|
||||
|
||||
// <-- fragmented_video_destination
|
||||
/// Render the specified part of the current frame.
|
||||
pub render_frame_part: extern "C" fn(this: *mut fragmented_video_destination, data: LPCBYTE, size: UINT, x: i32, y: i32, width: i32, height: i32) -> bool,
|
||||
// -->
|
||||
}
|
||||
|
||||
/// Fragmented destination interface, used for partial updates.
|
||||
#[repr(C)]
|
||||
pub struct fragmented_video_destination {
|
||||
vtbl: *const fragmented_video_destination_vtbl,
|
||||
}
|
||||
|
||||
impl fragmented_video_destination {
|
||||
|
||||
/// Whether this instance of `video_renderer` is attached to a DOM element and is capable of playing.
|
||||
pub fn is_alive(&self) -> bool {
|
||||
cppcall!(const self.is_alive())
|
||||
}
|
||||
|
||||
/// Start streaming/rendering.
|
||||
///
|
||||
/// * `frame_size` - the width and the height of the video frame.
|
||||
/// * `color_space` - the color space format of the video frame.
|
||||
/// * `src` - an optional custom [`video_source`](struct.video_source.html) interface implementation, provided by the application.
|
||||
pub fn start_streaming(&mut self, frame_size: (i32, i32), color_space: COLOR_SPACE, src: Option<&video_source>) -> Result<()> {
|
||||
let src_ptr = if let Some(ptr) = src { ptr as *const _ } else { ::std::ptr::null() };
|
||||
cppresult!(self.start_streaming(frame_size.0, frame_size.1, color_space, src_ptr))
|
||||
}
|
||||
|
||||
/// Stop streaming.
|
||||
pub fn stop_streaming(&mut self) -> Result<()> {
|
||||
cppresult!(self.stop_streaming())
|
||||
}
|
||||
|
||||
/// Render the next frame.
|
||||
pub fn render_frame(&mut self, data: &[u8]) -> Result<()> {
|
||||
cppresult!(self.render_frame(data.as_ptr(), data.len() as UINT))
|
||||
}
|
||||
|
||||
/// Render the specified part of the current frame.
|
||||
///
|
||||
/// * `update_point` - X and Y coordinates of the update portion.
|
||||
/// * `update_size` - width and height of the update portion.
|
||||
pub fn render_frame_part(&mut self, data: &[u8], update_point: (i32, i32), update_size: (i32, i32)) -> Result<()> {
|
||||
cppresult!(self.render_frame_part(data.as_ptr(), data.len() as UINT, update_point.0, update_point.1, update_size.0, update_size.1))
|
||||
}
|
||||
}
|
||||
|
||||
/// A managed `iasset` pointer.
|
||||
pub struct AssetPtr<T> {
|
||||
ptr: *mut T,
|
||||
}
|
||||
|
||||
/// It's okay to transfer video pointers between threads.
|
||||
unsafe impl<T> Send for AssetPtr<T> {}
|
||||
|
||||
use ::std::ops::{Deref, DerefMut};
|
||||
|
||||
impl Deref for AssetPtr<video_destination> {
|
||||
type Target = video_destination;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for AssetPtr<video_destination> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { &mut *self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AssetPtr<fragmented_video_destination> {
|
||||
type Target = fragmented_video_destination;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for AssetPtr<fragmented_video_destination> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { &mut *self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
/// Decrements the reference count of a managed pointer.
|
||||
impl<T> Drop for AssetPtr<T> {
|
||||
fn drop(&mut self) {
|
||||
self.get().release();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AssetPtr<T> {
|
||||
/// Attach to an existing `iasset` pointer without reference increment.
|
||||
fn attach(lp: *mut T) -> Self {
|
||||
assert!(!lp.is_null());
|
||||
Self {
|
||||
ptr: lp
|
||||
}
|
||||
}
|
||||
|
||||
/// Attach to an `iasset` pointer and increment its reference count.
|
||||
pub fn adopt(lp: *mut T) -> Self {
|
||||
let mut me = Self::attach(lp);
|
||||
me.get().add_ref();
|
||||
me
|
||||
}
|
||||
|
||||
/// Get as an `iasset` type.
|
||||
fn get(&mut self) -> &mut iasset {
|
||||
let ptr = self.ptr as *mut iasset;
|
||||
unsafe { &mut *ptr }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Attach to an `iasset` pointer.
|
||||
impl<T> From<*mut T> for AssetPtr<T> {
|
||||
/// Attach to a pointer and increment its reference count.
|
||||
fn from(lp: *mut T) -> Self {
|
||||
AssetPtr::adopt(lp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Attempt to construct `Self` via a conversion.
|
||||
impl<T: NamedInterface> AssetPtr<T> {
|
||||
|
||||
/// Retrieve a supported interface of the managed pointer.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use sciter::video::{AssetPtr, iasset, video_source};
|
||||
/// # let external_ptr: *mut iasset = ::std::ptr::null_mut();
|
||||
/// let mut site = AssetPtr::adopt(external_ptr);
|
||||
/// let source = AssetPtr::<video_source>::try_from(&mut site);
|
||||
/// assert!(source.is_ok());
|
||||
/// ```
|
||||
pub fn try_from<U>(other: &mut AssetPtr<U>) -> Result<Self> {
|
||||
let me = T::query_interface(other.get());
|
||||
me.map(|p| AssetPtr::adopt(p as *mut T)).ok_or(())
|
||||
}
|
||||
}
|
||||
444
libs/rust-sciter/src/window.rs
Normal file
444
libs/rust-sciter/src/window.rs
Normal file
@@ -0,0 +1,444 @@
|
||||
/*! High-level native window wrapper.
|
||||
|
||||
To create an instance of Sciter you will need either to create a new Sciter window
|
||||
or to attach (mix-in) the Sciter engine to an existing window.
|
||||
|
||||
The handle of the Sciter engine is defined as `HWINDOW` type which is:
|
||||
|
||||
* `HWND` handle on Microsoft Windows.
|
||||
* `NSView*` – a pointer to [`NSView`](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/) instance that is a contentView of Sciter window on OS X.
|
||||
* `GtkWidget*` – a pointer to [`GtkWidget`](https://developer.gnome.org/gtk3/stable/GtkWidget.html) instance
|
||||
that is a root widget of Sciter window on Linux/GTK.
|
||||
|
||||
## Creation of a new window:
|
||||
|
||||
```no_run
|
||||
extern crate sciter;
|
||||
|
||||
fn main() {
|
||||
let mut frame = sciter::Window::new();
|
||||
frame.load_file("minimal.htm");
|
||||
frame.run_app();
|
||||
}
|
||||
```
|
||||
|
||||
Also you can register a [host](../host/trait.HostHandler.html) and a [DOM](../dom/event/index.html) event handlers.
|
||||
|
||||
.
|
||||
*/
|
||||
use ::{_API};
|
||||
use capi::sctypes::*;
|
||||
|
||||
use platform::{BaseWindow, OsWindow};
|
||||
use host::{Host, HostHandler};
|
||||
use dom::event::{EventHandler};
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
/// `SCITER_CREATE_WINDOW_FLAGS` alias.
|
||||
pub type Flags = SCITER_CREATE_WINDOW_FLAGS;
|
||||
|
||||
pub use capi::scdef::{SCITER_CREATE_WINDOW_FLAGS};
|
||||
|
||||
|
||||
/// Per-window Sciter engine options.
|
||||
///
|
||||
/// Used by [`Window::set_options()`](struct.Window.html#method.set_options).
|
||||
///
|
||||
/// See also [global options](../enum.RuntimeOptions.html).
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Options {
|
||||
/// Enable smooth scrolling, enabled by default.
|
||||
SmoothScroll(bool),
|
||||
|
||||
/// Font rendering, value: `0` - system default, `1` - no smoothing, `2` - standard smoothing, `3` - ClearType.
|
||||
FontSmoothing(u8),
|
||||
|
||||
/// Windows Aero support, value: `false` - normal drawing, `true` - window has transparent background after calls
|
||||
/// [`DwmExtendFrameIntoClientArea()`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969512(v=vs.85).aspx)
|
||||
/// or [`DwmEnableBlurBehindWindow()`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969508(v=vs.85).aspx).
|
||||
TransparentWindow(bool),
|
||||
|
||||
/// Transparent windows support. When enabled, window uses per pixel alpha
|
||||
/// (e.g. [`WS_EX_LAYERED`](https://msdn.microsoft.com/en-us/library/ms997507.aspx?f=255&MSPPError=-2147217396) window).
|
||||
AlphaWindow(bool),
|
||||
|
||||
/// global or per-window; enables Sciter Inspector for this window, must be called before loading HTML.
|
||||
DebugMode(bool),
|
||||
|
||||
/// global or per-window; value: combination of [`SCRIPT_RUNTIME_FEATURES`](../enum.SCRIPT_RUNTIME_FEATURES.html) flags.
|
||||
ScriptFeatures(u8),
|
||||
|
||||
/// Window is main, will destroy all other dependent windows on close, since 4.3.0.12
|
||||
MainWindow(bool),
|
||||
}
|
||||
|
||||
|
||||
/// Sciter window.
|
||||
pub struct Window
|
||||
{
|
||||
base: OsWindow,
|
||||
host: Rc<Host>,
|
||||
}
|
||||
|
||||
// `Window::new()` is rather expensive operation to make it default.
|
||||
#[allow(clippy::new_without_default)]
|
||||
impl Window {
|
||||
|
||||
/// Create a new main window.
|
||||
// #[cfg(not(feature = "windowless"))]
|
||||
#[cfg_attr(feature = "windowless", deprecated = "Sciter.Lite doesn't have OS windows in windowless mode.")]
|
||||
pub fn new() -> Window {
|
||||
Builder::main_window().create()
|
||||
}
|
||||
|
||||
/// Create a new window with the specified position, flags and an optional parent window.
|
||||
#[cfg_attr(feature = "windowless", deprecated = "Sciter.Lite doesn't have OS windows in windowless mode.")]
|
||||
pub fn create(rect: RECT, flags: Flags, parent: Option<HWINDOW>) -> Window {
|
||||
if cfg!(feature = "windowless")
|
||||
{
|
||||
panic!("Sciter.Lite doesn't have OS windows in windowless mode!");
|
||||
}
|
||||
|
||||
let mut base = OsWindow::new();
|
||||
let hwnd = base.create(rect, flags as UINT, parent.unwrap_or(0 as HWINDOW));
|
||||
assert!(!hwnd.is_null());
|
||||
|
||||
let wnd = Window { base: base, host: Rc::new(Host::attach(hwnd))};
|
||||
return wnd;
|
||||
}
|
||||
|
||||
/// Attach Sciter to an existing native window.
|
||||
pub fn attach(hwnd: HWINDOW) -> Window {
|
||||
// suppress warnings about unused method
|
||||
let _ = &OsWindow::new;
|
||||
|
||||
assert!(!hwnd.is_null());
|
||||
Window { base: OsWindow::from(hwnd), host: Rc::new(Host::attach(hwnd)) }
|
||||
}
|
||||
|
||||
/// Obtain a reference to `Host` which allows you to control Sciter engine.
|
||||
pub fn get_host(&self) -> Rc<Host> {
|
||||
self.host.clone()
|
||||
}
|
||||
|
||||
/// Set [callback](../host/trait.HostHandler.html) for Sciter engine events.
|
||||
pub fn sciter_handler<Callback: HostHandler + Sized>(&mut self, handler: Callback) {
|
||||
self.host.setup_callback(handler);
|
||||
}
|
||||
|
||||
/// Attach [`dom::EventHandler`](../dom/event/trait.EventHandler.html) to the Sciter window.
|
||||
///
|
||||
/// You should install Window event handler only once - it will survive all document reloads.
|
||||
/// Also it can be registered on an empty window before the document is loaded.
|
||||
pub fn event_handler<Handler: EventHandler>(&mut self, handler: Handler) {
|
||||
self.host.attach_handler(handler);
|
||||
}
|
||||
|
||||
/// Register an archive produced by `packfolder` tool.
|
||||
///
|
||||
/// The resources can be accessed via the `this://app/` URL.
|
||||
///
|
||||
/// See documentation of the [`Archive`](../host/struct.Archive.html).
|
||||
///
|
||||
pub fn archive_handler(&mut self, resource: &[u8]) -> Result<(), ()> {
|
||||
self.host.register_archive(resource)
|
||||
}
|
||||
|
||||
/// Register a native event handler for the specified behavior name.
|
||||
///
|
||||
/// Behavior is a named event handler which is created for a particular DOM element.
|
||||
/// In Sciter’s sense, it is a function that is called for different UI events on the DOM element.
|
||||
/// Essentially it is an analog of the [WindowProc](https://en.wikipedia.org/wiki/WindowProc) in Windows.
|
||||
///
|
||||
/// In HTML, there is a `behavior` CSS property that defines the name of a native module
|
||||
/// that is responsible for the initialization and event handling on the element.
|
||||
/// For example, by defining `div { behavior:button; }` you are asking all `<div>` elements in your markup
|
||||
/// to behave as buttons: generate [`BUTTON_CLICK`](../dom/event/enum.BEHAVIOR_EVENTS.html#variant.BUTTON_CLICK)
|
||||
/// DOM events when the user clicks on that element, and be focusable.
|
||||
///
|
||||
/// When the engine discovers an element having `behavior: xyz;` defined in its style,
|
||||
/// it sends the [`SC_ATTACH_BEHAVIOR`](../host/trait.HostHandler.html#method.on_attach_behavior) host notification
|
||||
/// with the name `"xyz"` and an element handle to the application.
|
||||
/// You can consume the notification and respond to it yourself,
|
||||
/// or the default handler walks through the list of registered behavior factories
|
||||
/// and creates an instance of the corresponding [`dom::EventHandler`](../dom/event/trait.EventHandler.html).
|
||||
///
|
||||
/// ## Example:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// struct Button;
|
||||
///
|
||||
/// impl sciter::EventHandler for Button {}
|
||||
///
|
||||
/// let mut frame = sciter::Window::new();
|
||||
///
|
||||
/// // register a factory method that creates a new event handler
|
||||
/// // for each element that has "custom-button" behavior:
|
||||
/// frame.register_behavior("custom-button", || { Box::new(Button) });
|
||||
/// ```
|
||||
///
|
||||
/// And in HTML it can be used as:
|
||||
///
|
||||
/// ```html
|
||||
/// <button style="behavior: custom-button">Rusty button</button>
|
||||
/// ```
|
||||
pub fn register_behavior<Factory>(&mut self, name: &str, factory: Factory)
|
||||
where
|
||||
Factory: Fn() -> Box<dyn EventHandler> + 'static
|
||||
{
|
||||
self.host.register_behavior(name, factory);
|
||||
}
|
||||
|
||||
/// Load an HTML document from file.
|
||||
///
|
||||
/// The specified `uri` should be either an absolute file path
|
||||
/// or a full URL to the HTML to load.
|
||||
///
|
||||
/// Supported URL schemes are: `http://`, `file://`, `this://app/` (when used with [`archive_handler`](#archive_handler)).
|
||||
pub fn load_file(&mut self, uri: &str) -> bool {
|
||||
self.host.load_file(uri)
|
||||
}
|
||||
|
||||
/// Load an HTML document from memory.
|
||||
pub fn load_html(&mut self, html: &[u8], uri: Option<&str>) -> bool {
|
||||
self.host.load_html(html, uri)
|
||||
}
|
||||
|
||||
/// Get native window handle.
|
||||
pub fn get_hwnd(&self) -> HWINDOW {
|
||||
self.base.get_hwnd()
|
||||
}
|
||||
|
||||
/// Minimize or hide window.
|
||||
pub fn collapse(&self, hide: bool) {
|
||||
self.base.collapse(hide)
|
||||
}
|
||||
|
||||
/// Show or maximize window.
|
||||
pub fn expand(&self, maximize: bool) {
|
||||
self.base.expand(maximize)
|
||||
}
|
||||
|
||||
/// Close window.
|
||||
pub fn dismiss(&self) {
|
||||
self.base.dismiss()
|
||||
}
|
||||
|
||||
/// Set title of native window.
|
||||
pub fn set_title(&mut self, title: &str) {
|
||||
self.base.set_title(title)
|
||||
}
|
||||
|
||||
/// Get native window title.
|
||||
pub fn get_title(&self) -> String {
|
||||
self.base.get_title()
|
||||
}
|
||||
|
||||
/// Set various Sciter engine options, see the [`Options`](enum.Options.html).
|
||||
pub fn set_options(&self, options: Options) -> Result<(), ()> {
|
||||
use capi::scdef::SCITER_RT_OPTIONS::*;
|
||||
use self::Options::*;
|
||||
let (option, value) = match options {
|
||||
SmoothScroll(enable) => (SCITER_SMOOTH_SCROLL, enable as usize),
|
||||
FontSmoothing(technology) => (SCITER_FONT_SMOOTHING, technology as usize),
|
||||
TransparentWindow(enable) => (SCITER_TRANSPARENT_WINDOW, enable as usize),
|
||||
AlphaWindow(enable) => (SCITER_ALPHA_WINDOW, enable as usize),
|
||||
MainWindow(enable) => (SCITER_SET_MAIN_WINDOW, enable as usize),
|
||||
DebugMode(enable) => (SCITER_SET_DEBUG_MODE, enable as usize),
|
||||
ScriptFeatures(mask) => (SCITER_SET_SCRIPT_RUNTIME_FEATURES, mask as usize),
|
||||
};
|
||||
let ok = (_API.SciterSetOption)(self.get_hwnd(), option, value);
|
||||
if ok != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Show window and run the main app message loop until window been closed.
|
||||
pub fn run_app(self) {
|
||||
self.base.expand(false);
|
||||
self.base.run_app();
|
||||
}
|
||||
|
||||
/// Run the main app message loop with already configured window.
|
||||
pub fn run_loop(&self) {
|
||||
self.base.run_app();
|
||||
}
|
||||
|
||||
/// Post app quit message.
|
||||
pub fn quit_app(&self) {
|
||||
self.base.quit_app()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Generic rectangle struct.
|
||||
/// NOTE that this is different from the [`RECT`](../types/struct.RECT.html) type as it specifies width and height.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Rectangle {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub width: i32,
|
||||
pub height: i32
|
||||
}
|
||||
|
||||
|
||||
/// Builder pattern for window creation.
|
||||
///
|
||||
/// For example,
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// let mut frame = sciter::window::Builder::main_window()
|
||||
/// .with_size((800,600))
|
||||
/// .resizeable()
|
||||
/// .glassy()
|
||||
/// .create();
|
||||
/// ```
|
||||
#[derive(Default)]
|
||||
pub struct Builder {
|
||||
flags: Flags,
|
||||
rect: RECT,
|
||||
parent: Option<HWINDOW>,
|
||||
}
|
||||
|
||||
// Note: https://rust-lang-nursery.github.io/api-guidelines/type-safety.html#non-consuming-builders-preferred
|
||||
impl Builder {
|
||||
|
||||
/// Main application window (resizeable with min/max buttons and title).
|
||||
/// Will terminate the app on close.
|
||||
pub fn main_window() -> Self {
|
||||
Builder::main()
|
||||
.resizeable()
|
||||
.closeable()
|
||||
.with_title()
|
||||
}
|
||||
|
||||
/// Popup window (with min/max buttons and title).
|
||||
pub fn popup_window() -> Self {
|
||||
Builder::popup()
|
||||
.closeable()
|
||||
.with_title()
|
||||
}
|
||||
|
||||
/// Child window style. if this flag is set all other flags are ignored.
|
||||
pub fn child_window() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_CHILD)
|
||||
}
|
||||
|
||||
/// If you want to start from scratch.
|
||||
pub fn none() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_CHILD) // 0
|
||||
}
|
||||
|
||||
/// Start with some flags.
|
||||
pub fn with_flags(flags: Flags) -> Self {
|
||||
let mut me = Builder::default();
|
||||
me.flags = flags;
|
||||
me
|
||||
}
|
||||
|
||||
/// Main window style (appears in taskbar).
|
||||
/// Will terminate the app on close.
|
||||
pub fn main() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_MAIN)
|
||||
}
|
||||
|
||||
/// Popup style, window is created as topmost.
|
||||
pub fn popup() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_POPUP)
|
||||
}
|
||||
|
||||
/// Tool window style (with thin titlebar).
|
||||
pub fn tool() -> Self {
|
||||
Builder::with_flags(SCITER_CREATE_WINDOW_FLAGS::SW_TOOL)
|
||||
}
|
||||
|
||||
/// Specify the parent window (e.g. for child creation).
|
||||
pub fn with_parent(mut self, parent: HWINDOW) -> Self {
|
||||
self.parent = Some(parent);
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the precise window size in `(width, height)` form.
|
||||
pub fn with_size(mut self, size: (i32, i32)) -> Self {
|
||||
self.rect.right = self.rect.left + size.0;
|
||||
self.rect.bottom = self.rect.top + size.1;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the precise window position in `(X, Y)` form.
|
||||
pub fn with_pos(mut self, position: (i32, i32)) -> Self {
|
||||
let size = self.rect.size();
|
||||
self.rect.left = position.0;
|
||||
self.rect.top = position.1;
|
||||
self.rect.right = position.0 + size.cx;
|
||||
self.rect.bottom = position.1 + size.cy;
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the exact window rectangle in `(X, Y, W, H)` form.
|
||||
pub fn with_rect(mut self, rect: Rectangle) -> Self {
|
||||
self.rect = RECT {
|
||||
left: rect.x,
|
||||
top: rect.y,
|
||||
right: rect.x + rect.width,
|
||||
bottom: rect.y + rect.height,
|
||||
};
|
||||
self
|
||||
}
|
||||
|
||||
/// Top level window, has titlebar.
|
||||
pub fn with_title(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_TITLEBAR)
|
||||
}
|
||||
|
||||
/// Can be resized.
|
||||
pub fn resizeable(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_RESIZEABLE)
|
||||
}
|
||||
|
||||
/// Can not be resized.
|
||||
pub fn fixed(self) -> Self {
|
||||
self.and(SCITER_CREATE_WINDOW_FLAGS::SW_RESIZEABLE)
|
||||
}
|
||||
|
||||
/// Has minimize / maximize buttons.
|
||||
pub fn closeable(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_CONTROLS)
|
||||
}
|
||||
|
||||
/// Glassy window ("Acrylic" on Windows and "Vibrant" on macOS).
|
||||
pub fn glassy(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_GLASSY)
|
||||
}
|
||||
|
||||
/// Transparent window.
|
||||
pub fn alpha(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_ALPHA)
|
||||
}
|
||||
|
||||
/// Can be debugged with Inspector.
|
||||
pub fn debug(self) -> Self {
|
||||
self.or(SCITER_CREATE_WINDOW_FLAGS::SW_ENABLE_DEBUG)
|
||||
}
|
||||
|
||||
fn or(mut self, flag: Flags) -> Self {
|
||||
self.flags = self.flags | flag;
|
||||
self
|
||||
}
|
||||
|
||||
fn and(mut self, flag: Flags) -> Self {
|
||||
let masked = self.flags as u32 & !(flag as u32);
|
||||
self.flags = unsafe { ::std::mem::transmute(masked) };
|
||||
self
|
||||
}
|
||||
|
||||
/// Consume the builder and call [`Window::create()`](struct.Window.html#method.create) with built parameters.
|
||||
#[cfg_attr(feature = "windowless", deprecated = "Sciter.Lite doesn't have OS windows in windowless mode.")]
|
||||
pub fn create(self) -> Window {
|
||||
Window::create(self.rect, self.flags, self.parent)
|
||||
}
|
||||
}
|
||||
330
libs/rust-sciter/src/windowless.rs
Normal file
330
libs/rust-sciter/src/windowless.rs
Normal file
@@ -0,0 +1,330 @@
|
||||
/*! Windowless Sciter.
|
||||
|
||||
Windowless here means that Sciter does not use any `HWND`, `NSView*` or whatever OS uses for window designation.
|
||||
You just need to provide something of size `void*` that will be associated with the instance of the engine.
|
||||
|
||||
Check out [this article](https://sciter.com/sciter-lite-is-published/) on sciter.com that explains
|
||||
the difference between the desktop and the windowless Sciter engine versions.
|
||||
|
||||
*/
|
||||
|
||||
use ::{_API};
|
||||
use capi::scdef::{GFX_LAYER};
|
||||
use capi::scdom::HELEMENT;
|
||||
use capi::sctypes::{HWINDOW, POINT, UINT, BOOL, RECT, LPCBYTE, LPVOID, INT};
|
||||
use capi::scmsg::*;
|
||||
|
||||
pub use capi::scmsg::key_codes;
|
||||
pub use capi::scbehavior::{MOUSE_BUTTONS, MOUSE_EVENTS, KEYBOARD_STATES, KEY_EVENTS};
|
||||
|
||||
|
||||
/// Application-provided events to notify Sciter.
|
||||
#[derive(Debug)]
|
||||
pub enum Message {
|
||||
/// Creates an instance of Sciter assotiated with the given handle.
|
||||
Create {
|
||||
/// Graphics backend for rendering.
|
||||
backend: GFX_LAYER,
|
||||
/// Background transparency option.
|
||||
transparent: bool,
|
||||
},
|
||||
|
||||
/// Destroys the engine instance.
|
||||
Destroy,
|
||||
|
||||
/// Window size changes.
|
||||
Size {
|
||||
/// Width of the rendering surface.
|
||||
width: u32,
|
||||
/// Height of the rendering surface.
|
||||
height: u32,
|
||||
},
|
||||
|
||||
/// Screen resolution changes.
|
||||
Resolution {
|
||||
/// Pixels per inch.
|
||||
ppi: u32,
|
||||
},
|
||||
|
||||
/// Window focus event.
|
||||
Focus {
|
||||
/// Whether the window has got or lost the input focus.
|
||||
enter: bool,
|
||||
},
|
||||
|
||||
/// Time changes in order to process animations, timers and other timed things.
|
||||
Heartbit {
|
||||
/// Absolute steady clock value, e.g. `GetTickCount()` or `glfwGetTime()`.
|
||||
milliseconds: u32,
|
||||
},
|
||||
|
||||
/// Redraw the whole document.
|
||||
Redraw,
|
||||
|
||||
/// Redraw the specific layer.
|
||||
Paint(PaintLayer),
|
||||
|
||||
/// Render to a bitmap.
|
||||
RenderTo(RenderEvent),
|
||||
|
||||
#[cfg(any(windows, doc))]
|
||||
/// Render to a DXGI surface (Windows only, since 4.4.3.27).
|
||||
RenderToDxgiSurface(DxgiRenderEvent),
|
||||
|
||||
/// Mouse input.
|
||||
Mouse(MouseEvent),
|
||||
|
||||
/// Keyboard input.
|
||||
Keyboard(KeyboardEvent),
|
||||
}
|
||||
|
||||
/// Events describing the mouse input.
|
||||
#[derive(Debug)]
|
||||
pub struct MouseEvent {
|
||||
/// A specific mouse event, like "mouse down" or "mouse move".
|
||||
pub event: MOUSE_EVENTS,
|
||||
/// Which mouse button is pressed.
|
||||
pub button: MOUSE_BUTTONS,
|
||||
/// Which keyboard modifier (e.g. Ctrl or Alt) is pressed.
|
||||
pub modifiers: KEYBOARD_STATES,
|
||||
/// Mouse cursor position.
|
||||
pub pos: POINT,
|
||||
}
|
||||
|
||||
/// Events describing the keyboard input.
|
||||
#[derive(Debug)]
|
||||
pub struct KeyboardEvent {
|
||||
/// A specific key event, like "key down" or "key up".
|
||||
pub event: KEY_EVENTS,
|
||||
/// A key code:
|
||||
///
|
||||
/// * a keyboard [scan-code](key_codes/index.html)
|
||||
/// for [`KEY_DOWN`](enum.KEY_EVENTS.html#variant.KEY_DOWN)
|
||||
/// and [`KEY_UP`](enum.KEY_EVENTS.html#variant.KEY_UP) events;
|
||||
/// * a Unicode code point for [`KEY_CHAR`](enum.KEY_EVENTS.html#variant.KEY_CHAR).
|
||||
pub code: UINT,
|
||||
/// Which keyboard modifier (e.g. Ctrl or Alt) is pressed.
|
||||
pub modifiers: KEYBOARD_STATES,
|
||||
}
|
||||
|
||||
/// A specific UI layer to redraw.
|
||||
#[derive(Debug)]
|
||||
pub struct PaintLayer {
|
||||
/// A DOM element (layer) to render.
|
||||
pub element: HELEMENT,
|
||||
|
||||
/// Whether the `element` is the topmost layer or a background one.
|
||||
pub is_foreground: bool,
|
||||
}
|
||||
|
||||
/// Events for rendering UI to a bitmap.
|
||||
pub struct RenderEvent
|
||||
{
|
||||
/// Which layer to render (or the whole document if `None`).
|
||||
pub layer: Option<PaintLayer>,
|
||||
|
||||
/// The callback that receives a rendered bitmap.
|
||||
///
|
||||
/// The first argument contains a rectangle with the coordinates (position and size) of the rendered bitmap.
|
||||
///
|
||||
/// The second ardument is the rendered bitmap in the `BGRA` form. The size of the bitmap equals to `width * height * 4`.
|
||||
pub callback: Box<dyn Fn(&RECT, &[u8])>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for RenderEvent {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt
|
||||
.debug_struct("RenderEvent")
|
||||
.field("layer", &self.layer)
|
||||
.field("callback", &"Box<dyn Fn>")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(windows, doc))]
|
||||
#[derive(Debug)]
|
||||
/// Events for rendering UI to a DXGI surface.
|
||||
///
|
||||
/// Since 4.4.3.27.
|
||||
pub struct DxgiRenderEvent {
|
||||
/// Which layer to render (or the whole document if `None`).
|
||||
pub layer: Option<PaintLayer>,
|
||||
|
||||
/// [`IDXGISurface`](https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nn-dxgi-idxgisurface) pointer.
|
||||
pub surface: LPVOID,
|
||||
}
|
||||
|
||||
|
||||
/// Notify Sciter about UI-specific events.
|
||||
///
|
||||
/// `wnd` here is not a window handle but rather a window instance (pointer).
|
||||
pub fn handle_message(wnd: HWINDOW, event: Message) -> bool
|
||||
{
|
||||
let ok = match event {
|
||||
Message::Create { backend, transparent } => {
|
||||
let msg = SCITER_X_MSG_CREATE {
|
||||
header: SCITER_X_MSG_CODE::SXM_CREATE.into(),
|
||||
backend,
|
||||
transparent: transparent as BOOL,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Destroy => {
|
||||
let msg = SCITER_X_MSG_DESTROY {
|
||||
header: SCITER_X_MSG_CODE::SXM_DESTROY.into(),
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Size { width, height} => {
|
||||
let msg = SCITER_X_MSG_SIZE {
|
||||
header: SCITER_X_MSG_CODE::SXM_SIZE.into(),
|
||||
width,
|
||||
height,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Resolution { ppi } => {
|
||||
let msg = SCITER_X_MSG_RESOLUTION {
|
||||
header: SCITER_X_MSG_CODE::SXM_RESOLUTION.into(),
|
||||
ppi,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Focus { enter } => {
|
||||
let msg = SCITER_X_MSG_FOCUS {
|
||||
header: SCITER_X_MSG_CODE::SXM_FOCUS.into(),
|
||||
enter: enter as BOOL,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Heartbit { milliseconds } => {
|
||||
let msg = SCITER_X_MSG_HEARTBIT {
|
||||
header: SCITER_X_MSG_CODE::SXM_HEARTBIT.into(),
|
||||
time: milliseconds,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Mouse(params) => {
|
||||
let msg = SCITER_X_MSG_MOUSE {
|
||||
header: SCITER_X_MSG_CODE::SXM_MOUSE.into(),
|
||||
|
||||
event: params.event,
|
||||
button: params.button,
|
||||
modifiers: params.modifiers as u32,
|
||||
pos: params.pos,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Keyboard(params) => {
|
||||
let msg = SCITER_X_MSG_KEY {
|
||||
header: SCITER_X_MSG_CODE::SXM_KEY.into(),
|
||||
|
||||
event: params.event,
|
||||
code: params.code,
|
||||
modifiers: params.modifiers as u32,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Redraw => {
|
||||
use std::ptr;
|
||||
let msg = SCITER_X_MSG_PAINT {
|
||||
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
|
||||
element: ptr::null_mut(),
|
||||
isFore: true as BOOL,
|
||||
targetType: SCITER_PAINT_TARGET_TYPE::SPT_DEFAULT,
|
||||
context: ptr::null_mut(),
|
||||
callback: None,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::Paint(paint) => {
|
||||
let msg = SCITER_X_MSG_PAINT {
|
||||
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
|
||||
element: paint.element,
|
||||
isFore: paint.is_foreground as BOOL,
|
||||
targetType: SCITER_PAINT_TARGET_TYPE::SPT_DEFAULT,
|
||||
context: std::ptr::null_mut(),
|
||||
callback: None,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
#[cfg(windows)]
|
||||
Message::RenderToDxgiSurface(paint) => {
|
||||
let layer = paint.layer.unwrap_or(PaintLayer {
|
||||
element: std::ptr::null_mut(),
|
||||
is_foreground: false,
|
||||
});
|
||||
|
||||
let msg = SCITER_X_MSG_PAINT {
|
||||
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
|
||||
element: layer.element,
|
||||
isFore: layer.is_foreground as BOOL,
|
||||
targetType: SCITER_PAINT_TARGET_TYPE::SPT_SURFACE,
|
||||
context: paint.surface,
|
||||
callback: None,
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
Message::RenderTo(paint) => {
|
||||
|
||||
struct Callback {
|
||||
callback: Box<dyn Fn(&RECT, &[u8])>,
|
||||
}
|
||||
|
||||
extern "system" fn inner(rgba: LPCBYTE, x: INT, y: INT, width: UINT, height: UINT, param: LPVOID)
|
||||
{
|
||||
assert!(!param.is_null());
|
||||
assert!(!rgba.is_null());
|
||||
if param.is_null() || rgba.is_null() { return; }
|
||||
|
||||
let bitmap_area = RECT {
|
||||
left: x,
|
||||
top: y,
|
||||
right: x + width as INT,
|
||||
bottom: y + height as INT,
|
||||
};
|
||||
|
||||
let bitmap_size = width * height * 4;
|
||||
let bitmap_data = unsafe { std::slice::from_raw_parts(rgba, bitmap_size as usize) };
|
||||
|
||||
let param = param as *const Callback;
|
||||
let wrapper = unsafe { &*param };
|
||||
(wrapper.callback)(&bitmap_area, bitmap_data);
|
||||
}
|
||||
|
||||
let wrapper = Callback {
|
||||
callback: paint.callback,
|
||||
};
|
||||
let param = &wrapper as *const _ as LPVOID;
|
||||
|
||||
let layer = paint.layer.unwrap_or(PaintLayer {
|
||||
element: std::ptr::null_mut(),
|
||||
is_foreground: false,
|
||||
});
|
||||
|
||||
let msg = SCITER_X_MSG_PAINT {
|
||||
header: SCITER_X_MSG_CODE::SXM_PAINT.into(),
|
||||
element: layer.element,
|
||||
isFore: layer.is_foreground as BOOL,
|
||||
targetType: SCITER_PAINT_TARGET_TYPE::SPT_RECEIVER,
|
||||
context: param,
|
||||
callback: Some(inner),
|
||||
};
|
||||
(_API.SciterProcX)(wnd, &msg.header as *const _)
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
ok != 0
|
||||
}
|
||||
Reference in New Issue
Block a user