quickwin 2026.5.2-3.145209
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/examples/pdf_preview.js +440 -0
- package/examples/pdf_preview.ts +470 -0
- package/examples/preact_demo.js +35 -0
- package/examples/preact_demo.tsx +49 -0
- package/examples/tray_demo.js +75 -0
- package/examples/tray_demo.tsx +79 -0
- package/lib/fetch.js +746 -0
- package/lib/fetch.ts +811 -0
- package/lib/polyfill.js +500 -0
- package/lib/polyfill.ts +454 -0
- package/lib/preact/hooks.js +287 -0
- package/lib/preact/hooks.ts +330 -0
- package/lib/preact/jsx-runtime.js +1 -0
- package/lib/preact/jsx-runtime.ts +2 -0
- package/lib/preact/jsx.d.ts +36 -0
- package/lib/preact/layout.js +153 -0
- package/lib/preact/layout.ts +183 -0
- package/lib/preact/preact.js +54 -0
- package/lib/preact/preact.ts +133 -0
- package/lib/preact/props.js +99 -0
- package/lib/preact/props.ts +119 -0
- package/lib/preact/render.js +320 -0
- package/lib/preact/render.ts +353 -0
- package/lib/websocket.js +540 -0
- package/lib/websocket.ts +574 -0
- package/package.json +32 -0
- package/quickwin.d.ts +657 -0
- package/test/add.wasm +0 -0
- package/test/complex.wasm +0 -0
- package/test/complex_imports.wasm +0 -0
- package/test/global_imports.wasm +0 -0
- package/test/import_func.wasm +0 -0
- package/test/imports.wasm +0 -0
- package/test/run.js +86 -0
- package/test/run.ts +90 -0
- package/test/sjlj.wasm +0 -0
- package/test/test_basic.js +7 -0
- package/test/test_basic.ts +9 -0
- package/test/test_brotli.js +48 -0
- package/test/test_brotli.ts +52 -0
- package/test/test_fetch_cache.js +131 -0
- package/test/test_fetch_cache.ts +141 -0
- package/test/test_ffi.js +157 -0
- package/test/test_ffi.ts +174 -0
- package/test/test_frame_encoding.js +128 -0
- package/test/test_frame_encoding.ts +132 -0
- package/test/test_helper.js +84 -0
- package/test/test_helper.ts +80 -0
- package/test/test_http_import.js +78 -0
- package/test/test_http_import.ts +74 -0
- package/test/test_mupdf_render.js +69 -0
- package/test/test_mupdf_render.ts +74 -0
- package/test/test_mupdf_twice.js +77 -0
- package/test/test_mupdf_twice.ts +81 -0
- package/test/test_mupdf_wasm.js +33 -0
- package/test/test_mupdf_wasm.ts +30 -0
- package/test/test_net_event.js +63 -0
- package/test/test_net_event.ts +59 -0
- package/test/test_net_fetch.js +153 -0
- package/test/test_net_fetch.ts +131 -0
- package/test/test_net_websocket.js +158 -0
- package/test/test_net_websocket.ts +144 -0
- package/test/test_polyfill.js +58 -0
- package/test/test_polyfill.ts +60 -0
- package/test/test_url.js +173 -0
- package/test/test_url.ts +183 -0
- package/test/test_wasm_basic.js +82 -0
- package/test/test_wasm_basic.ts +70 -0
- package/test/test_wasm_import_global.js +41 -0
- package/test/test_wasm_import_global.ts +39 -0
- package/test/test_wasm_sjlj.js +153 -0
- package/test/test_wasm_sjlj.ts +134 -0
- package/test/test_wasm_types.js +96 -0
- package/test/test_wasm_types.ts +108 -0
- package/test/types.wasm +0 -0
- package/tsconfig.json +18 -0
- package/vendor/mupdf-wasm/mupdf-wasm.d.ts +571 -0
- package/vendor/mupdf-wasm/mupdf-wasm.js +2749 -0
- package/vendor/mupdf-wasm/mupdf-wasm.wasm +0 -0
- package/vendor/mupdf-wasm/mupdf.d.ts +939 -0
- package/vendor/mupdf-wasm/mupdf.js +3317 -0
- package/win-mingw64.exe +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import * as gui from 'gui'
|
|
2
|
+
import * as ffi from 'ffi'
|
|
3
|
+
import * as win from 'win'
|
|
4
|
+
|
|
5
|
+
const FFI_PTR = ffi.FFI_TYPE_POINTER
|
|
6
|
+
const FFI_S32 = ffi.FFI_TYPE_SINT32
|
|
7
|
+
const FFI_U32 = ffi.FFI_TYPE_UINT32
|
|
8
|
+
const FFI_U64 = ffi.FFI_TYPE_UINT64
|
|
9
|
+
|
|
10
|
+
const _user32 = win.LoadLibrary('user32.dll')
|
|
11
|
+
|
|
12
|
+
const MoveWindow_proc = _user32 ? win.GetProcAddress(_user32, 'MoveWindow') : 0
|
|
13
|
+
const EnableWindow_proc = _user32 ? win.GetProcAddress(_user32, 'EnableWindow') : 0
|
|
14
|
+
const ShowWindow_proc = _user32 ? win.GetProcAddress(_user32, 'ShowWindow') : 0
|
|
15
|
+
const SendMessageW_proc = _user32 ? win.GetProcAddress(_user32, 'SendMessageW') : 0
|
|
16
|
+
const DestroyWindow_proc = _user32 ? win.GetProcAddress(_user32, 'DestroyWindow') : 0
|
|
17
|
+
|
|
18
|
+
const SW_HIDE = gui.ShowWindowCmd.HIDE
|
|
19
|
+
const SW_SHOW = gui.ShowWindowCmd.SHOW
|
|
20
|
+
|
|
21
|
+
const BM_GETCHECK = gui.ButtonMsg.GETCHECK
|
|
22
|
+
const BM_SETCHECK = gui.ButtonMsg.SETCHECK
|
|
23
|
+
const BST_CHECKED = gui.ButtonCheckState.CHECKED
|
|
24
|
+
const BST_UNCHECKED = gui.ButtonCheckState.UNCHECKED
|
|
25
|
+
const EM_SETCUEBANNER = gui.EditMsg.SETCUEBANNER
|
|
26
|
+
const EM_SETPASSWORDCHAR = gui.EditMsg.SETPASSWORDCHAR
|
|
27
|
+
const CB_ADDSTRING = gui.ComboBoxMsg.ADDSTRING
|
|
28
|
+
const LB_ADDSTRING = gui.LbMsg.ADDSTRING
|
|
29
|
+
const PBM_SETRANGE32 = gui.ProgressMsg.SETRANGE32
|
|
30
|
+
const PBM_SETPOS = gui.ProgressMsg.SETPOS
|
|
31
|
+
|
|
32
|
+
export interface WProps {
|
|
33
|
+
type?: string
|
|
34
|
+
text?: string
|
|
35
|
+
value?: string
|
|
36
|
+
disabled?: boolean
|
|
37
|
+
visible?: boolean
|
|
38
|
+
style?: Record<string, any>
|
|
39
|
+
onEvent?: (e: Record<string, any>) => void
|
|
40
|
+
placeholder?: string
|
|
41
|
+
password?: boolean
|
|
42
|
+
checked?: boolean
|
|
43
|
+
items?: string[]
|
|
44
|
+
max?: number
|
|
45
|
+
children?: any
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function applyProps(hwnd: number, props: WProps, vnode?: Record<string, any>): void {
|
|
49
|
+
if (props.text !== undefined) {
|
|
50
|
+
gui.SetWindowText(hwnd as gui.HWND, props.text)
|
|
51
|
+
}
|
|
52
|
+
if (props.value !== undefined) {
|
|
53
|
+
gui.SetWindowText(hwnd as gui.HWND, props.value)
|
|
54
|
+
}
|
|
55
|
+
if (props.disabled !== undefined && EnableWindow_proc) {
|
|
56
|
+
ffi.ffiCall(EnableWindow_proc, [FFI_U64, FFI_U32] as const, [hwnd, props.disabled ? 0 : 1], FFI_U32)
|
|
57
|
+
}
|
|
58
|
+
if (props.visible !== undefined && ShowWindow_proc) {
|
|
59
|
+
ffi.ffiCall(ShowWindow_proc, [FFI_U64, FFI_S32] as const, [hwnd, props.visible ? SW_SHOW : SW_HIDE], FFI_U32)
|
|
60
|
+
}
|
|
61
|
+
if (props.onEvent !== undefined && vnode) {
|
|
62
|
+
const h = hwnd as unknown as gui.HWND
|
|
63
|
+
const oldProc = vnode._oldProc || gui.GetWindowLongPtr(h, gui.Gwlp.WNDPROC)
|
|
64
|
+
vnode._oldProc = oldProc
|
|
65
|
+
gui.SetWindowProc(h, (hw, msg, wParam, lParam) => {
|
|
66
|
+
const cb = vnode!.props?.onEvent
|
|
67
|
+
if (cb) cb({ hwnd: hw as unknown as number, msg, wParam, lParam })
|
|
68
|
+
return gui.CallWindowProc(oldProc as unknown as gui.WNDPROC, hw, msg, wParam, lParam)
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
if (props.placeholder !== undefined && SendMessageW_proc) {
|
|
72
|
+
ffi.ffiCall(SendMessageW_proc, [FFI_U64, FFI_S32, FFI_U32, FFI_PTR] as const, [hwnd, EM_SETCUEBANNER, 0, strToWide(props.placeholder)], FFI_U64)
|
|
73
|
+
}
|
|
74
|
+
if (props.password !== undefined && SendMessageW_proc) {
|
|
75
|
+
ffi.ffiCall(SendMessageW_proc, [FFI_U64, FFI_U64, FFI_U64, FFI_U64] as const, [hwnd, EM_SETPASSWORDCHAR, props.password ? 42 : 0, 0], FFI_U64)
|
|
76
|
+
}
|
|
77
|
+
if (props.checked !== undefined && SendMessageW_proc) {
|
|
78
|
+
ffi.ffiCall(SendMessageW_proc, [FFI_U64, FFI_U64, FFI_U64, FFI_U64] as const, [hwnd, BM_SETCHECK, props.checked ? BST_CHECKED : BST_UNCHECKED, 0], FFI_U64)
|
|
79
|
+
}
|
|
80
|
+
if (props.items && SendMessageW_proc) {
|
|
81
|
+
const msg = props.type === 'combobox' ? CB_ADDSTRING : LB_ADDSTRING
|
|
82
|
+
for (const item of props.items) {
|
|
83
|
+
ffi.ffiCall(SendMessageW_proc, [FFI_U64, FFI_S32, FFI_U32, FFI_PTR] as const, [hwnd, msg, 0, strToWide(item)], FFI_U64)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (props.max !== undefined && SendMessageW_proc) {
|
|
87
|
+
ffi.ffiCall(SendMessageW_proc, [FFI_U64, FFI_U64, FFI_U64, FFI_U64] as const, [hwnd, PBM_SETRANGE32, 0, props.max], FFI_U64)
|
|
88
|
+
}
|
|
89
|
+
if (props.value !== undefined && props.type === 'progressbar' && SendMessageW_proc) {
|
|
90
|
+
ffi.ffiCall(SendMessageW_proc, [FFI_U64, FFI_U64, FFI_U64, FFI_U64] as const, [hwnd, PBM_SETPOS, Number(props.value), 0], FFI_U64)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const wideCache = new Map<string, ArrayBuffer>()
|
|
95
|
+
const MAX_WIDE_CACHE = 50
|
|
96
|
+
|
|
97
|
+
function strToWide(str: string): ArrayBuffer {
|
|
98
|
+
const cached = wideCache.get(str)
|
|
99
|
+
if (cached) return cached
|
|
100
|
+
const buf = new ArrayBuffer((str.length + 1) * 2)
|
|
101
|
+
const dv = new DataView(buf)
|
|
102
|
+
for (let i = 0; i < str.length; i++) dv.setUint16(i * 2, str.charCodeAt(i), true)
|
|
103
|
+
if (wideCache.size >= MAX_WIDE_CACHE) {
|
|
104
|
+
const key = wideCache.keys().next().value
|
|
105
|
+
if (key !== undefined) wideCache.delete(key)
|
|
106
|
+
}
|
|
107
|
+
wideCache.set(str, buf)
|
|
108
|
+
return buf
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function moveWindow(hwnd: number, x: number, y: number, w: number, h: number): void {
|
|
112
|
+
if (!MoveWindow_proc) return
|
|
113
|
+
ffi.ffiCall(MoveWindow_proc, [FFI_U64, FFI_S32, FFI_S32, FFI_S32, FFI_S32, FFI_U32] as const, [hwnd, x, y, w, h, 1], FFI_U32)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function destroyWindow(hwnd: number): boolean {
|
|
117
|
+
if (!DestroyWindow_proc) return false
|
|
118
|
+
return !!ffi.ffiCall(DestroyWindow_proc, [FFI_U64] as const, [hwnd], FFI_U32)
|
|
119
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import '../polyfill.js';
|
|
2
|
+
import * as gui from 'gui';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import { applyProps, destroyWindow } from './props.js';
|
|
5
|
+
import { layout as doLayout } from './layout.js';
|
|
6
|
+
import { options } from './preact.js';
|
|
7
|
+
const scaleFactor = gui.GetScaleFactor();
|
|
8
|
+
const dpiFont = gui.CreateSystemDpiFont();
|
|
9
|
+
const HWND_PROP = '__qw_hwnd';
|
|
10
|
+
const STYLE_PROP = '__qw_style';
|
|
11
|
+
const CHILDREN_HWNDS_PROP = '__qw_children';
|
|
12
|
+
const RENDERED_VNODE_PROP = '__qw_rendered';
|
|
13
|
+
let rootHwnd = null;
|
|
14
|
+
let rootVNode = null;
|
|
15
|
+
const WIN32_CLASS = {
|
|
16
|
+
button: 'BUTTON', edit: 'EDIT', static: 'STATIC',
|
|
17
|
+
checkbox: 'BUTTON', groupbox: 'BUTTON', combobox: 'COMBOBOX',
|
|
18
|
+
listbox: 'LISTBOX', progressbar: 'msctls_progress32',
|
|
19
|
+
};
|
|
20
|
+
const WIN32_STYLE = {
|
|
21
|
+
button: 0 /* gui.ButtonStyle.PUSHBUTTON */,
|
|
22
|
+
edit: 8388608 /* gui.WindowStyle.BORDER */ | 128 /* gui.EditStyle.AUTOHSCROLL */,
|
|
23
|
+
static: 0 /* gui.StaticStyle.LEFT */,
|
|
24
|
+
checkbox: 3 /* gui.ButtonStyle.AUTOCHECKBOX */,
|
|
25
|
+
groupbox: 7 /* gui.ButtonStyle.GROUPBOX */,
|
|
26
|
+
combobox: 3 /* gui.ComboBoxStyle.DROPDOWNLIST */,
|
|
27
|
+
listbox: 1 /* gui.ListBoxStyle.NOTIFY */ | 2097152 /* gui.WindowStyle.VSCROLL */,
|
|
28
|
+
progressbar: 0,
|
|
29
|
+
};
|
|
30
|
+
function createControl(type, parentHwnd, vnode) {
|
|
31
|
+
const base = 1073741824 /* gui.WindowStyle.CHILD */ | 268435456 /* gui.WindowStyle.VISIBLE */;
|
|
32
|
+
const winClass = WIN32_CLASS[type] || 'STATIC';
|
|
33
|
+
const style = base | (WIN32_STYLE[type] ?? 0 /* gui.StaticStyle.LEFT */);
|
|
34
|
+
const text = (vnode.props?.text || vnode.props?.value || '');
|
|
35
|
+
const hwnd = gui.CreateWindow(winClass, text, style, 0, 0, 0, 0, parentHwnd, null);
|
|
36
|
+
if (!hwnd)
|
|
37
|
+
return 0;
|
|
38
|
+
gui.SendMessage(hwnd, 48 /* gui.WmMsg.SETFONT */, dpiFont, 1);
|
|
39
|
+
applyProps(hwnd, vnode.props || {}, vnode);
|
|
40
|
+
return hwnd;
|
|
41
|
+
}
|
|
42
|
+
function isVNode(val) {
|
|
43
|
+
return val != null && typeof val === 'object' && val.constructor === undefined && val.type !== undefined;
|
|
44
|
+
}
|
|
45
|
+
function getChildren(vnode) {
|
|
46
|
+
const children = vnode.props?.children;
|
|
47
|
+
if (children == null)
|
|
48
|
+
return [];
|
|
49
|
+
if (Array.isArray(children))
|
|
50
|
+
return children.filter((c) => c != null && c !== false && c !== true);
|
|
51
|
+
if (typeof children === 'object' && children.type !== undefined)
|
|
52
|
+
return [children];
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
function renderToWin32(vnode, parentHwnd, context) {
|
|
56
|
+
if (vnode == null || vnode === false || vnode === true)
|
|
57
|
+
return 0;
|
|
58
|
+
if (typeof vnode === 'string' || typeof vnode === 'number') {
|
|
59
|
+
const hwnd = gui.CreateWindow('STATIC', String(vnode), 1073741824 /* gui.WindowStyle.CHILD */ | 268435456 /* gui.WindowStyle.VISIBLE */ | 0 /* gui.StaticStyle.LEFT */, 0, 0, 0, 0, parentHwnd, null);
|
|
60
|
+
if (hwnd)
|
|
61
|
+
gui.SendMessage(hwnd, 48 /* gui.WmMsg.SETFONT */, dpiFont, 1);
|
|
62
|
+
return hwnd;
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(vnode)) {
|
|
65
|
+
for (const child of vnode)
|
|
66
|
+
renderToWin32(child, parentHwnd, context);
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
if (!isVNode(vnode))
|
|
70
|
+
return 0;
|
|
71
|
+
if (typeof vnode.type === 'function') {
|
|
72
|
+
return renderComponent(vnode, parentHwnd, context);
|
|
73
|
+
}
|
|
74
|
+
if (vnode.type === 'w') {
|
|
75
|
+
const ctrlType = vnode.props?.type || '';
|
|
76
|
+
let hwnd;
|
|
77
|
+
if (ctrlType) {
|
|
78
|
+
hwnd = createControl(ctrlType, parentHwnd, vnode);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
hwnd = gui.CreateWindow('STATIC', '', 1073741824 /* gui.WindowStyle.CHILD */ | 268435456 /* gui.WindowStyle.VISIBLE */, 0, 0, 0, 0, parentHwnd, null);
|
|
82
|
+
if (hwnd) {
|
|
83
|
+
gui.SendMessage(hwnd, 48 /* gui.WmMsg.SETFONT */, dpiFont, 1);
|
|
84
|
+
applyProps(hwnd, vnode.props || {}, vnode);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (!hwnd)
|
|
88
|
+
return 0;
|
|
89
|
+
vnode[HWND_PROP] = hwnd;
|
|
90
|
+
vnode[STYLE_PROP] = vnode.props?.style ?? {};
|
|
91
|
+
const children = getChildren(vnode);
|
|
92
|
+
const childHwnds = [];
|
|
93
|
+
for (const child of children) {
|
|
94
|
+
const childHwnd = renderToWin32(child, hwnd, context);
|
|
95
|
+
if (childHwnd)
|
|
96
|
+
childHwnds.push(childHwnd);
|
|
97
|
+
}
|
|
98
|
+
vnode[CHILDREN_HWNDS_PROP] = childHwnds;
|
|
99
|
+
return hwnd;
|
|
100
|
+
}
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
function invokeComponent(component, vnode) {
|
|
104
|
+
options._diff?.(vnode);
|
|
105
|
+
options._render?.(vnode);
|
|
106
|
+
try {
|
|
107
|
+
const fn = vnode.type;
|
|
108
|
+
return fn.call(component, component.props, component.context);
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
const errHandler = component._errorHandler;
|
|
112
|
+
if (errHandler) {
|
|
113
|
+
errHandler(e);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
console.log('[preact-render] render threw: ' + e);
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
options.diffed?.(vnode);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function renderComponent(vnode, parentHwnd, context) {
|
|
124
|
+
const rendered = invokeComponent(newComponent(vnode, parentHwnd, context), vnode);
|
|
125
|
+
if (rendered == null)
|
|
126
|
+
return 0;
|
|
127
|
+
const resultHwnd = renderToWin32(rendered, parentHwnd, context);
|
|
128
|
+
vnode[HWND_PROP] = resultHwnd;
|
|
129
|
+
vnode[RENDERED_VNODE_PROP] = rendered;
|
|
130
|
+
return resultHwnd;
|
|
131
|
+
}
|
|
132
|
+
function newComponent(vnode, parentHwnd, context) {
|
|
133
|
+
const component = {
|
|
134
|
+
_vnode: vnode,
|
|
135
|
+
props: vnode.props,
|
|
136
|
+
context,
|
|
137
|
+
__hooks: { _list: [], _pendingEffects: [] },
|
|
138
|
+
_renderCallbacks: [],
|
|
139
|
+
_parentDom: true,
|
|
140
|
+
_qw_parent_hwnd: parentHwnd,
|
|
141
|
+
_dirty: false,
|
|
142
|
+
_forceUpdate() {
|
|
143
|
+
component._dirty = true;
|
|
144
|
+
scheduleUpdate(component);
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
vnode._component = component;
|
|
148
|
+
return component;
|
|
149
|
+
}
|
|
150
|
+
function destroyHwnd(hwnd) {
|
|
151
|
+
if (!hwnd)
|
|
152
|
+
return;
|
|
153
|
+
gui.RemoveWindow(hwnd);
|
|
154
|
+
destroyWindow(hwnd);
|
|
155
|
+
}
|
|
156
|
+
function destroyVNode(vnode) {
|
|
157
|
+
options.unmount?.(vnode);
|
|
158
|
+
const hwnd = vnode[HWND_PROP];
|
|
159
|
+
if (hwnd)
|
|
160
|
+
destroyHwnd(hwnd);
|
|
161
|
+
vnode[HWND_PROP] = 0;
|
|
162
|
+
for (const child of getChildren(vnode)) {
|
|
163
|
+
if (isVNode(child))
|
|
164
|
+
destroyVNode(child);
|
|
165
|
+
}
|
|
166
|
+
const extra = vnode[CHILDREN_HWNDS_PROP];
|
|
167
|
+
if (extra) {
|
|
168
|
+
for (const h of extra)
|
|
169
|
+
destroyHwnd(h);
|
|
170
|
+
}
|
|
171
|
+
vnode[CHILDREN_HWNDS_PROP] = [];
|
|
172
|
+
}
|
|
173
|
+
function reconcile(oldVNode, newVNode, parentHwnd, context) {
|
|
174
|
+
if (oldVNode == null || oldVNode === false || oldVNode === true) {
|
|
175
|
+
return renderToWin32(newVNode, parentHwnd, context);
|
|
176
|
+
}
|
|
177
|
+
if (newVNode == null || newVNode === false || newVNode === true) {
|
|
178
|
+
if (isVNode(oldVNode))
|
|
179
|
+
destroyVNode(oldVNode);
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
if (typeof oldVNode !== typeof newVNode ||
|
|
183
|
+
typeof oldVNode === 'string' || typeof oldVNode === 'number' ||
|
|
184
|
+
Array.isArray(oldVNode) || Array.isArray(newVNode)) {
|
|
185
|
+
if (isVNode(oldVNode))
|
|
186
|
+
destroyVNode(oldVNode);
|
|
187
|
+
return renderToWin32(newVNode, parentHwnd, context);
|
|
188
|
+
}
|
|
189
|
+
if (!isVNode(oldVNode) || !isVNode(newVNode)) {
|
|
190
|
+
return renderToWin32(newVNode, parentHwnd, context);
|
|
191
|
+
}
|
|
192
|
+
const o = oldVNode;
|
|
193
|
+
const n = newVNode;
|
|
194
|
+
if (typeof n.type === 'function') {
|
|
195
|
+
const oldComp = o._component;
|
|
196
|
+
let comp;
|
|
197
|
+
if (oldComp) {
|
|
198
|
+
oldComp._vnode = n;
|
|
199
|
+
oldComp.props = n.props;
|
|
200
|
+
oldComp._qw_parent_hwnd = parentHwnd;
|
|
201
|
+
comp = oldComp;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
comp = newComponent(n, parentHwnd, context);
|
|
205
|
+
}
|
|
206
|
+
n._component = comp;
|
|
207
|
+
const oldResult = o[RENDERED_VNODE_PROP];
|
|
208
|
+
const newResult = invokeComponent(comp, n);
|
|
209
|
+
let resultHwnd;
|
|
210
|
+
if (newResult != null) {
|
|
211
|
+
resultHwnd = reconcile(oldResult || null, newResult, parentHwnd, context);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
if (oldResult && isVNode(oldResult))
|
|
215
|
+
destroyVNode(oldResult);
|
|
216
|
+
resultHwnd = 0;
|
|
217
|
+
}
|
|
218
|
+
n[HWND_PROP] = resultHwnd;
|
|
219
|
+
n[RENDERED_VNODE_PROP] = newResult;
|
|
220
|
+
return resultHwnd;
|
|
221
|
+
}
|
|
222
|
+
if (o.type === 'w' && n.type === 'w') {
|
|
223
|
+
const oldCtrl = o.props?.type || '';
|
|
224
|
+
const newCtrl = n.props?.type || '';
|
|
225
|
+
if (oldCtrl === newCtrl) {
|
|
226
|
+
const hwnd = o[HWND_PROP];
|
|
227
|
+
if (hwnd) {
|
|
228
|
+
n[HWND_PROP] = hwnd;
|
|
229
|
+
n[STYLE_PROP] = n.props?.style ?? {};
|
|
230
|
+
n._oldProc = o._oldProc;
|
|
231
|
+
applyProps(hwnd, n.props || {}, n);
|
|
232
|
+
const oldChildren = getChildren(o);
|
|
233
|
+
const newChildren = getChildren(n);
|
|
234
|
+
const oldChildHwnds = o[CHILDREN_HWNDS_PROP];
|
|
235
|
+
const childHwnds = [];
|
|
236
|
+
const maxLen = Math.max(oldChildren.length, newChildren.length);
|
|
237
|
+
for (let i = 0; i < maxLen; i++) {
|
|
238
|
+
const oc = oldChildren[i];
|
|
239
|
+
const nc = newChildren[i];
|
|
240
|
+
if (oc != null && oc !== false && oc !== true) {
|
|
241
|
+
if (nc != null && nc !== false && nc !== true) {
|
|
242
|
+
if (typeof oc === 'string' && typeof nc === 'string') {
|
|
243
|
+
if (oc !== nc && oldChildHwnds && oldChildHwnds[i]) {
|
|
244
|
+
applyProps(oldChildHwnds[i], { text: nc });
|
|
245
|
+
}
|
|
246
|
+
if (oldChildHwnds && oldChildHwnds[i])
|
|
247
|
+
childHwnds.push(oldChildHwnds[i]);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
const ch = reconcile(oc, nc, hwnd, context);
|
|
251
|
+
if (ch)
|
|
252
|
+
childHwnds.push(ch);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
if (isVNode(oc))
|
|
257
|
+
destroyVNode(oc);
|
|
258
|
+
else if (oldChildHwnds && oldChildHwnds[i])
|
|
259
|
+
destroyHwnd(oldChildHwnds[i]);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
else if (nc != null && nc !== false && nc !== true) {
|
|
263
|
+
const ch = renderToWin32(nc, hwnd, context);
|
|
264
|
+
if (ch)
|
|
265
|
+
childHwnds.push(ch);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
n[CHILDREN_HWNDS_PROP] = childHwnds;
|
|
269
|
+
return hwnd;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
destroyVNode(o);
|
|
274
|
+
return renderToWin32(n, parentHwnd, context);
|
|
275
|
+
}
|
|
276
|
+
function scheduleUpdate(component) {
|
|
277
|
+
if (!component._dirty)
|
|
278
|
+
return;
|
|
279
|
+
os.setTimeout(() => {
|
|
280
|
+
if (!component._dirty)
|
|
281
|
+
return;
|
|
282
|
+
component._dirty = false;
|
|
283
|
+
const vnode = component._vnode;
|
|
284
|
+
const parentHwnd = component._qw_parent_hwnd;
|
|
285
|
+
if (!parentHwnd)
|
|
286
|
+
return;
|
|
287
|
+
const oldRendered = vnode[RENDERED_VNODE_PROP];
|
|
288
|
+
const rendered = invokeComponent(component, vnode);
|
|
289
|
+
if (rendered != null) {
|
|
290
|
+
reconcile(oldRendered || null, rendered, parentHwnd, component.context);
|
|
291
|
+
}
|
|
292
|
+
else if (oldRendered) {
|
|
293
|
+
if (isVNode(oldRendered))
|
|
294
|
+
destroyVNode(oldRendered);
|
|
295
|
+
}
|
|
296
|
+
vnode[RENDERED_VNODE_PROP] = rendered;
|
|
297
|
+
const commitQueue = [component];
|
|
298
|
+
options._commit?.(vnode, commitQueue);
|
|
299
|
+
if (rootHwnd && rootVNode) {
|
|
300
|
+
doLayout(rootHwnd, rootVNode);
|
|
301
|
+
}
|
|
302
|
+
}, 0);
|
|
303
|
+
}
|
|
304
|
+
export function notifyResize(hwnd) {
|
|
305
|
+
if (rootVNode)
|
|
306
|
+
doLayout(hwnd, rootVNode);
|
|
307
|
+
}
|
|
308
|
+
export function render(vnode, containerHwnd) {
|
|
309
|
+
rootHwnd = containerHwnd;
|
|
310
|
+
rootVNode = vnode;
|
|
311
|
+
renderToWin32(vnode, containerHwnd, {});
|
|
312
|
+
if (vnode._component) {
|
|
313
|
+
const commitQueue = [vnode._component];
|
|
314
|
+
options._commit?.(vnode, commitQueue);
|
|
315
|
+
}
|
|
316
|
+
doLayout(containerHwnd, vnode);
|
|
317
|
+
return containerHwnd;
|
|
318
|
+
}
|
|
319
|
+
export { HWND_PROP, STYLE_PROP, CHILDREN_HWNDS_PROP, RENDERED_VNODE_PROP, isVNode, getChildren };
|
|
320
|
+
export { scaleFactor };
|