basalt-core 0.0.0-rc5
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/LICENSE +21 -0
- package/dist/cli/basalt.d.ts +3 -0
- package/dist/cli/basalt.d.ts.map +1 -0
- package/dist/cli/basalt.js +47 -0
- package/dist/cli/basalt.js.map +1 -0
- package/dist/cli/bundle-cli.d.ts +12 -0
- package/dist/cli/bundle-cli.d.ts.map +1 -0
- package/dist/cli/bundle-cli.js +124 -0
- package/dist/cli/bundle-cli.js.map +1 -0
- package/dist/cli/bundleWithAssets.d.ts +79 -0
- package/dist/cli/bundleWithAssets.d.ts.map +1 -0
- package/dist/cli/bundleWithAssets.js +198 -0
- package/dist/cli/bundleWithAssets.js.map +1 -0
- package/dist/cli/desktop.d.ts +339 -0
- package/dist/cli/desktop.d.ts.map +1 -0
- package/dist/cli/desktop.js +1029 -0
- package/dist/cli/desktop.js.map +1 -0
- package/dist/cli/doctor.d.ts +31 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +283 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.d.ts +77 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +442 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/metro.d.ts +49 -0
- package/dist/cli/metro.d.ts.map +1 -0
- package/dist/cli/metro.js +148 -0
- package/dist/cli/metro.js.map +1 -0
- package/dist/cli/packageApp.d.ts +102 -0
- package/dist/cli/packageApp.d.ts.map +1 -0
- package/dist/cli/packageApp.js +319 -0
- package/dist/cli/packageApp.js.map +1 -0
- package/dist/cli/steps.d.ts +34 -0
- package/dist/cli/steps.d.ts.map +1 -0
- package/dist/cli/steps.js +53 -0
- package/dist/cli/steps.js.map +1 -0
- package/dist/metro-config.d.ts +168 -0
- package/dist/metro-config.d.ts.map +1 -0
- package/dist/metro-config.js +671 -0
- package/dist/metro-config.js.map +1 -0
- package/dist/react-native.config.d.ts +7 -0
- package/dist/react-native.config.d.ts.map +1 -0
- package/dist/react-native.config.js +80 -0
- package/dist/react-native.config.js.map +1 -0
- package/dist/src/DragSource.d.ts +52 -0
- package/dist/src/DragSource.d.ts.map +1 -0
- package/dist/src/DragSource.js +97 -0
- package/dist/src/DragSource.js.map +1 -0
- package/dist/src/DropTarget.d.ts +58 -0
- package/dist/src/DropTarget.d.ts.map +1 -0
- package/dist/src/DropTarget.js +131 -0
- package/dist/src/DropTarget.js.map +1 -0
- package/dist/src/KeyHandler.d.ts +57 -0
- package/dist/src/KeyHandler.d.ts.map +1 -0
- package/dist/src/KeyHandler.js +48 -0
- package/dist/src/KeyHandler.js.map +1 -0
- package/dist/src/Menu.d.ts +72 -0
- package/dist/src/Menu.d.ts.map +1 -0
- package/dist/src/Menu.js +179 -0
- package/dist/src/Menu.js.map +1 -0
- package/dist/src/TitleBar.d.ts +75 -0
- package/dist/src/TitleBar.d.ts.map +1 -0
- package/dist/src/TitleBar.js +236 -0
- package/dist/src/TitleBar.js.map +1 -0
- package/dist/src/Window.d.ts +87 -0
- package/dist/src/Window.d.ts.map +1 -0
- package/dist/src/Window.js +248 -0
- package/dist/src/Window.js.map +1 -0
- package/dist/src/closeRequest.d.ts +55 -0
- package/dist/src/closeRequest.d.ts.map +1 -0
- package/dist/src/closeRequest.js +134 -0
- package/dist/src/closeRequest.js.map +1 -0
- package/dist/src/index.d.ts +45 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +92 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/overrides/Alert.d.ts +69 -0
- package/dist/src/overrides/Alert.d.ts.map +1 -0
- package/dist/src/overrides/Alert.js +112 -0
- package/dist/src/overrides/Alert.js.map +1 -0
- package/dist/src/overrides/BaseViewConfig.d.ts +28 -0
- package/dist/src/overrides/BaseViewConfig.d.ts.map +1 -0
- package/dist/src/overrides/BaseViewConfig.js +72 -0
- package/dist/src/overrides/BaseViewConfig.js.map +1 -0
- package/dist/src/overrides/Platform.linux.d.ts +10 -0
- package/dist/src/overrides/Platform.linux.d.ts.map +1 -0
- package/dist/src/overrides/Platform.linux.js +15 -0
- package/dist/src/overrides/Platform.linux.js.map +1 -0
- package/dist/src/overrides/Platform.macos.d.ts +10 -0
- package/dist/src/overrides/Platform.macos.d.ts.map +1 -0
- package/dist/src/overrides/Platform.macos.js +15 -0
- package/dist/src/overrides/Platform.macos.js.map +1 -0
- package/dist/src/overrides/Platform.windows.d.ts +10 -0
- package/dist/src/overrides/Platform.windows.d.ts.map +1 -0
- package/dist/src/overrides/Platform.windows.js +15 -0
- package/dist/src/overrides/Platform.windows.js.map +1 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts +24 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts.map +1 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.js +30 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.js.map +1 -0
- package/dist/src/overrides/RefreshControl.d.ts +52 -0
- package/dist/src/overrides/RefreshControl.d.ts.map +1 -0
- package/dist/src/overrides/RefreshControl.js +92 -0
- package/dist/src/overrides/RefreshControl.js.map +1 -0
- package/dist/src/overrides/ScrollView.d.ts +39 -0
- package/dist/src/overrides/ScrollView.d.ts.map +1 -0
- package/dist/src/overrides/ScrollView.js +59 -0
- package/dist/src/overrides/ScrollView.js.map +1 -0
- package/dist/src/overrides/Share.d.ts +96 -0
- package/dist/src/overrides/Share.d.ts.map +1 -0
- package/dist/src/overrides/Share.js +97 -0
- package/dist/src/overrides/Share.js.map +1 -0
- package/dist/src/overrides/TextInput.d.ts +81 -0
- package/dist/src/overrides/TextInput.d.ts.map +1 -0
- package/dist/src/overrides/TextInput.js +213 -0
- package/dist/src/overrides/TextInput.js.map +1 -0
- package/dist/src/overrides/View.d.ts +36 -0
- package/dist/src/overrides/View.d.ts.map +1 -0
- package/dist/src/overrides/View.js +99 -0
- package/dist/src/overrides/View.js.map +1 -0
- package/dist/src/overrides/createPlatform.d.ts +32 -0
- package/dist/src/overrides/createPlatform.d.ts.map +1 -0
- package/dist/src/overrides/createPlatform.js +84 -0
- package/dist/src/overrides/createPlatform.js.map +1 -0
- package/dist/src/overrides/setUpDeveloperTools.d.ts +28 -0
- package/dist/src/overrides/setUpDeveloperTools.d.ts.map +1 -0
- package/dist/src/overrides/setUpDeveloperTools.js +84 -0
- package/dist/src/overrides/setUpDeveloperTools.js.map +1 -0
- package/dist/src/overrides/setUpXHR.d.ts +46 -0
- package/dist/src/overrides/setUpXHR.d.ts.map +1 -0
- package/dist/src/overrides/setUpXHR.js +236 -0
- package/dist/src/overrides/setUpXHR.js.map +1 -0
- package/dist/src/quitRequest.d.ts +55 -0
- package/dist/src/quitRequest.d.ts.map +1 -0
- package/dist/src/quitRequest.js +121 -0
- package/dist/src/quitRequest.js.map +1 -0
- package/dist/src/resourcePath.d.ts +18 -0
- package/dist/src/resourcePath.d.ts.map +1 -0
- package/dist/src/resourcePath.js +31 -0
- package/dist/src/resourcePath.js.map +1 -0
- package/dist/src/responseBody.d.ts +76 -0
- package/dist/src/responseBody.d.ts.map +1 -0
- package/dist/src/responseBody.js +94 -0
- package/dist/src/responseBody.js.map +1 -0
- package/dist/src/responseHeaders.d.ts +40 -0
- package/dist/src/responseHeaders.d.ts.map +1 -0
- package/dist/src/responseHeaders.js +75 -0
- package/dist/src/responseHeaders.js.map +1 -0
- package/dist/src/titleBarState.d.ts +43 -0
- package/dist/src/titleBarState.d.ts.map +1 -0
- package/dist/src/titleBarState.js +77 -0
- package/dist/src/titleBarState.js.map +1 -0
- package/dist/src/useContextMenu.d.ts +113 -0
- package/dist/src/useContextMenu.d.ts.map +1 -0
- package/dist/src/useContextMenu.js +109 -0
- package/dist/src/useContextMenu.js.map +1 -0
- package/dist/src/useDialog.d.ts +98 -0
- package/dist/src/useDialog.d.ts.map +1 -0
- package/dist/src/useDialog.js +112 -0
- package/dist/src/useDialog.js.map +1 -0
- package/dist/src/useDisplays.d.ts +70 -0
- package/dist/src/useDisplays.d.ts.map +1 -0
- package/dist/src/useDisplays.js +118 -0
- package/dist/src/useDisplays.js.map +1 -0
- package/dist/src/useHandledKeys.d.ts +38 -0
- package/dist/src/useHandledKeys.d.ts.map +1 -0
- package/dist/src/useHandledKeys.js +70 -0
- package/dist/src/useHandledKeys.js.map +1 -0
- package/dist/src/useWindow.d.ts +140 -0
- package/dist/src/useWindow.d.ts.map +1 -0
- package/dist/src/useWindow.js +233 -0
- package/dist/src/useWindow.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/native/CMakeLists.txt +355 -0
- package/native/bootstrap.sh +613 -0
- package/native/cmake/CompilerFlags.cmake +49 -0
- package/native/cmake/Expo.cmake +125 -0
- package/native/cmake/ReactNativeCore.cmake +612 -0
- package/native/cmake/Reanimated.cmake +108 -0
- package/native/cmake/Skia.cmake +379 -0
- package/native/cmake/ThirdParty.cmake +290 -0
- package/native/cmake/Worklets.cmake +67 -0
- package/native/cmake/codegen/CMakeLists.txt +32 -0
- package/native/core/AppIdentity.cpp +85 -0
- package/native/core/AppIdentity.h +59 -0
- package/native/core/AppPaths.cpp +96 -0
- package/native/core/AppPaths.h +53 -0
- package/native/core/AppearanceModule.cpp +60 -0
- package/native/core/AppearanceModule.h +40 -0
- package/native/core/Backface.h +59 -0
- package/native/core/BlobModule.cpp +283 -0
- package/native/core/BlobModule.h +76 -0
- package/native/core/BlobRegistry.cpp +75 -0
- package/native/core/BlobRegistry.h +44 -0
- package/native/core/ColorScheme.cpp +105 -0
- package/native/core/ColorScheme.h +59 -0
- package/native/core/ComponentRegistry.h +30 -0
- package/native/core/ControlMetrics.h +37 -0
- package/native/core/CoreModules.cpp +592 -0
- package/native/core/CoreModules.h +308 -0
- package/native/core/DebuggingOverlay.cpp +106 -0
- package/native/core/DebuggingOverlay.h +65 -0
- package/native/core/DesktopControls.cpp +232 -0
- package/native/core/DesktopControls.h +170 -0
- package/native/core/DevBundle.cpp +108 -0
- package/native/core/DevBundle.h +69 -0
- package/native/core/DevMenu.cpp +99 -0
- package/native/core/DevMenu.h +75 -0
- package/native/core/DialogModule.cpp +150 -0
- package/native/core/DialogModule.h +51 -0
- package/native/core/DragAndDrop.cpp +45 -0
- package/native/core/DragAndDrop.h +225 -0
- package/native/core/ExpoImageComponent.cpp +79 -0
- package/native/core/ExpoImageComponent.h +80 -0
- package/native/core/ExpoModules.cpp +415 -0
- package/native/core/ExpoModules.h +115 -0
- package/native/core/ExpoRuntime.cpp +366 -0
- package/native/core/ExpoRuntime.h +42 -0
- package/native/core/FocusRing.h +36 -0
- package/native/core/FontRegistry.h +51 -0
- package/native/core/GestureHandlerModule.cpp +136 -0
- package/native/core/GestureHandlerModule.h +71 -0
- package/native/core/Gestures.cpp +533 -0
- package/native/core/Gestures.h +145 -0
- package/native/core/HoverTracker.cpp +69 -0
- package/native/core/HoverTracker.h +109 -0
- package/native/core/HttpClient.cpp +282 -0
- package/native/core/ImageBytes.cpp +205 -0
- package/native/core/ImageBytes.h +29 -0
- package/native/core/ImageCache.cpp +51 -0
- package/native/core/ImageCache.h +89 -0
- package/native/core/JsRuntimeAccess.cpp +70 -0
- package/native/core/JsRuntimeAccess.h +60 -0
- package/native/core/JsiPromise.h +51 -0
- package/native/core/KeyEvents.cpp +116 -0
- package/native/core/KeyEvents.h +144 -0
- package/native/core/LogBoxSurface.cpp +46 -0
- package/native/core/LogBoxSurface.h +68 -0
- package/native/core/MenuModel.h +117 -0
- package/native/core/MenuModule.cpp +209 -0
- package/native/core/MenuModule.h +66 -0
- package/native/core/MountingWalk.h +524 -0
- package/native/core/PackageModules.cpp.in +25 -0
- package/native/core/PackageModules.h +50 -0
- package/native/core/PlatformConstantsModule.cpp +63 -0
- package/native/core/PlatformConstantsModule.h +64 -0
- package/native/core/PlatformServices.h +213 -0
- package/native/core/PointerButtons.h +63 -0
- package/native/core/PullToRefresh.cpp +57 -0
- package/native/core/PullToRefresh.h +73 -0
- package/native/core/ReanimatedCompat.h +47 -0
- package/native/core/ReanimatedModule.cpp +203 -0
- package/native/core/ReanimatedModule.h +55 -0
- package/native/core/ScrollAnimation.cpp +59 -0
- package/native/core/ScrollAnimation.h +70 -0
- package/native/core/ScrollBounds.cpp +26 -0
- package/native/core/ScrollBounds.h +68 -0
- package/native/core/ScrollIndicator.cpp +50 -0
- package/native/core/ScrollIndicator.h +69 -0
- package/native/core/ScrollMomentum.cpp +71 -0
- package/native/core/ScrollMomentum.h +73 -0
- package/native/core/ScrollSnap.cpp +123 -0
- package/native/core/ScrollSnap.h +80 -0
- package/native/core/ShareFallback.cpp +101 -0
- package/native/core/ShareFallback.h +45 -0
- package/native/core/SkiaPictureViewComponent.cpp +11 -0
- package/native/core/SkiaPictureViewComponent.h +47 -0
- package/native/core/SourceCodeModule.cpp +55 -0
- package/native/core/SourceCodeModule.h +53 -0
- package/native/core/StatusBarModule.cpp +23 -0
- package/native/core/StatusBarModule.h +42 -0
- package/native/core/TestDialog.cpp +148 -0
- package/native/core/TestDialog.h +96 -0
- package/native/core/TestKeys.cpp +78 -0
- package/native/core/TestKeys.h +50 -0
- package/native/core/TestQuitFile.cpp +33 -0
- package/native/core/TestQuitFile.h +60 -0
- package/native/core/TestSettle.h +192 -0
- package/native/core/TitleBarRegions.h +31 -0
- package/native/core/TurboModuleProxy.cpp +51 -0
- package/native/core/TurboModuleProxy.h +46 -0
- package/native/core/UIManagerAccess.cpp +43 -0
- package/native/core/UIManagerAccess.h +43 -0
- package/native/core/WindowBoundsCache.cpp +319 -0
- package/native/core/WindowControl.h +235 -0
- package/native/core/WindowHost.h +158 -0
- package/native/core/WindowMethods.cpp +167 -0
- package/native/core/WindowMethods.h +84 -0
- package/native/core/WindowsModule.cpp +448 -0
- package/native/core/WindowsModule.h +133 -0
- package/native/core/WorkletsModule.cpp +199 -0
- package/native/core/WorkletsModule.h +57 -0
- package/native/core/portability_probe.cpp +210 -0
- package/native/tests/EventRecorder.h +124 -0
- package/native/tests/TestHarness.cpp +109 -0
- package/native/tests/TestHarness.h +89 -0
- package/native/tests/TreeDump.h +49 -0
- package/native/tests/test_app_identity.cpp +114 -0
- package/native/tests/test_app_paths.cpp +48 -0
- package/native/tests/test_appearance.cpp +107 -0
- package/native/tests/test_backface.cpp +79 -0
- package/native/tests/test_blobs.cpp +157 -0
- package/native/tests/test_controls.cpp +185 -0
- package/native/tests/test_devbundle.cpp +103 -0
- package/native/tests/test_drag_and_drop.cpp +143 -0
- package/native/tests/test_gestures.cpp +331 -0
- package/native/tests/test_hover.cpp +92 -0
- package/native/tests/test_image_cache.cpp +109 -0
- package/native/tests/test_js_runtime_access.cpp +137 -0
- package/native/tests/test_key_events.cpp +235 -0
- package/native/tests/test_momentum.cpp +138 -0
- package/native/tests/test_quit_file.cpp +104 -0
- package/native/tests/test_scroll_animation.cpp +120 -0
- package/native/tests/test_scroll_bounds.cpp +66 -0
- package/native/tests/test_scroll_indicator.cpp +149 -0
- package/native/tests/test_scroll_snap.cpp +112 -0
- package/native/tests/test_settle.cpp +115 -0
- package/native/tests/test_share.cpp +75 -0
- package/native/tests/test_sourcecode.cpp +62 -0
- package/native/tests/test_window_close.cpp +119 -0
- package/native/tests/test_window_limits.cpp +123 -0
- package/package.json +43 -0
- package/react-native.config.js +86 -0
- package/supported-versions.json +66 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// The window's geometry: how big it is, where it is, and whether it fills the
|
|
2
|
+
// screen.
|
|
3
|
+
//
|
|
4
|
+
// React Native has no API for any of this, for the same reason it has no file
|
|
5
|
+
// dialog: on a phone there is one window, it is the screen, and nothing an app
|
|
6
|
+
// can say would change it. On a desktop it is the first thing an app wants
|
|
7
|
+
// after it has drawn something.
|
|
8
|
+
//
|
|
9
|
+
// A seam rather than three modules. The title bar next door is per-host because
|
|
10
|
+
// what it does differs per host -- GTK installs a header bar to have something
|
|
11
|
+
// to style, Windows draws its own caption buttons -- but a window's size is the
|
|
12
|
+
// same idea everywhere and only the call differs. So the JavaScript boundary is
|
|
13
|
+
// written once, in core/WindowMethods.h, and this is the four lines under it
|
|
14
|
+
// each platform answers.
|
|
15
|
+
//
|
|
16
|
+
// One window, which is the honest limit. Every function here means "the
|
|
17
|
+
// window", because the host makes exactly one; multiple windows are their own
|
|
18
|
+
// piece of work and are in docs/BACKLOG.md. When they arrive these grow a
|
|
19
|
+
// window argument and the module grows a handle, and nothing above changes
|
|
20
|
+
// shape.
|
|
21
|
+
|
|
22
|
+
#pragma once
|
|
23
|
+
|
|
24
|
+
#include <functional>
|
|
25
|
+
#include <vector>
|
|
26
|
+
|
|
27
|
+
namespace basalt {
|
|
28
|
+
|
|
29
|
+
struct WindowBounds {
|
|
30
|
+
// In logical pixels, in the desktop's coordinates -- which is what an app can
|
|
31
|
+
// pass straight back to `setWindowPosition`. Not physical pixels: an app
|
|
32
|
+
// reasoning about its own layout is reasoning in the same units React Native
|
|
33
|
+
// lays out in.
|
|
34
|
+
double x{0.0};
|
|
35
|
+
double y{0.0};
|
|
36
|
+
double width{0.0};
|
|
37
|
+
double height{0.0};
|
|
38
|
+
|
|
39
|
+
// Distinct states, not one enum: a window can be maximised *and* full screen
|
|
40
|
+
// on every one of these desktops, and an app that restores a remembered
|
|
41
|
+
// layout needs to know which it was.
|
|
42
|
+
bool fullScreen{false};
|
|
43
|
+
bool maximized{false};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Where the window is now.
|
|
47
|
+
//
|
|
48
|
+
// **Called on the UI thread only.** Every one of these touches a GtkWindow, an
|
|
49
|
+
// NSWindow or an HWND, and none of those may be touched from the JavaScript
|
|
50
|
+
// thread -- which is where a TurboModule method arrives. `core/WindowMethods.h`
|
|
51
|
+
// is what marshals, so a platform implementation may assume it is already in
|
|
52
|
+
// the right place. Getting this wrong is quiet rather than loud: the AppKit
|
|
53
|
+
// resize simply did not happen, with no warning anywhere.
|
|
54
|
+
WindowBounds windowBounds();
|
|
55
|
+
|
|
56
|
+
void setWindowSize(double width, double height);
|
|
57
|
+
void setWindowPosition(double x, double y);
|
|
58
|
+
|
|
59
|
+
// Centred on the display the window is already on, which is not always the
|
|
60
|
+
// primary one.
|
|
61
|
+
void centerWindow();
|
|
62
|
+
|
|
63
|
+
void setWindowFullScreen(bool fullScreen);
|
|
64
|
+
|
|
65
|
+
// Called by the host whenever the window is resized, moved, or changes state.
|
|
66
|
+
//
|
|
67
|
+
// The module installs one of these and turns it into a device event, so that
|
|
68
|
+
// `useWindow()` can hand an app live bounds rather than a snapshot it has to
|
|
69
|
+
// remember to refresh. Replacing a listener drops the previous one; passing
|
|
70
|
+
// nothing removes it.
|
|
71
|
+
void setWindowBoundsListener(std::function<void(const WindowBounds &)> listener);
|
|
72
|
+
|
|
73
|
+
// The host's half of that: called from wherever it already learns the window
|
|
74
|
+
// moved or resized, on the UI thread. Also updates the cache below, so it is
|
|
75
|
+
// worth calling once when the window is first shown even if nothing is
|
|
76
|
+
// listening yet.
|
|
77
|
+
void notifyWindowBoundsChanged();
|
|
78
|
+
|
|
79
|
+
// How big the window is allowed to be, in logical pixels.
|
|
80
|
+
//
|
|
81
|
+
// Zero means "no limit" in either direction, which is the default and is also
|
|
82
|
+
// how an app clears one. Not part of `WindowBounds`: bounds are what the window
|
|
83
|
+
// *is* and these are what it may become, and an app restoring a remembered
|
|
84
|
+
// layout wants the first without being told the second.
|
|
85
|
+
struct WindowSizeLimits {
|
|
86
|
+
double minWidth{0.0};
|
|
87
|
+
double minHeight{0.0};
|
|
88
|
+
double maxWidth{0.0};
|
|
89
|
+
double maxHeight{0.0};
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Set the limits and apply them. Portable: the storing is identical everywhere
|
|
93
|
+
// and only `applyWindowSizeLimits` differs.
|
|
94
|
+
void setWindowMinimumSize(double width, double height);
|
|
95
|
+
void setWindowMaximumSize(double width, double height);
|
|
96
|
+
|
|
97
|
+
// What is in force, readable from any thread. Windows answers WM_GETMINMAXINFO
|
|
98
|
+
// from this, which is a message rather than a call and so cannot be given them.
|
|
99
|
+
WindowSizeLimits windowSizeLimits();
|
|
100
|
+
|
|
101
|
+
// Clamp a requested size to the limits this platform says it enforces.
|
|
102
|
+
//
|
|
103
|
+
// Portable, and applied before every `setWindowSize`, because the toolkits do
|
|
104
|
+
// not agree on whether a programmatic resize is subject to the same limits a
|
|
105
|
+
// dragged corner is. AppKit's `setFrame:` clamps down to the maximum and not up
|
|
106
|
+
// to the minimum, which is a resize that lands outside a limit an app set and
|
|
107
|
+
// the window manager would have refused -- found by the test for exactly that.
|
|
108
|
+
//
|
|
109
|
+
// Filtered by `windowCapabilities()` rather than applied unconditionally, so
|
|
110
|
+
// that what an app is told and what it gets stay the same thing: a desktop that
|
|
111
|
+
// reports `maximumSize: false` does not quietly enforce one here.
|
|
112
|
+
void constrainToWindowSizeLimits(double &width, double &height);
|
|
113
|
+
|
|
114
|
+
// Tell the window manager about the limits above. Called on the UI thread, with
|
|
115
|
+
// the new values already stored.
|
|
116
|
+
void applyWindowSizeLimits();
|
|
117
|
+
|
|
118
|
+
// Whether the person may resize the window at all.
|
|
119
|
+
void setWindowResizable(bool resizable);
|
|
120
|
+
|
|
121
|
+
// Whether it floats above other applications' windows. Not "above everything":
|
|
122
|
+
// no desktop lets an ordinary application outrank a screen lock or a system
|
|
123
|
+
// alert, and none of these ask it to.
|
|
124
|
+
void setWindowAlwaysOnTop(bool alwaysOnTop);
|
|
125
|
+
|
|
126
|
+
// Which of the above this desktop actually does.
|
|
127
|
+
//
|
|
128
|
+
// Answered rather than documented, because two of these are not gaps and will
|
|
129
|
+
// not be filled. GTK4 removed `gtk_window_set_geometry_hints` and
|
|
130
|
+
// `gtk_window_set_keep_above`, and Wayland has no protocol for either: a client
|
|
131
|
+
// there does not know where it is, does not place itself, and does not outrank
|
|
132
|
+
// its neighbours. An app that asks can put its "always on top" switch away on
|
|
133
|
+
// the platform that has no such thing, which is better than a switch that lies.
|
|
134
|
+
struct WindowCapabilities {
|
|
135
|
+
bool position{false};
|
|
136
|
+
bool minimumSize{false};
|
|
137
|
+
bool maximumSize{false};
|
|
138
|
+
bool resizable{false};
|
|
139
|
+
bool alwaysOnTop{false};
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
WindowCapabilities windowCapabilities();
|
|
143
|
+
|
|
144
|
+
// The last bounds the host reported, readable from any thread.
|
|
145
|
+
//
|
|
146
|
+
// `windowBounds()` cannot be: it asks the toolkit, and a TurboModule method
|
|
147
|
+
// runs on the JavaScript thread. So `getBounds()` answers from here, which is
|
|
148
|
+
// exact rather than approximate -- the host reports every change -- and needs
|
|
149
|
+
// no hop, which matters because it is read during render.
|
|
150
|
+
//
|
|
151
|
+
// All zeroes before the host has reported anything, which is what an app
|
|
152
|
+
// reading bounds during its first render sees.
|
|
153
|
+
WindowBounds lastKnownWindowBounds();
|
|
154
|
+
|
|
155
|
+
// --- The displays the desktop has -------------------------------------------
|
|
156
|
+
//
|
|
157
|
+
// React Native's `Dimensions` reports the window, which is the right answer to
|
|
158
|
+
// a different question: an app placing a window, or deciding how much it can
|
|
159
|
+
// show, is asking about the screen it is on and the ones beside it.
|
|
160
|
+
//
|
|
161
|
+
// The lookups already existed -- `NSScreen`, `GdkMonitor` and
|
|
162
|
+
// `MonitorFromWindow` are how `center()` and full screen work -- and were
|
|
163
|
+
// simply not passed on.
|
|
164
|
+
|
|
165
|
+
struct DisplayInfo {
|
|
166
|
+
// In the same logical pixels and the same desktop coordinates WindowBounds
|
|
167
|
+
// uses, so a bound and a display can be compared without converting either.
|
|
168
|
+
// Top-left origin on every host, which costs AppKit a flip: its own
|
|
169
|
+
// coordinates grow upwards from the primary screen.
|
|
170
|
+
double x{0.0};
|
|
171
|
+
double y{0.0};
|
|
172
|
+
double width{0.0};
|
|
173
|
+
double height{0.0};
|
|
174
|
+
|
|
175
|
+
// What is left after the desktop's own furniture -- a menu bar, a taskbar, a
|
|
176
|
+
// dock, a panel. Where a window should go; `bounds` is where the glass is.
|
|
177
|
+
// Equal to bounds on a desktop that reserves nothing.
|
|
178
|
+
double workX{0.0};
|
|
179
|
+
double workY{0.0};
|
|
180
|
+
double workWidth{0.0};
|
|
181
|
+
double workHeight{0.0};
|
|
182
|
+
|
|
183
|
+
// Physical pixels per logical pixel: 2 on a Retina display, 1 on an
|
|
184
|
+
// ordinary one, and fractional under Wayland or a Windows display set to
|
|
185
|
+
// 150%. Never zero -- a host that cannot answer reports 1, because a caller
|
|
186
|
+
// dividing by this should not have to check.
|
|
187
|
+
double scaleFactor{1.0};
|
|
188
|
+
|
|
189
|
+
// Exactly one display is primary, and it is the one the desktop's
|
|
190
|
+
// coordinates are anchored to.
|
|
191
|
+
bool primary{false};
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// Every display, primary first.
|
|
195
|
+
//
|
|
196
|
+
// **Called on the UI thread only**, like everything above it: each host asks
|
|
197
|
+
// its toolkit.
|
|
198
|
+
std::vector<DisplayInfo> displays();
|
|
199
|
+
|
|
200
|
+
// The last list the host reported, readable from any thread.
|
|
201
|
+
//
|
|
202
|
+
// The same arrangement `lastKnownWindowBounds` has, and for the same reason:
|
|
203
|
+
// `displays()` asks the toolkit and a TurboModule method runs on the
|
|
204
|
+
// JavaScript thread. Exact rather than approximate, because the host reports
|
|
205
|
+
// every change -- and empty before the host has reported anything, which is
|
|
206
|
+
// what an app asking during its first render sees.
|
|
207
|
+
std::vector<DisplayInfo> lastKnownDisplays();
|
|
208
|
+
|
|
209
|
+
// Where the pointer is, in the same coordinates the bounds above use.
|
|
210
|
+
//
|
|
211
|
+
// A display question rather than a window one: it may be over a different
|
|
212
|
+
// display than the app's window, or over no window at all. All zeroes on a
|
|
213
|
+
// host that cannot answer -- Wayland does not tell a client where the pointer
|
|
214
|
+
// is unless it is over one of its own surfaces.
|
|
215
|
+
struct PointerPosition {
|
|
216
|
+
double x{0.0};
|
|
217
|
+
double y{0.0};
|
|
218
|
+
// False where the desktop will not say, so that an app can tell "at the
|
|
219
|
+
// origin" from "not answered".
|
|
220
|
+
bool known{false};
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
PointerPosition pointerPosition();
|
|
224
|
+
|
|
225
|
+
// A monitor plugged in, unplugged, or rearranged.
|
|
226
|
+
//
|
|
227
|
+
// No argument: an app that cares re-reads the list, which is the only way to
|
|
228
|
+
// be right about several changes arriving together. Same shape as the window
|
|
229
|
+
// bounds listener above, and set by the module for the same reason.
|
|
230
|
+
void setDisplaysListener(std::function<void()> listener);
|
|
231
|
+
|
|
232
|
+
// The host's half: called on the UI thread when the arrangement changes.
|
|
233
|
+
void notifyDisplaysChanged();
|
|
234
|
+
|
|
235
|
+
} // namespace basalt
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// Opening a second window.
|
|
2
|
+
//
|
|
3
|
+
// Fabric has supported more than one surface all along -- `startSurface` takes
|
|
4
|
+
// a surface id, the mounting managers keep a root per id, and the error
|
|
5
|
+
// inspector has been a second surface since it was written. What has been
|
|
6
|
+
// missing is a second *window* to put one in: every host made exactly one, at
|
|
7
|
+
// startup, and everything in it reached for `the` window and `the` root.
|
|
8
|
+
//
|
|
9
|
+
// So this is the seam for the part that is genuinely per-toolkit -- making a
|
|
10
|
+
// window and wiring a surface into it -- and `core/WindowsModule.h` is the
|
|
11
|
+
// JavaScript boundary above it. The implementation lives in each host's
|
|
12
|
+
// `main_*.cpp` rather than beside the other platform services, because that is
|
|
13
|
+
// where a window is made and where the ReactHost that starts a surface lives.
|
|
14
|
+
//
|
|
15
|
+
// ## A window is a surface
|
|
16
|
+
//
|
|
17
|
+
// One window, one surface, one React root. That is Fabric's grain rather than a
|
|
18
|
+
// simplification: a surface is what has a size, a layout context and a root
|
|
19
|
+
// shadow node, and two windows sharing one would be two windows sharing a
|
|
20
|
+
// layout. It is also why the id a window is identified by *is* its surface id
|
|
21
|
+
// -- there is no second numbering to keep in step.
|
|
22
|
+
//
|
|
23
|
+
// The cost is that a second window is a second React tree: it does not share
|
|
24
|
+
// context, state or a render pass with the first. `<Window>` in JavaScript
|
|
25
|
+
// papers over enough of that to be useful and says where it cannot; see
|
|
26
|
+
// src/Window.js.
|
|
27
|
+
|
|
28
|
+
#pragma once
|
|
29
|
+
|
|
30
|
+
#include <folly/dynamic.h>
|
|
31
|
+
|
|
32
|
+
#include <functional>
|
|
33
|
+
#include <react/renderer/core/ReactPrimitives.h>
|
|
34
|
+
|
|
35
|
+
#include <string>
|
|
36
|
+
#include <vector>
|
|
37
|
+
|
|
38
|
+
namespace basalt {
|
|
39
|
+
|
|
40
|
+
struct NewWindowOptions {
|
|
41
|
+
// The component to run, as registered with `AppRegistry.registerComponent`.
|
|
42
|
+
// A window with no component is a window with nothing in it, which is not
|
|
43
|
+
// something to open by accident: an empty one is refused.
|
|
44
|
+
std::string component;
|
|
45
|
+
std::string title;
|
|
46
|
+
double width{900.0};
|
|
47
|
+
double height{700.0};
|
|
48
|
+
// `initialProps`, which is how the second React root is told which window it
|
|
49
|
+
// is. See src/Window.js.
|
|
50
|
+
folly::dynamic props{folly::dynamic::object()};
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Opens a window and starts `component` in it. Returns the new surface id,
|
|
54
|
+
// which is also the window's, or 0 if it could not.
|
|
55
|
+
//
|
|
56
|
+
// Called on the UI thread.
|
|
57
|
+
facebook::react::SurfaceId openHostWindow(const NewWindowOptions &options);
|
|
58
|
+
|
|
59
|
+
// Closes a window opened by `openHostWindow` and stops its surface. Ignores the
|
|
60
|
+
// main window: an app closing the window it is running in should say so through
|
|
61
|
+
// `close()` on the window itself, which is a different thing from destroying a
|
|
62
|
+
// surface out from under a React tree.
|
|
63
|
+
//
|
|
64
|
+
// Called on the UI thread.
|
|
65
|
+
void closeHostWindow(facebook::react::SurfaceId surfaceId);
|
|
66
|
+
|
|
67
|
+
// Ends the application: `[NSApp terminate:]`, `g_application_quit`,
|
|
68
|
+
// `PostQuitMessage`. What `quit()` reaches, and what a quit handler calls
|
|
69
|
+
// when its answer is "go ahead" -- an app that intercepted the quit refused
|
|
70
|
+
// the one the system asked for, so somebody has to ask again.
|
|
71
|
+
//
|
|
72
|
+
// Called on the UI thread.
|
|
73
|
+
void quitHost();
|
|
74
|
+
|
|
75
|
+
// Every window this host has open, main window first. For the tree dump, and
|
|
76
|
+
// for an app asking what it has.
|
|
77
|
+
std::vector<facebook::react::SurfaceId> hostWindows();
|
|
78
|
+
|
|
79
|
+
// A window was closed by the person rather than by the app -- its own close
|
|
80
|
+
// button, or the window manager.
|
|
81
|
+
//
|
|
82
|
+
// This is not a nicety. Without it the host is left holding a record whose
|
|
83
|
+
// window is gone, which is a dangling pointer rather than a stale flag, and the
|
|
84
|
+
// `<Window>` that opened it goes on believing it is open: the app's state says
|
|
85
|
+
// one thing and the screen says another, and the next render tries to close a
|
|
86
|
+
// window that has already closed itself.
|
|
87
|
+
//
|
|
88
|
+
// So the host calls `hostWindowClosed` on the way out, and the module turns it
|
|
89
|
+
// into a device event that `<Window>` unmounts on.
|
|
90
|
+
void setHostWindowClosedListener(std::function<void(facebook::react::SurfaceId)> listener);
|
|
91
|
+
|
|
92
|
+
// The host's half: called on the UI thread, before the record is dropped.
|
|
93
|
+
void hostWindowClosed(facebook::react::SurfaceId surfaceId);
|
|
94
|
+
|
|
95
|
+
// ## Refusing to close
|
|
96
|
+
//
|
|
97
|
+
// The above is a window that *has* closed. This is a window somebody is trying
|
|
98
|
+
// to close, which is a different question with a different answer: an app with
|
|
99
|
+
// unsaved work wants to ask before it goes, and by the time `hostWindowClosed`
|
|
100
|
+
// runs there is nothing left to ask about.
|
|
101
|
+
//
|
|
102
|
+
// Electron spells this `event.preventDefault()` in a `close` handler, and can,
|
|
103
|
+
// because its handler runs in the main process and the answer is available the
|
|
104
|
+
// moment the event is raised. Here the answer lives in JavaScript, on another
|
|
105
|
+
// thread, and the window manager wants a synchronous yes or no -- so the
|
|
106
|
+
// decision has to be made *before* the attempt rather than during it.
|
|
107
|
+
//
|
|
108
|
+
// Hence a flag rather than a callback. An app that registers a close handler
|
|
109
|
+
// marks its window intercepted; the host then refuses every close the window
|
|
110
|
+
// manager asks for and reports the attempt instead, and the app closes the
|
|
111
|
+
// window itself when it is ready. A window with no handler is not marked and
|
|
112
|
+
// closes exactly as it did before -- which matters, because that is every
|
|
113
|
+
// window, and a close path that waits on JavaScript to say "go ahead" would be
|
|
114
|
+
// a window that does not close when the runtime is busy.
|
|
115
|
+
void setHostWindowCloseIntercepted(facebook::react::SurfaceId surfaceId, bool intercepted);
|
|
116
|
+
|
|
117
|
+
// Whether this window refuses the window manager. Called on the UI thread from
|
|
118
|
+
// inside a close handler, which is why it may not hop to ask anybody.
|
|
119
|
+
bool hostWindowCloseIntercepted(facebook::react::SurfaceId surfaceId);
|
|
120
|
+
|
|
121
|
+
// Somebody tried to close a window that is intercepted, and it did not close.
|
|
122
|
+
// The module turns this into a device event; the app decides what to do and
|
|
123
|
+
// calls `close()` if that is "go ahead".
|
|
124
|
+
void setHostWindowCloseRequestListener(std::function<void(facebook::react::SurfaceId)> listener);
|
|
125
|
+
|
|
126
|
+
// The host's half: called on the UI thread, instead of closing.
|
|
127
|
+
void hostWindowCloseRequested(facebook::react::SurfaceId surfaceId);
|
|
128
|
+
|
|
129
|
+
// ## Refusing to quit
|
|
130
|
+
//
|
|
131
|
+
// The same question about the application rather than about one window, and
|
|
132
|
+
// not answerable by the above: an app can guard every window it owns and
|
|
133
|
+
// still lose the person's work to Cmd-Q. macOS routes quitting through
|
|
134
|
+
// `applicationShouldTerminate:` and asks no window whether it minds; the
|
|
135
|
+
// Windows and GNOME session-end signals do the same.
|
|
136
|
+
//
|
|
137
|
+
// A flag rather than a callback, for exactly the reason the close case is:
|
|
138
|
+
// the system wants a synchronous yes or no and the answer lives in
|
|
139
|
+
// JavaScript on another thread. An app that registers a quit handler marks
|
|
140
|
+
// the application intercepted; the host then refuses the quit and reports
|
|
141
|
+
// the attempt, and the app quits itself when it is ready.
|
|
142
|
+
//
|
|
143
|
+
// One flag rather than one per window, because quitting is one event no
|
|
144
|
+
// matter how many windows are open -- and because the last window closing is
|
|
145
|
+
// already a different thing that already works.
|
|
146
|
+
void setHostQuitIntercepted(bool intercepted);
|
|
147
|
+
|
|
148
|
+
// Whether the application refuses to quit. Called on the UI thread from
|
|
149
|
+
// inside a terminate handler, which is why it may not hop to ask anybody.
|
|
150
|
+
bool hostQuitIntercepted();
|
|
151
|
+
|
|
152
|
+
// Somebody tried to quit an intercepted application, and it did not quit.
|
|
153
|
+
void setHostQuitRequestListener(std::function<void()> listener);
|
|
154
|
+
|
|
155
|
+
// The host's half: called on the UI thread, instead of quitting.
|
|
156
|
+
void hostQuitRequested();
|
|
157
|
+
|
|
158
|
+
} // namespace basalt
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#include "WindowMethods.h"
|
|
2
|
+
|
|
3
|
+
#include "PlatformServices.h"
|
|
4
|
+
#include "WindowControl.h"
|
|
5
|
+
|
|
6
|
+
#include <mutex>
|
|
7
|
+
|
|
8
|
+
namespace basalt {
|
|
9
|
+
|
|
10
|
+
namespace {
|
|
11
|
+
|
|
12
|
+
using facebook::jsi::Object;
|
|
13
|
+
using facebook::jsi::Runtime;
|
|
14
|
+
using facebook::jsi::Value;
|
|
15
|
+
using facebook::react::TurboModule;
|
|
16
|
+
|
|
17
|
+
bool twoNumbers(const Value *args, size_t count) {
|
|
18
|
+
return count >= 2 && args[0].isNumber() && args[1].isNumber();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Everything that changes a window happens on the UI thread.
|
|
22
|
+
//
|
|
23
|
+
// A TurboModule method runs on the JavaScript thread, and none of the three
|
|
24
|
+
// toolkits may be touched from it. This was found the loud way and reported the
|
|
25
|
+
// quiet way: `setSize` from JavaScript did nothing at all on macOS, with no
|
|
26
|
+
// warning and no crash.
|
|
27
|
+
void onUiThread(std::function<void()> work) {
|
|
28
|
+
postToUiThread(std::move(work));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
} // namespace
|
|
32
|
+
|
|
33
|
+
Value windowSetSize(Runtime & /*runtime*/,
|
|
34
|
+
TurboModule & /*module*/,
|
|
35
|
+
const Value *args,
|
|
36
|
+
size_t count) {
|
|
37
|
+
if (twoNumbers(args, count)) {
|
|
38
|
+
const double first = args[0].asNumber();
|
|
39
|
+
const double second = args[1].asNumber();
|
|
40
|
+
onUiThread([first, second] {
|
|
41
|
+
// Clamped here rather than left to the toolkit, which is the only way the
|
|
42
|
+
// three agree. See core/WindowControl.h.
|
|
43
|
+
double width = first;
|
|
44
|
+
double height = second;
|
|
45
|
+
constrainToWindowSizeLimits(width, height);
|
|
46
|
+
setWindowSize(width, height);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return Value::undefined();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Value windowSetPosition(Runtime & /*runtime*/,
|
|
53
|
+
TurboModule & /*module*/,
|
|
54
|
+
const Value *args,
|
|
55
|
+
size_t count) {
|
|
56
|
+
if (twoNumbers(args, count)) {
|
|
57
|
+
const double first = args[0].asNumber();
|
|
58
|
+
const double second = args[1].asNumber();
|
|
59
|
+
onUiThread([first, second] { setWindowPosition(first, second); });
|
|
60
|
+
}
|
|
61
|
+
return Value::undefined();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Value windowCenter(Runtime & /*runtime*/,
|
|
65
|
+
TurboModule & /*module*/,
|
|
66
|
+
const Value * /*args*/,
|
|
67
|
+
size_t /*count*/) {
|
|
68
|
+
onUiThread([] { centerWindow(); });
|
|
69
|
+
return Value::undefined();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Value windowSetFullScreen(Runtime & /*runtime*/,
|
|
73
|
+
TurboModule & /*module*/,
|
|
74
|
+
const Value *args,
|
|
75
|
+
size_t count) {
|
|
76
|
+
// Anything but a boolean is ignored rather than coerced: `setFullScreen()`
|
|
77
|
+
// with no argument reads as "make it full screen" to a JavaScript truthiness
|
|
78
|
+
// check and as a mistake to everyone else.
|
|
79
|
+
if (count >= 1 && args[0].isBool()) {
|
|
80
|
+
const bool fullScreen = args[0].asBool();
|
|
81
|
+
onUiThread([fullScreen] { setWindowFullScreen(fullScreen); });
|
|
82
|
+
}
|
|
83
|
+
return Value::undefined();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Value windowSetMinimumSize(Runtime & /*runtime*/,
|
|
87
|
+
TurboModule & /*module*/,
|
|
88
|
+
const Value *args,
|
|
89
|
+
size_t count) {
|
|
90
|
+
if (twoNumbers(args, count)) {
|
|
91
|
+
const double width = args[0].asNumber();
|
|
92
|
+
const double height = args[1].asNumber();
|
|
93
|
+
// The store is portable and thread-safe; what needs the UI thread is the
|
|
94
|
+
// applying, which is why the hop wraps the whole call rather than half of
|
|
95
|
+
// it. See core/WindowControl.h.
|
|
96
|
+
onUiThread([width, height] { setWindowMinimumSize(width, height); });
|
|
97
|
+
}
|
|
98
|
+
return Value::undefined();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
Value windowSetMaximumSize(Runtime & /*runtime*/,
|
|
102
|
+
TurboModule & /*module*/,
|
|
103
|
+
const Value *args,
|
|
104
|
+
size_t count) {
|
|
105
|
+
if (twoNumbers(args, count)) {
|
|
106
|
+
const double width = args[0].asNumber();
|
|
107
|
+
const double height = args[1].asNumber();
|
|
108
|
+
onUiThread([width, height] { setWindowMaximumSize(width, height); });
|
|
109
|
+
}
|
|
110
|
+
return Value::undefined();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
Value windowSetResizable(Runtime & /*runtime*/,
|
|
114
|
+
TurboModule & /*module*/,
|
|
115
|
+
const Value *args,
|
|
116
|
+
size_t count) {
|
|
117
|
+
if (count >= 1 && args[0].isBool()) {
|
|
118
|
+
const bool resizable = args[0].asBool();
|
|
119
|
+
onUiThread([resizable] { setWindowResizable(resizable); });
|
|
120
|
+
}
|
|
121
|
+
return Value::undefined();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
Value windowSetAlwaysOnTop(Runtime & /*runtime*/,
|
|
125
|
+
TurboModule & /*module*/,
|
|
126
|
+
const Value *args,
|
|
127
|
+
size_t count) {
|
|
128
|
+
if (count >= 1 && args[0].isBool()) {
|
|
129
|
+
const bool onTop = args[0].asBool();
|
|
130
|
+
onUiThread([onTop] { setWindowAlwaysOnTop(onTop); });
|
|
131
|
+
}
|
|
132
|
+
return Value::undefined();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
Value windowGetCapabilities(Runtime &runtime,
|
|
136
|
+
TurboModule & /*module*/,
|
|
137
|
+
const Value * /*args*/,
|
|
138
|
+
size_t /*count*/) {
|
|
139
|
+
const WindowCapabilities capabilities = windowCapabilities();
|
|
140
|
+
Object result(runtime);
|
|
141
|
+
result.setProperty(runtime, "position", capabilities.position);
|
|
142
|
+
result.setProperty(runtime, "minimumSize", capabilities.minimumSize);
|
|
143
|
+
result.setProperty(runtime, "maximumSize", capabilities.maximumSize);
|
|
144
|
+
result.setProperty(runtime, "resizable", capabilities.resizable);
|
|
145
|
+
result.setProperty(runtime, "alwaysOnTop", capabilities.alwaysOnTop);
|
|
146
|
+
return Value(runtime, result);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
Value windowGetBounds(Runtime &runtime,
|
|
150
|
+
TurboModule & /*module*/,
|
|
151
|
+
const Value * /*args*/,
|
|
152
|
+
size_t /*count*/) {
|
|
153
|
+
// From the cache rather than from the toolkit: this runs on the JavaScript
|
|
154
|
+
// thread, and it is read during render, so it can neither ask AppKit nor wait
|
|
155
|
+
// for a hop. The host reports every change, so the cache is exact.
|
|
156
|
+
const WindowBounds bounds = lastKnownWindowBounds();
|
|
157
|
+
Object object(runtime);
|
|
158
|
+
object.setProperty(runtime, "x", bounds.x);
|
|
159
|
+
object.setProperty(runtime, "y", bounds.y);
|
|
160
|
+
object.setProperty(runtime, "width", bounds.width);
|
|
161
|
+
object.setProperty(runtime, "height", bounds.height);
|
|
162
|
+
object.setProperty(runtime, "fullScreen", bounds.fullScreen);
|
|
163
|
+
object.setProperty(runtime, "maximized", bounds.maximized);
|
|
164
|
+
return Value(runtime, object);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
} // namespace basalt
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// The JavaScript boundary for a window's geometry, written once.
|
|
2
|
+
//
|
|
3
|
+
// Each host's `BasaltWindow` module registers these beside its own title-bar
|
|
4
|
+
// methods. They are free functions with the signature a TurboModule method has,
|
|
5
|
+
// so a host installs one with a line:
|
|
6
|
+
//
|
|
7
|
+
// methodMap_["setSize"] = MethodMetadata{2, basalt::windowSetSize};
|
|
8
|
+
//
|
|
9
|
+
// Everything they do is in core/WindowControl.h, which is the part that differs
|
|
10
|
+
// per platform. Nothing here is per-platform at all, which is why it is not
|
|
11
|
+
// written three times -- the reading of arguments and the shape of the answer
|
|
12
|
+
// are exactly the things three copies would drift on.
|
|
13
|
+
|
|
14
|
+
#pragma once
|
|
15
|
+
|
|
16
|
+
#include <ReactCommon/TurboModule.h>
|
|
17
|
+
|
|
18
|
+
namespace basalt {
|
|
19
|
+
|
|
20
|
+
// `setSize(width, height)`. Ignores a call with anything but two numbers, which
|
|
21
|
+
// is what a JavaScript caller passing undefined looks like.
|
|
22
|
+
facebook::jsi::Value windowSetSize(facebook::jsi::Runtime &runtime,
|
|
23
|
+
facebook::react::TurboModule &module,
|
|
24
|
+
const facebook::jsi::Value *args,
|
|
25
|
+
size_t count);
|
|
26
|
+
|
|
27
|
+
// `setPosition(x, y)`, in the desktop's coordinates.
|
|
28
|
+
facebook::jsi::Value windowSetPosition(facebook::jsi::Runtime &runtime,
|
|
29
|
+
facebook::react::TurboModule &module,
|
|
30
|
+
const facebook::jsi::Value *args,
|
|
31
|
+
size_t count);
|
|
32
|
+
|
|
33
|
+
// `center()`, on whichever display the window is already on.
|
|
34
|
+
facebook::jsi::Value windowCenter(facebook::jsi::Runtime &runtime,
|
|
35
|
+
facebook::react::TurboModule &module,
|
|
36
|
+
const facebook::jsi::Value *args,
|
|
37
|
+
size_t count);
|
|
38
|
+
|
|
39
|
+
// `setFullScreen(boolean)`.
|
|
40
|
+
facebook::jsi::Value windowSetFullScreen(facebook::jsi::Runtime &runtime,
|
|
41
|
+
facebook::react::TurboModule &module,
|
|
42
|
+
const facebook::jsi::Value *args,
|
|
43
|
+
size_t count);
|
|
44
|
+
|
|
45
|
+
// `setMinimumSize(width, height)` and `setMaximumSize(width, height)`. Zero in
|
|
46
|
+
// either direction clears that limit.
|
|
47
|
+
facebook::jsi::Value windowSetMinimumSize(facebook::jsi::Runtime &runtime,
|
|
48
|
+
facebook::react::TurboModule &module,
|
|
49
|
+
const facebook::jsi::Value *args,
|
|
50
|
+
size_t count);
|
|
51
|
+
facebook::jsi::Value windowSetMaximumSize(facebook::jsi::Runtime &runtime,
|
|
52
|
+
facebook::react::TurboModule &module,
|
|
53
|
+
const facebook::jsi::Value *args,
|
|
54
|
+
size_t count);
|
|
55
|
+
|
|
56
|
+
// `setResizable(boolean)` and `setAlwaysOnTop(boolean)`.
|
|
57
|
+
facebook::jsi::Value windowSetResizable(facebook::jsi::Runtime &runtime,
|
|
58
|
+
facebook::react::TurboModule &module,
|
|
59
|
+
const facebook::jsi::Value *args,
|
|
60
|
+
size_t count);
|
|
61
|
+
facebook::jsi::Value windowSetAlwaysOnTop(facebook::jsi::Runtime &runtime,
|
|
62
|
+
facebook::react::TurboModule &module,
|
|
63
|
+
const facebook::jsi::Value *args,
|
|
64
|
+
size_t count);
|
|
65
|
+
|
|
66
|
+
// `getCapabilities()` -> which of the above this desktop does. Read during
|
|
67
|
+
// render, so it answers without a thread hop -- it is five booleans a platform
|
|
68
|
+
// knows at compile time, not a question for the window manager.
|
|
69
|
+
facebook::jsi::Value windowGetCapabilities(facebook::jsi::Runtime &runtime,
|
|
70
|
+
facebook::react::TurboModule &module,
|
|
71
|
+
const facebook::jsi::Value *args,
|
|
72
|
+
size_t count);
|
|
73
|
+
|
|
74
|
+
// `getBounds()` -> `{x, y, width, height, fullScreen, maximized}`.
|
|
75
|
+
facebook::jsi::Value windowGetBounds(facebook::jsi::Runtime &runtime,
|
|
76
|
+
facebook::react::TurboModule &module,
|
|
77
|
+
const facebook::jsi::Value *args,
|
|
78
|
+
size_t count);
|
|
79
|
+
|
|
80
|
+
// The device event `useWindow()` listens for. Named here so the two sides
|
|
81
|
+
// cannot drift.
|
|
82
|
+
inline constexpr const char *kWindowBoundsEvent = "basaltWindowBoundsChanged";
|
|
83
|
+
|
|
84
|
+
} // namespace basalt
|