@effindomv2/fui-as 0.1.37 → 0.1.41

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.
Files changed (119) hide show
  1. package/browser/routed-app-conventions.ts +1 -1
  2. package/browser/src/common-harness.ts +1 -27
  3. package/browser/src/index.ts +19 -26
  4. package/browser/src/routed-harness.ts +1 -194
  5. package/browser/src/shared-browser.ts +3 -0
  6. package/package.json +23 -13
  7. package/scripts/build.sh +70 -46
  8. package/scripts/check-runtime-dependency.sh +0 -19
  9. package/scripts/framework-host-services.ts +1 -1
  10. package/scripts/generate-host-events.ts +15 -241
  11. package/scripts/generate-host-services.ts +13 -261
  12. package/scripts/hostgen/assemblyscript-host-events.ts +165 -0
  13. package/scripts/hostgen/assemblyscript-host-services.ts +207 -0
  14. package/scripts/hostgen/common.ts +73 -0
  15. package/scripts/hostgen/registry.ts +159 -0
  16. package/src/Fui.ts +65 -5
  17. package/src/FuiExports.ts +12 -1
  18. package/src/bindings/ui.ts +157 -8
  19. package/src/controls/Button.ts +98 -71
  20. package/src/controls/Checkbox.ts +23 -21
  21. package/src/controls/ComboBox.ts +1201 -0
  22. package/src/controls/ContextMenu.ts +279 -165
  23. package/src/controls/Dialog.ts +91 -17
  24. package/src/controls/Dropdown.ts +101 -333
  25. package/src/controls/NavLink.ts +29 -6
  26. package/src/controls/Popup.ts +10 -5
  27. package/src/controls/ProgressBar.ts +1 -2
  28. package/src/controls/RadioButton.ts +34 -13
  29. package/src/controls/RadioGroup.ts +32 -19
  30. package/src/controls/Slider.ts +21 -23
  31. package/src/controls/Switch.ts +34 -17
  32. package/src/controls/index.ts +2 -1
  33. package/src/controls/internal/ButtonPresenter.ts +5 -2
  34. package/src/controls/internal/CheckboxIndicatorPresenter.ts +10 -10
  35. package/src/controls/internal/DropdownChevronPresenter.ts +3 -3
  36. package/src/controls/internal/DropdownFieldPresenter.ts +6 -6
  37. package/src/controls/internal/DropdownOptionRowPresenter.ts +5 -4
  38. package/src/controls/internal/PressableLabeledControl.ts +4 -7
  39. package/src/controls/internal/RadioIndicatorPresenter.ts +7 -7
  40. package/src/controls/internal/SelectablePopupList.ts +463 -0
  41. package/src/controls/internal/SliderPresenter.ts +5 -5
  42. package/src/controls/internal/SwitchIndicatorPresenter.ts +63 -17
  43. package/src/controls/internal/TextInputCore.ts +307 -41
  44. package/src/controls/internal/TextInputPresenter.ts +2 -2
  45. package/src/controls/templating.ts +10 -0
  46. package/src/core/Application.ts +17 -8
  47. package/src/core/Bitmap.ts +192 -3
  48. package/src/core/ContextMenuManager.ts +128 -44
  49. package/src/core/DebugApi.ts +17 -2
  50. package/src/core/DragGesture.ts +8 -7
  51. package/src/core/EventRouter.ts +332 -12
  52. package/src/core/Fetch.ts +15 -7
  53. package/src/core/FetchFfi.ts +1 -15
  54. package/src/core/File.ts +75 -34
  55. package/src/core/FocusAdornerManager.ts +3 -3
  56. package/src/core/FocusVisibility.ts +7 -0
  57. package/src/core/FrameScheduler.ts +104 -5
  58. package/src/core/ImageSampling.ts +43 -0
  59. package/src/core/Logger.ts +2 -0
  60. package/src/core/MobileTextSelectionToolbarManager.ts +901 -0
  61. package/src/core/Node.ts +1039 -97
  62. package/src/core/Platform.ts +16 -16
  63. package/src/core/SelectionHandleAdornerManager.ts +697 -0
  64. package/src/core/Theme.ts +34 -20
  65. package/src/core/ToolTipManager.ts +3 -3
  66. package/src/core/Typography.ts +411 -19
  67. package/src/core/Worker.ts +69 -33
  68. package/src/core/event_exports.ts +123 -5
  69. package/src/core/ffi.ts +5 -865
  70. package/src/core/generated/FetchHostAbi.ts +10 -0
  71. package/src/core/generated/FrameworkHostServices.ts +1 -1
  72. package/src/core/generated/HostAbi.ts +220 -0
  73. package/src/core/generated/UiAbi.ts +356 -0
  74. package/src/core/generated/UiEnums.ts +186 -0
  75. package/src/drawing/DrawCallback.ts +17 -1
  76. package/src/drawing/DrawContext.ts +140 -32
  77. package/src/nodes/CustomDrawable.ts +8 -1
  78. package/src/nodes/FlexBox.ts +40 -11
  79. package/src/nodes/Grid.ts +5 -5
  80. package/src/nodes/Image.ts +20 -1
  81. package/src/nodes/RichText.ts +36 -25
  82. package/src/nodes/ScrollBar.ts +2 -1
  83. package/src/nodes/ScrollBox.ts +7 -2
  84. package/src/nodes/ScrollView.ts +17 -6
  85. package/src/nodes/Svg.ts +18 -1
  86. package/src/nodes/Text.ts +1 -1
  87. package/src/nodes/TextCore.ts +115 -20
  88. package/src/nodes/index.ts +1 -1
  89. package/src/text/DynamicTextLayout.ts +275 -0
  90. package/src/text/TextLayout.ts +308 -0
  91. package/src/worker/Worker.ts +3 -36
  92. package/src/worker/WorkerJob.ts +5 -9
  93. package/src/worker/ffi.ts +0 -6
  94. package/browser/src/common-harness/host-imports.ts +0 -447
  95. package/browser/src/common-harness/interop.ts +0 -39
  96. package/browser/src/common-harness/managed-harness-bitmap-host.ts +0 -92
  97. package/browser/src/common-harness/managed-harness-canvas-host.ts +0 -72
  98. package/browser/src/common-harness/managed-harness-fetch-host.ts +0 -201
  99. package/browser/src/common-harness/managed-harness-file-host.ts +0 -1066
  100. package/browser/src/common-harness/managed-harness-file-payloads.ts +0 -143
  101. package/browser/src/common-harness/managed-harness-file-types.ts +0 -71
  102. package/browser/src/common-harness/managed-harness-session.ts +0 -15
  103. package/browser/src/common-harness/managed-harness.ts +0 -1472
  104. package/browser/src/common-harness/managed-history.ts +0 -168
  105. package/browser/src/common-harness/persisted-restore-policy.ts +0 -50
  106. package/browser/src/common-harness/persisted-ui-state-controller.ts +0 -309
  107. package/browser/src/common-harness/text-session-bridge.ts +0 -452
  108. package/browser/src/common-harness/types.ts +0 -206
  109. package/browser/src/common-harness/ui-chrome.ts +0 -206
  110. package/browser/src/common-harness/ui-imports.ts +0 -559
  111. package/browser/src/common-harness/wasm-module-cache.ts +0 -47
  112. package/browser/src/file-processing-worker.ts +0 -89
  113. package/browser/src/host-events.ts +0 -118
  114. package/browser/src/host-services.ts +0 -483
  115. package/browser/src/persisted-ui-state.ts +0 -206
  116. package/browser/src/routed-app-conventions.ts +0 -292
  117. package/browser/src/worker-bootstrap.ts +0 -916
  118. package/browser/src/worker-manager.ts +0 -234
  119. package/browser/src/worker-types.ts +0 -68
package/src/Fui.ts CHANGED
@@ -30,15 +30,22 @@ export {
30
30
  loadSvg,
31
31
  loadTexture,
32
32
  } from "./core/Assets";
33
- export { Bitmap } from "./core/Bitmap";
33
+ export { Bitmap, BitmapTextReadyEventArgs, BitmapTextReadyHandler } from "./core/Bitmap";
34
+ export { ImageSampling } from "./core/ImageSampling";
34
35
  export { DrawContext } from "./drawing/DrawContext";
35
36
  export { Paint } from "./drawing/Paint";
36
37
  export { Path } from "./drawing/Path";
37
- export { Fetch, FetchRequest, FetchResponse } from "./core/Fetch";
38
+ export { TextLayout, TextLayoutReadyEventArgs, TextLayoutReadyHandler, TextMetrics } from "./text/TextLayout";
39
+ export {
40
+ DynamicTextLayout,
41
+ DynamicTextLayoutReadyHandler,
42
+ DynamicTextOverflow,
43
+ } from "./text/DynamicTextLayout";
44
+ export { Fetch, FetchErrorEventArgs, FetchRequest, FetchResponse } from "./core/Fetch";
38
45
  export { log } from "./core/Logger";
39
46
  export { disposeAll, Disposable } from "./core/Disposable";
40
47
  export { cancelAllTimers, cancelTimer, hasTimer, scheduleTimer } from "./core/Timers";
41
- export { onLoaded } from "./core/FrameScheduler";
48
+ export { LoadedEventArgs, LoadedHandler, onLoaded, onLoadedWith } from "./core/FrameScheduler";
42
49
  export { SetBackgroundAction, SetTextAction } from "./core/Actions";
43
50
  export { hslToColor, mixColor, rgb, rgba } from "./color";
44
51
  export {
@@ -60,6 +67,13 @@ export {
60
67
  } from "./core/Animation";
61
68
  export { NodeTransitions } from "./core/Transitions";
62
69
  export {
70
+ CheckboxChangedEventArgs,
71
+ ClickEventArgs,
72
+ ComboBoxChangedEventArgs,
73
+ ContextMenuEventArgs,
74
+ DragCompletedEventArgs,
75
+ DropdownChangedEventArgs,
76
+ PointerClickEventArgs,
63
77
  DragDataObject,
64
78
  DragDropEffects,
65
79
  DragEventArgs,
@@ -68,10 +82,36 @@ export {
68
82
  ExternalDropEventArgs,
69
83
  ExternalDropItemInfo,
70
84
  ExternalDropItemKind,
85
+ DEFAULT_LONG_PRESS_MINIMUM_DURATION_MS,
86
+ DEFAULT_LONG_PRESS_MOVEMENT_TOLERANCE,
87
+ FocusChangedEventArgs,
88
+ GestureEventArgs,
89
+ GestureEventKind,
90
+ GestureEventPhase,
91
+ HoverChangedEventArgs,
92
+ KeyEventArgs,
93
+ LongPressGesture,
94
+ LongPressEventArgs,
71
95
  Node,
96
+ PointerButton,
97
+ PointerButtons,
98
+ PanGestureEventArgs,
99
+ PinchGestureEventArgs,
100
+ PointerEventArgs,
101
+ PointerType,
102
+ RadioButtonChangedEventArgs,
103
+ RadioGroupChangedEventArgs,
104
+ SelectionChangedEventArgs,
105
+ SliderChangedEventArgs,
106
+ SwitchChangedEventArgs,
107
+ TextChangedEventArgs,
108
+ VisibilityChangedEventArgs,
109
+ WheelDeltaMode,
110
+ WheelEventArgs,
72
111
  } from "./core/Node";
73
112
  export { DragCompletedEvent, DragDeltaEvent, DragGesture, DragGestureHost, DragStartedEvent } from "./core/DragGesture";
74
113
  export { ContextMenuManager } from "./core/ContextMenuManager";
114
+ export { NavigateEventArgs } from "./controls/NavLink";
75
115
  export {
76
116
  AlignSelf,
77
117
  AlignItems,
@@ -100,12 +140,26 @@ export {
100
140
  export { Signal } from "./core/Signal";
101
141
  export { showKeyboardFocusForKeyEvent } from "./core/FocusVisibility";
102
142
  export { ToolTip, PopupPlacement } from "./core/ToolTip";
103
- export { FontFace, FontFamily, FontStack, FontStyle, FontWeight } from "./core/Typography";
143
+ export {
144
+ FontFace,
145
+ FontFaceLoadedEventArgs,
146
+ FontFamily,
147
+ FontLoadedHandler,
148
+ FontReadyHandler,
149
+ FontsLoadedEventArgs,
150
+ FontStack,
151
+ FontStackLoadedEventArgs,
152
+ FontStackLoadedHandler,
153
+ FontStyle,
154
+ FontWeight,
155
+ } from "./core/Typography";
104
156
  export {
105
157
  BrowserFile,
106
158
  BrowserFileWriter,
107
159
  File,
108
160
  FileCapabilities,
161
+ FileErrorEventArgs,
162
+ FileOpenEventArgs,
109
163
  FileReadChunk,
110
164
  FileWorkerProcessProgress,
111
165
  FileWorkerProcessRequest,
@@ -115,7 +169,7 @@ export {
115
169
  FileSaveResult,
116
170
  FileWriteProgress,
117
171
  } from "./core/File";
118
- export { Worker } from "./core/Worker";
172
+ export { Worker, WorkerCompletedEventArgs, WorkerErrorEventArgs, WorkerProgressEventArgs } from "./core/Worker";
119
173
  export { Worker as WorkerRuntime } from "./worker/Worker";
120
174
  export { WorkerJob } from "./worker/WorkerJob";
121
175
  export { currentRoute, navigateTo } from "./core/Navigation";
@@ -140,6 +194,7 @@ export {
140
194
  useSystemTheme,
141
195
  } from "./core/Theme";
142
196
  export { frameTimeSignal, viewportHeightSignal, viewportWidthSignal } from "./core/event_exports";
197
+ export { getDevicePixelRatio as devicePixelRatio } from "./bindings/ui";
143
198
  export {
144
199
  AntiSelectionArea,
145
200
  Button,
@@ -152,6 +207,10 @@ export {
152
207
  CheckboxIndicatorVisualState,
153
208
  Checkbox,
154
209
  clearControlTemplates,
210
+ ComboBox,
211
+ ComboBoxCommitMode,
212
+ ComboBoxFilterMode,
213
+ ComboBoxItem,
155
214
  ControlTemplateSet,
156
215
  ContextMenu,
157
216
  Dialog,
@@ -204,6 +263,7 @@ export {
204
263
  useControlTemplates,
205
264
  } from "./controls";
206
265
  export {
266
+ Border,
207
267
  FlexBox,
208
268
  FlexBoxProps,
209
269
  CustomDrawable,
package/src/FuiExports.ts CHANGED
@@ -7,6 +7,7 @@ export {
7
7
  } from "./core/Application";
8
8
  export {
9
9
  __fui_on_external_drag_event,
10
+ __fui_can_show_context_menu,
10
11
  __fui_on_fetch_complete,
11
12
  __fui_on_fetch_error,
12
13
  __fui_on_file_finish_result,
@@ -25,15 +26,25 @@ export {
25
26
  __fui_on_cross_selection_changed,
26
27
  __fui_on_focus_changed,
27
28
  __fui_on_frame,
29
+ __fui_get_gesture_intent,
30
+ __fui_get_long_press_minimum_duration_ms,
31
+ __fui_get_long_press_movement_tolerance,
32
+ __fui_on_gesture_event,
33
+ __fui_on_long_press_event,
28
34
  __fui_on_key_event,
29
- __fui_on_pointer_event,
35
+ __fui_on_pointer_event_with_metadata,
30
36
  __fui_on_route_changed,
31
37
  __fui_on_scroll,
32
38
  __fui_on_selection_changed,
39
+ __fui_on_system_accent_color_changed,
33
40
  __fui_on_system_dark_mode_changed,
34
41
  __fui_on_text_changed,
35
42
  __fui_on_text_replaced,
36
43
  __fui_on_timer,
44
+ __fui_on_wheel_event,
45
+ __fui_resolve_gesture_owner,
46
+ __fui_resolve_long_press_owner,
47
+ __fui_on_font_loaded,
37
48
  __fui_on_viewport_changed,
38
49
  __fui_on_worker_complete,
39
50
  __fui_on_worker_error,
@@ -180,6 +180,42 @@ export function setFlexWrap(handle: u64, wrap: u32): void {
180
180
  ffi.ui_set_flex_wrap(handle, wrap);
181
181
  }
182
182
 
183
+ export function prepareNode(handle: u64): u32 {
184
+ return ffi.ui_prepare_node(handle);
185
+ }
186
+
187
+ export function setDynamicTextCharset(handle: u64, charset: string): void {
188
+ const bytes = encodeUtf8(charset);
189
+ ffi.ui_set_dynamic_text_charset(handle, bytes.length > 0 ? bytes.dataStart : 0, <u32>bytes.length);
190
+ }
191
+
192
+ export function registerTextInputMetadata(handle: u64, isPassword: bool, hostAutofillHint: string | null): void {
193
+ if (hostAutofillHint === null || hostAutofillHint.length == 0) {
194
+ ffi.fui_register_text_input_metadata(handle, isPassword, 0, 0);
195
+ return;
196
+ }
197
+ const bytes = encodeUtf8(hostAutofillHint);
198
+ ffi.fui_register_text_input_metadata(handle, isPassword, bytes.dataStart, <u32>bytes.length);
199
+ }
200
+
201
+ export function tryGetTextMetrics(handle: u64): Float32Array | null {
202
+ const values = new Float32Array(5);
203
+ const lineCount = new Uint32Array(1);
204
+ const found = ffi.ui_get_text_metrics(
205
+ handle,
206
+ values.dataStart,
207
+ values.dataStart + sizeof<f32>(),
208
+ values.dataStart + (sizeof<f32>() * 2),
209
+ lineCount.dataStart,
210
+ values.dataStart + (sizeof<f32>() * 4),
211
+ );
212
+ if (!found) {
213
+ return null;
214
+ }
215
+ unchecked(values[3] = <f32>unchecked(lineCount[0]));
216
+ return values;
217
+ }
218
+
183
219
  export function gridSetColumns(handle: u64, values: Float32Array, types: Uint8Array): void {
184
220
  ffi.ui_grid_set_columns(
185
221
  handle,
@@ -263,8 +299,8 @@ export function setBackgroundBlur(handle: u64, blurSigma: f32): void {
263
299
  ffi.ui_set_background_blur(handle, blurSigma);
264
300
  }
265
301
 
266
- export function setImage(handle: u64, textureId: u32, objectFit: u32): void {
267
- ffi.ui_set_image(handle, textureId, objectFit);
302
+ export function setImage(handle: u64, textureId: u32, objectFit: u32, samplingKind: u32, maxAniso: u32): void {
303
+ ffi.ui_set_image(handle, textureId, objectFit, samplingKind, maxAniso);
268
304
  }
269
305
 
270
306
  export function setImageNine(
@@ -274,12 +310,14 @@ export function setImageNine(
274
310
  insetTop: f32,
275
311
  insetRight: f32,
276
312
  insetBottom: f32,
313
+ samplingKind: u32,
314
+ maxAniso: u32,
277
315
  ): void {
278
- ffi.ui_set_image_nine(handle, textureId, insetLeft, insetTop, insetRight, insetBottom);
316
+ ffi.ui_set_image_nine(handle, textureId, insetLeft, insetTop, insetRight, insetBottom, samplingKind, maxAniso);
279
317
  }
280
318
 
281
- export function setSvg(handle: u64, svgId: u32, tintColor: u32): void {
282
- ffi.ui_set_svg(handle, svgId, tintColor);
319
+ export function setSvg(handle: u64, svgId: u32, tintColor: u32, samplingKind: u32, maxAniso: u32): void {
320
+ ffi.ui_set_svg(handle, svgId, tintColor, samplingKind, maxAniso);
283
321
  }
284
322
 
285
323
  export function setLinearGradient(
@@ -301,10 +339,9 @@ export function setLinearGradient(
301
339
  endX,
302
340
  endY,
303
341
  <u32>offsets.length,
342
+ offsets.length > 0 ? offsets.dataStart : 0,
343
+ colors.length > 0 ? colors.dataStart : 0,
304
344
  );
305
- for (let i = 0; i < offsets.length; ++i) {
306
- ffi.ui_push_linear_gradient_stop(handle, unchecked(offsets[i]), unchecked(colors[i]));
307
- }
308
345
  }
309
346
 
310
347
  export function setClipToBounds(handle: u64, clip: bool): void {
@@ -315,6 +352,10 @@ export function setInteractive(handle: u64, flag: bool): void {
315
352
  ffi.ui_set_interactive(handle, flag);
316
353
  }
317
354
 
355
+ export function setPreserveSelectionOnPointerDown(handle: u64, preserve: bool): void {
356
+ ffi.ui_set_preserve_selection_on_pointer_down(handle, preserve);
357
+ }
358
+
318
359
  export function setScrollProxyTarget(handle: u64, scrollHandle: u64): void {
319
360
  ffi.ui_set_scroll_proxy_target(handle, scrollHandle);
320
361
  }
@@ -331,6 +372,10 @@ export function setScrollFriction(handle: u64, friction: f32): void {
331
372
  ffi.ui_set_scroll_friction(handle, friction);
332
373
  }
333
374
 
375
+ export function setSmoothScrolling(handle: u64, smoothScrolling: bool): void {
376
+ ffi.ui_set_smooth_scrolling(handle, smoothScrolling);
377
+ }
378
+
334
379
  export function setFocusable(handle: u64, flag: bool, tabIndex: i32): void {
335
380
  ffi.ui_set_focusable(handle, flag, tabIndex);
336
381
  }
@@ -380,6 +425,10 @@ export function bitmapRelease(textureId: u32): void {
380
425
  ffi.fui_bitmap_release(textureId);
381
426
  }
382
427
 
428
+ export function renderNodeToRgba(handle: u64, width: u32, height: u32, outPtr: usize, capacity: u32, scale: f32, x: f32, y: f32): u32 {
429
+ return ffi.fui_render_node_to_rgba(handle, width, height, outPtr, capacity, scale, x, y);
430
+ }
431
+
383
432
  export function loadFont(fontId: u32, url: string): void {
384
433
  const bytes = encodeUtf8(url);
385
434
  ffi.fui_load_font(fontId, bytes.length > 0 ? bytes.dataStart : 0, <u32>bytes.length);
@@ -445,6 +494,14 @@ export function setEditable(handle: u64, editable: bool): void {
445
494
  ffi.ui_set_editable(handle, editable);
446
495
  }
447
496
 
497
+ export function setEditorCommandKeys(handle: u64, enabled: bool): void {
498
+ ffi.ui_set_editor_command_keys(handle, enabled);
499
+ }
500
+
501
+ export function setEditorAcceptsTab(handle: u64, enabled: bool): void {
502
+ ffi.ui_set_editor_accepts_tab(handle, enabled);
503
+ }
504
+
448
505
  export function setCaretColor(handle: u64, color: u32): void {
449
506
  ffi.ui_set_caret_color(handle, color);
450
507
  }
@@ -489,6 +546,82 @@ export function setTextSelectionRange(handle: u64, selectionStart: u32, selectio
489
546
  ffi.ui_set_text_selection_range(handle, selectionStart, selectionEnd);
490
547
  }
491
548
 
549
+ export function selectWordAt(handle: u64, x: f32, y: f32): bool {
550
+ return ffi.ui_select_word_at(handle, x, y);
551
+ }
552
+
553
+ export function beginSelectionEndpointDrag(handle: u64, endpoint: u32): bool {
554
+ return ffi.ui_begin_selection_endpoint_drag(handle, endpoint);
555
+ }
556
+
557
+ export class TextRangeRect {
558
+ readonly x: f32;
559
+ readonly y: f32;
560
+ readonly width: f32;
561
+ readonly height: f32;
562
+
563
+ constructor(x: f32, y: f32, width: f32, height: f32) {
564
+ this.x = x;
565
+ this.y = y;
566
+ this.width = width;
567
+ this.height = height;
568
+ }
569
+ }
570
+
571
+ export function getTextRangeRects(handle: u64, start: u32, end: u32): Array<TextRangeRect> {
572
+ const rectCount = ffi.ui_get_text_range_rect_count(handle, start, end);
573
+ if (rectCount == 0) {
574
+ return new Array<TextRangeRect>();
575
+ }
576
+ const rectWords = new StaticArray<f32>(<i32>rectCount * 4);
577
+ const copiedCount = ffi.ui_copy_text_range_rects(handle, start, end, changetype<usize>(rectWords), rectCount);
578
+ if (copiedCount == 0) {
579
+ return new Array<TextRangeRect>();
580
+ }
581
+ const rects = new Array<TextRangeRect>(copiedCount);
582
+ for (let index: u32 = 0; index < copiedCount; ++index) {
583
+ const base = <i32>index * 4;
584
+ unchecked(rects[<i32>index] = new TextRangeRect(
585
+ unchecked(rectWords[base]),
586
+ unchecked(rectWords[base + 1]),
587
+ unchecked(rectWords[base + 2]),
588
+ unchecked(rectWords[base + 3]),
589
+ ));
590
+ }
591
+ return rects;
592
+ }
593
+
594
+ export class TextSelectionEndpointRects {
595
+ readonly start: TextRangeRect;
596
+ readonly end: TextRangeRect;
597
+
598
+ constructor(start: TextRangeRect, end: TextRangeRect) {
599
+ this.start = start;
600
+ this.end = end;
601
+ }
602
+ }
603
+
604
+ export function getCrossSelectionEndpointRects(areaHandle: u64): TextSelectionEndpointRects | null {
605
+ const rectWords = new StaticArray<f32>(8);
606
+ if (!ffi.ui_copy_cross_selection_endpoint_rects(areaHandle, changetype<usize>(rectWords))) {
607
+ return null;
608
+ }
609
+ return new TextSelectionEndpointRects(
610
+ new TextRangeRect(
611
+ unchecked(rectWords[0]),
612
+ unchecked(rectWords[1]),
613
+ unchecked(rectWords[2]),
614
+ unchecked(rectWords[3]),
615
+ ),
616
+ new TextRangeRect(
617
+ unchecked(rectWords[4]),
618
+ unchecked(rectWords[5]),
619
+ unchecked(rectWords[6]),
620
+ unchecked(rectWords[7]),
621
+ ),
622
+ );
623
+ }
624
+
492
625
  export function clearCurrentSelection(): void {
493
626
  ffi.ui_clear_current_selection();
494
627
  }
@@ -554,6 +687,18 @@ export function tryGetBounds(handle: u64): Float32Array | null {
554
687
  return found ? values : null;
555
688
  }
556
689
 
690
+ export function tryGetVisibleBounds(handle: u64): Float32Array | null {
691
+ const values = new Float32Array(4);
692
+ const found = ffi.ui_get_visible_bounds(
693
+ handle,
694
+ values.dataStart,
695
+ values.dataStart + sizeof<f32>(),
696
+ values.dataStart + (sizeof<f32>() * 2),
697
+ values.dataStart + (sizeof<f32>() * 3),
698
+ );
699
+ return found ? values : null;
700
+ }
701
+
557
702
  export function resizeWindow(width: f32, height: f32): void {
558
703
  ffi.ui_resize_window(width, height);
559
704
  }
@@ -569,3 +714,7 @@ export function getViewportWidth(): f32 {
569
714
  export function getViewportHeight(): f32 {
570
715
  return ffi.get_viewport_height();
571
716
  }
717
+
718
+ export function getDevicePixelRatio(): f32 {
719
+ return ffi.get_device_pixel_ratio();
720
+ }