basalt-win32 0.0.0-stage → 0.2.0
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/cli/runWindows.js +35 -0
- package/cli/shared.js +75 -0
- package/native/CMakeLists.txt +429 -0
- package/native/tests/test_win32_accessibility.cpp +585 -0
- package/native/tests/test_win32_animated_image.cpp +351 -0
- package/native/tests/test_win32_clipboard.cpp +121 -0
- package/native/tests/test_win32_focus.cpp +195 -0
- package/native/tests/test_win32_hittest.cpp +750 -0
- package/native/tests/test_win32_image.cpp +370 -0
- package/native/tests/test_win32_imageloader.cpp +208 -0
- package/native/tests/test_win32_input.cpp +511 -0
- package/native/tests/test_win32_key_events.cpp +84 -0
- package/native/tests/test_win32_mounting.cpp +757 -0
- package/native/tests/test_win32_paint.cpp +1799 -0
- package/native/tests/test_win32_scrollview.cpp +647 -0
- package/native/tests/test_win32_selection.cpp +215 -0
- package/native/tests/test_win32_text.cpp +1456 -0
- package/native/tests/test_win32_textinput.cpp +1594 -0
- package/native/tests/test_win32_titlebar.cpp +111 -0
- package/native/tests/test_win32_titlebar_actions.cpp +62 -0
- package/native/tests/test_win32_view.cpp +222 -0
- package/native/win32/ColorSchemeWin32.cpp +56 -0
- package/native/win32/ComponentRegistryWin32.cpp +156 -0
- package/native/win32/DirectWriteLayout.cpp +485 -0
- package/native/win32/DirectWriteLayout.h +77 -0
- package/native/win32/DirectWriteLayoutManager.cpp +154 -0
- package/native/win32/FontRegistryDirectWrite.cpp +117 -0
- package/native/win32/PlatformServicesWin32.cpp +744 -0
- package/native/win32/RnWin32Accessible.cpp +343 -0
- package/native/win32/RnWin32Accessible.h +130 -0
- package/native/win32/RnWin32Image.cpp +588 -0
- package/native/win32/RnWin32Image.h +139 -0
- package/native/win32/RnWin32TextLayout.cpp +1379 -0
- package/native/win32/RnWin32TextLayout.h +390 -0
- package/native/win32/RnWin32View.cpp +2956 -0
- package/native/win32/RnWin32View.h +926 -0
- package/native/win32/Win32AnimationChoreographer.cpp +76 -0
- package/native/win32/Win32AnimationChoreographer.h +61 -0
- package/native/win32/Win32Clip.h +209 -0
- package/native/win32/Win32Cursors.cpp +309 -0
- package/native/win32/Win32Cursors.h +121 -0
- package/native/win32/Win32DropTarget.cpp +567 -0
- package/native/win32/Win32DropTarget.h +42 -0
- package/native/win32/Win32Focus.cpp +262 -0
- package/native/win32/Win32Focus.h +109 -0
- package/native/win32/Win32ImageLoader.cpp +199 -0
- package/native/win32/Win32ImageLoader.h +133 -0
- package/native/win32/Win32InputScopes.h +92 -0
- package/native/win32/Win32KeyEvents.cpp +126 -0
- package/native/win32/Win32KeyEvents.h +20 -0
- package/native/win32/Win32MenuBar.cpp +382 -0
- package/native/win32/Win32MenuBar.h +16 -0
- package/native/win32/Win32MountingManager.cpp +1282 -0
- package/native/win32/Win32MountingManager.h +243 -0
- package/native/win32/Win32Offscreen.h +53 -0
- package/native/win32/Win32Packaging.cpp +161 -0
- package/native/win32/Win32Packaging.h +56 -0
- package/native/win32/Win32RunLoopObserver.cpp +48 -0
- package/native/win32/Win32RunLoopObserver.h +42 -0
- package/native/win32/Win32ScrollView.cpp +718 -0
- package/native/win32/Win32ScrollView.h +256 -0
- package/native/win32/Win32SkiaContext.cpp +221 -0
- package/native/win32/Win32SkiaContext.h +53 -0
- package/native/win32/Win32SkiaModule.cpp +80 -0
- package/native/win32/Win32SkiaModule.h +50 -0
- package/native/win32/Win32SkiaPeer.cpp +358 -0
- package/native/win32/Win32SkiaPeer.h +66 -0
- package/native/win32/Win32SkiaUnicode.cpp +42 -0
- package/native/win32/Win32Snapshot.cpp +201 -0
- package/native/win32/Win32Snapshot.h +66 -0
- package/native/win32/Win32Strings.h +54 -0
- package/native/win32/Win32TextInput.cpp +1296 -0
- package/native/win32/Win32TextInput.h +341 -0
- package/native/win32/Win32TitleBar.cpp +562 -0
- package/native/win32/Win32TitleBar.h +146 -0
- package/native/win32/Win32TitleBarLayout.cpp +46 -0
- package/native/win32/Win32TitleBarLayout.h +58 -0
- package/native/win32/Win32TouchDispatcher.cpp +577 -0
- package/native/win32/Win32TouchDispatcher.h +201 -0
- package/native/win32/Win32UiThread.h +27 -0
- package/native/win32/Win32WindowControl.cpp +329 -0
- package/native/win32/Win32WindowModule.cpp +209 -0
- package/native/win32/Win32WindowModule.h +72 -0
- package/native/win32/demo_layout_win32.cpp +232 -0
- package/native/win32/main_win32.cpp +2722 -0
- package/native/win32/mount_harness_win32.cpp +316 -0
- package/package.json +25 -4
- package/react-native.config.js +22 -0
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vince Vella
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `react-native run-windows`.
|
|
3
|
+
*
|
|
4
|
+
* Four strings and a path. Everything a desktop run actually does is in
|
|
5
|
+
* basalt-core's cli/desktop.js, shared with `run-linux` and
|
|
6
|
+
* `run-macos`, because none of it is about a toolkit -- see the note at the top
|
|
7
|
+
* of that file.
|
|
8
|
+
*
|
|
9
|
+
* The command name is react-native-windows', deliberately: an app that already
|
|
10
|
+
* knows `react-native run-windows` should not have to learn a second spelling
|
|
11
|
+
* to try this one. Same argument as the `windows` platform name.
|
|
12
|
+
*
|
|
13
|
+
* @format
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// @ts-check
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
const {shared, sharedPackageDir} = require('./shared');
|
|
22
|
+
|
|
23
|
+
const {makeRunCommand} = shared('cli/desktop');
|
|
24
|
+
|
|
25
|
+
module.exports = makeRunCommand({
|
|
26
|
+
platform: 'windows',
|
|
27
|
+
label: 'Windows',
|
|
28
|
+
command: 'run-windows',
|
|
29
|
+
binary: 'basalt_win32.exe',
|
|
30
|
+
nativeDir: path.resolve(__dirname, '..', 'native'),
|
|
31
|
+
coreDir: path.join(sharedPackageDir(), 'native'),
|
|
32
|
+
toolchain:
|
|
33
|
+
'the Visual Studio Build Tools with clang-cl, a Git Bash to run bootstrap.sh in, ' +
|
|
34
|
+
'and a vcpkg with glog, fmt, double-conversion, boost, gflags, openssl and curl',
|
|
35
|
+
});
|
package/cli/shared.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reaching basalt-core, the shared half, from this package.
|
|
3
|
+
*
|
|
4
|
+
* The one file in a platform package's CLI that cannot itself be shared,
|
|
5
|
+
* because it is what finds the thing everything else is shared through. Two
|
|
6
|
+
* layouts matter and only one of them resolves by name.
|
|
7
|
+
*
|
|
8
|
+
* Installed into an app, basalt-core is a sibling in node_modules and
|
|
9
|
+
* `require('basalt-core/...')` finds it. In a checkout of this
|
|
10
|
+
* repository the two packages are sibling directories with nothing installed
|
|
11
|
+
* between them -- deliberately, since this repo has no node_modules of its own
|
|
12
|
+
* -- and the same require fails. So: by name first, because that is the layout
|
|
13
|
+
* an app is in, and beside us second, because that is the layout it is
|
|
14
|
+
* developed in.
|
|
15
|
+
*
|
|
16
|
+
* Both reach the *built* package. basalt-core is TypeScript: by name
|
|
17
|
+
* resolves through its `exports` map, which points into `dist/`, and the
|
|
18
|
+
* sibling path has to say so itself. A checkout that has not run
|
|
19
|
+
* scripts/build_ts.sh has nothing here to find, which is what the error says.
|
|
20
|
+
*
|
|
21
|
+
* @format
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// @ts-check
|
|
25
|
+
'use strict';
|
|
26
|
+
|
|
27
|
+
const path = require('path');
|
|
28
|
+
|
|
29
|
+
const SIBLING = path.resolve(__dirname, '..', '..', 'basalt-core');
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Where basalt-core is on disk. Same two layouts, same order.
|
|
33
|
+
* @returns {string}
|
|
34
|
+
*/
|
|
35
|
+
function sharedPackageDir() {
|
|
36
|
+
try {
|
|
37
|
+
return path.dirname(require.resolve('basalt-core/package.json'));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (/** @type {NodeJS.ErrnoException} */ (error).code !== 'MODULE_NOT_FOUND') {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
return SIBLING;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* One of basalt-core's modules, by subpath.
|
|
48
|
+
* @param {string} subpath
|
|
49
|
+
* @returns {any}
|
|
50
|
+
*/
|
|
51
|
+
function shared(subpath) {
|
|
52
|
+
const name = `basalt-core/${subpath}`;
|
|
53
|
+
try {
|
|
54
|
+
return require(name);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (/** @type {NodeJS.ErrnoException} */ (error).code !== 'MODULE_NOT_FOUND') {
|
|
57
|
+
// The module was found and threw on its way up. Passing it through keeps
|
|
58
|
+
// a real error in that file from being reported as a missing package.
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
return require(path.join(SIBLING, 'dist', subpath));
|
|
63
|
+
} catch (siblingError) {
|
|
64
|
+
if (/** @type {NodeJS.ErrnoException} */ (siblingError).code === 'MODULE_NOT_FOUND') {
|
|
65
|
+
throw new Error(
|
|
66
|
+
`could not load ${name}. In a checkout, basalt-core has to be ` +
|
|
67
|
+
'built first: run scripts/build_ts.sh.',
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
throw siblingError;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {shared, sharedPackageDir};
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# basalt-win32 — the Windows view layer, over Win32 and Direct2D.
|
|
2
|
+
#
|
|
3
|
+
# A view layer, a mounting manager and a host. Everything behind them is in
|
|
4
|
+
# basalt-core, which this adds as a subdirectory.
|
|
5
|
+
#
|
|
6
|
+
# `win32/` rather than `windows/`: the toolkit is what differs, and the name
|
|
7
|
+
# would be wrong the moment WinUI or something after it mattered. The npm
|
|
8
|
+
# package is `-win32` for the same reason `-appkit` is not `-macos`, and neither
|
|
9
|
+
# name is the JavaScript platform's -- that one is `windows`, matching
|
|
10
|
+
# react-native-windows, and lives in the shared package.
|
|
11
|
+
|
|
12
|
+
cmake_minimum_required(VERSION 3.13)
|
|
13
|
+
project(basalt_win32 CXX)
|
|
14
|
+
|
|
15
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
16
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
17
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
18
|
+
|
|
19
|
+
# Executables at the top of the build tree whether this is configured directly
|
|
20
|
+
# or added by a wrapper, so `build/basalt_win32` means the same thing either
|
|
21
|
+
# way. Every script and document here names that path.
|
|
22
|
+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
|
23
|
+
# ...including under the multi-config generators, which are the default on
|
|
24
|
+
# Windows: Visual Studio and Ninja Multi-Config both append Debug/ or Release/
|
|
25
|
+
# to the directory above unless told otherwise, and a document that says
|
|
26
|
+
# `build/basalt_win32_tests` would be wrong on the platform it was written for.
|
|
27
|
+
foreach(config ${CMAKE_CONFIGURATION_TYPES})
|
|
28
|
+
string(TOUPPER ${config} config_upper)
|
|
29
|
+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config_upper} ${CMAKE_BINARY_DIR})
|
|
30
|
+
endforeach()
|
|
31
|
+
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
# Finding basalt-core, the shared half.
|
|
34
|
+
#
|
|
35
|
+
# The default works in both layouts this can be built from: a checkout of this
|
|
36
|
+
# repository, where the packages are siblings under packages/, and an app's
|
|
37
|
+
# node_modules, where npm hoists them side by side.
|
|
38
|
+
#
|
|
39
|
+
# Guarded on the target rather than on the variable: a build that configures
|
|
40
|
+
# more than one platform package would otherwise add the same directory twice,
|
|
41
|
+
# which CMake refuses.
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
if(NOT TARGET basalt_core)
|
|
44
|
+
if(NOT DEFINED BASALT_CORE_DIR)
|
|
45
|
+
set(BASALT_CORE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../basalt-core/native)
|
|
46
|
+
endif()
|
|
47
|
+
get_filename_component(BASALT_CORE_DIR "${BASALT_CORE_DIR}" ABSOLUTE)
|
|
48
|
+
if(NOT EXISTS ${BASALT_CORE_DIR}/CMakeLists.txt)
|
|
49
|
+
message(FATAL_ERROR
|
|
50
|
+
"basalt-core not found at ${BASALT_CORE_DIR}.\n"
|
|
51
|
+
"Pass -DBASALT_CORE_DIR=<path to basalt-core/native>.")
|
|
52
|
+
endif()
|
|
53
|
+
# Capability packages first, and only here, because they contribute include
|
|
54
|
+
# directories to basalt_core and CMake resolves those when the target is
|
|
55
|
+
# created rather than afterwards.
|
|
56
|
+
#
|
|
57
|
+
# This used to live only in the repository's root CMakeLists, which is the
|
|
58
|
+
# entry point for a checkout and is not the entry point for an app: the CLI
|
|
59
|
+
# configures -S <host package>/native, so the loop never ran and
|
|
60
|
+
# core/portability_probe.cpp failed on a Notifications.h that nothing had
|
|
61
|
+
# put on the path. A checkout could not see it, because there the root added
|
|
62
|
+
# the packages first and the header was always there.
|
|
63
|
+
#
|
|
64
|
+
# Guarded on the property rather than the variable for the same reason the
|
|
65
|
+
# block around it is guarded on the target: a build configuring two host
|
|
66
|
+
# packages must not add the same directory twice.
|
|
67
|
+
get_property(basalt_packages_added GLOBAL PROPERTY BASALT_PACKAGES_ADDED)
|
|
68
|
+
if(NOT basalt_packages_added)
|
|
69
|
+
set_property(GLOBAL PROPERTY BASALT_PACKAGES_ADDED TRUE)
|
|
70
|
+
foreach(package ${BASALT_PACKAGES})
|
|
71
|
+
if(EXISTS ${package}/native/CMakeLists.txt)
|
|
72
|
+
get_filename_component(basalt_package_name ${package} NAME)
|
|
73
|
+
message(STATUS "basalt: capability package ${basalt_package_name}")
|
|
74
|
+
add_subdirectory(${package}/native basalt-package-${basalt_package_name})
|
|
75
|
+
endif()
|
|
76
|
+
endforeach()
|
|
77
|
+
endif()
|
|
78
|
+
|
|
79
|
+
add_subdirectory(${BASALT_CORE_DIR} basalt_core)
|
|
80
|
+
endif()
|
|
81
|
+
|
|
82
|
+
# What capability packages contributed for this host; see
|
|
83
|
+
# packages/basalt-notifications for what a package sets.
|
|
84
|
+
#
|
|
85
|
+
# Read *after* the block above, because that block is where the packages are
|
|
86
|
+
# added. It used to be read at the top of this file, which worked for a
|
|
87
|
+
# checkout -- the root CMakeLists adds the packages before it adds this one --
|
|
88
|
+
# and silently contributed nothing for an app, where this file is the entry
|
|
89
|
+
# point. The symptom was a link error naming every notification seam.
|
|
90
|
+
get_property(BASALT_PACKAGE_WIN32_SOURCES GLOBAL PROPERTY BASALT_PACKAGE_WIN32_SOURCES)
|
|
91
|
+
# And what those sources need linked. A package contributing an implementation
|
|
92
|
+
# that reaches for a library had no way to say so; see the same property in the
|
|
93
|
+
# AppKit package for what went missing.
|
|
94
|
+
get_property(BASALT_PACKAGE_WIN32_LINK_LIBRARIES GLOBAL PROPERTY BASALT_PACKAGE_WIN32_LINK_LIBRARIES)
|
|
95
|
+
# And a package's own unit tests, which run in this host's suite. A capability
|
|
96
|
+
# with a platform half has nowhere else to be tested: it is compiled into the
|
|
97
|
+
# host binary, so the host's suite is the only binary that has it.
|
|
98
|
+
get_property(BASALT_PACKAGE_TESTS GLOBAL PROPERTY BASALT_PACKAGE_TESTS)
|
|
99
|
+
|
|
100
|
+
if(NOT WIN32)
|
|
101
|
+
# Not an error. A checkout builds every package it finds, and on anything but
|
|
102
|
+
# Windows this one has nothing it could compile.
|
|
103
|
+
message(STATUS "basalt-win32 skipped: not Windows")
|
|
104
|
+
return()
|
|
105
|
+
endif()
|
|
106
|
+
|
|
107
|
+
# ---------------------------------------------------------------------------
|
|
108
|
+
# What this project's own sources are held to.
|
|
109
|
+
#
|
|
110
|
+
# The GTK and AppKit halves say `-Wall -Wextra`, which MSVC does not speak.
|
|
111
|
+
# /W4 is the nearest equivalent and /permissive- is the part that matters more:
|
|
112
|
+
# without it MSVC accepts things no other compiler in this project would, and
|
|
113
|
+
# the first anyone would hear of it is the Linux build failing on code that
|
|
114
|
+
# compiled here. Set on targets rather than globally, so React Native's own
|
|
115
|
+
# sources -- which set their own flags and are not warning-clean under /W4 --
|
|
116
|
+
# never inherit them.
|
|
117
|
+
#
|
|
118
|
+
# Note that clang-cl reports as MSVC here, which is intended: it takes the same
|
|
119
|
+
# flags, and `docs/DECISIONS.md` prefers clang where there is a choice.
|
|
120
|
+
# ---------------------------------------------------------------------------
|
|
121
|
+
if(MSVC)
|
|
122
|
+
set(BASALT_WIN32_WARNINGS /W4 /permissive-)
|
|
123
|
+
else()
|
|
124
|
+
set(BASALT_WIN32_WARNINGS -Wall -Wextra)
|
|
125
|
+
endif()
|
|
126
|
+
|
|
127
|
+
# UNICODE, because every Win32 entry point in this project takes wide strings
|
|
128
|
+
# and the ANSI variants silently lose anything outside the active code page --
|
|
129
|
+
# which for React Native, where a string is UTF-8 from JavaScript, is most of
|
|
130
|
+
# the world. NOMINMAX and WIN32_LEAN_AND_MEAN because windows.h otherwise
|
|
131
|
+
# defines `min` and `max` as macros and breaks <algorithm> at a distance.
|
|
132
|
+
#
|
|
133
|
+
# _CRT_SECURE_NO_WARNINGS is not laziness about a real hazard: what it silences
|
|
134
|
+
# here is C4996 on `std::getenv`, which the other two platforms call in the same
|
|
135
|
+
# place for the same reason and which has no portable replacement. Anything that
|
|
136
|
+
# genuinely wants the checked CRT can ask for it on its own.
|
|
137
|
+
add_compile_definitions(UNICODE _UNICODE NOMINMAX WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS)
|
|
138
|
+
|
|
139
|
+
# ---------------------------------------------------------------------------
|
|
140
|
+
# basalt_win32_view — the Win32 view layer.
|
|
141
|
+
#
|
|
142
|
+
# No React Native dependency, so it builds and is tested on its own, on a
|
|
143
|
+
# Windows box with nothing installed but a compiler and the SDK. Direct2D, WIC
|
|
144
|
+
# and USER32 all ship with the operating system; there is nothing to fetch.
|
|
145
|
+
# ---------------------------------------------------------------------------
|
|
146
|
+
add_library(basalt_win32_view STATIC
|
|
147
|
+
win32/RnWin32View.cpp
|
|
148
|
+
# The paragraph object. DirectWrite only, no React Native, which is what keeps
|
|
149
|
+
# this target buildable and testable with nothing else installed.
|
|
150
|
+
win32/RnWin32TextLayout.cpp
|
|
151
|
+
# <Image> pixels: the WIC decode and the four resize modes. The fetch that
|
|
152
|
+
# feeds it is core/ImageBytes.cpp in the shared half, because a URI means the
|
|
153
|
+
# same thing on every desktop.
|
|
154
|
+
win32/RnWin32Image.cpp
|
|
155
|
+
# UI Automation. Windows inverts what the other two do -- a provider answers
|
|
156
|
+
# questions rather than a widget carrying properties; see the header.
|
|
157
|
+
win32/RnWin32Accessible.cpp
|
|
158
|
+
# Offscreen rendering, to a PNG or to pixels a test can read. The second is
|
|
159
|
+
# why this is in the view target rather than beside the demo: it is what the
|
|
160
|
+
# rendering assertions in tests/test_win32_paint.cpp are built on.
|
|
161
|
+
win32/Win32Snapshot.cpp
|
|
162
|
+
# The cursors Windows has no stock art for -- six CSS keywords drawn here as
|
|
163
|
+
# DIBs. Header-only until they were drawn; see Win32Cursors.h.
|
|
164
|
+
win32/Win32Cursors.cpp
|
|
165
|
+
# Where a hidden title bar's pieces are -- the caption buttons and the drag
|
|
166
|
+
# regions. Pure geometry over the view tree, so it is tested here with no
|
|
167
|
+
# window and no React Native.
|
|
168
|
+
win32/Win32TitleBarLayout.cpp)
|
|
169
|
+
target_compile_options(basalt_win32_view PRIVATE ${BASALT_WIN32_WARNINGS})
|
|
170
|
+
target_include_directories(basalt_win32_view PUBLIC win32)
|
|
171
|
+
# The header-only part of core, and only that: FocusRing.h, Backface.h,
|
|
172
|
+
# ImageAnimation.h and ShadowShape.h so far. None of them has React Native in
|
|
173
|
+
# it, so taking them does not make this target depend on the half that does --
|
|
174
|
+
# and the alternative is a focus ring that is a different blue on each desktop,
|
|
175
|
+
# three toolkits each with their own idea of which way a rotated card is facing,
|
|
176
|
+
# a GIF paced differently on each, and a hand-rolled copy of CSS's shadow-corner
|
|
177
|
+
# cubic per platform.
|
|
178
|
+
#
|
|
179
|
+
# Header-only is the constraint, not a preference: this library links no core,
|
|
180
|
+
# so anything it takes from there has to be `inline`.
|
|
181
|
+
target_include_directories(basalt_win32_view PUBLIC
|
|
182
|
+
${CMAKE_CURRENT_SOURCE_DIR}/../../basalt-core/native/core)
|
|
183
|
+
# dxguid is for the effect CLSIDs, and it is the kind of thing that only a
|
|
184
|
+
# linker tells you: `CLSID_D2D1Shadow` and its siblings are `DEFINE_GUID`
|
|
185
|
+
# declarations in d2d1effects.h, so the symbols live in that library rather
|
|
186
|
+
# than in d2d1. Without it a text shadow compiles and fails to link.
|
|
187
|
+
target_link_libraries(basalt_win32_view PUBLIC
|
|
188
|
+
d2d1 dwrite windowscodecs uiautomationcore ole32 oleaut32 user32 shcore dxguid)
|
|
189
|
+
|
|
190
|
+
add_executable(demo_layout_win32 win32/demo_layout_win32.cpp)
|
|
191
|
+
target_compile_options(demo_layout_win32 PRIVATE ${BASALT_WIN32_WARNINGS})
|
|
192
|
+
target_link_libraries(demo_layout_win32 PRIVATE basalt_win32_view)
|
|
193
|
+
|
|
194
|
+
# The runner comes from the shared half, which knows about no toolkit: the test
|
|
195
|
+
# infrastructure is shared even though the views are not. Unlike the GTK suite
|
|
196
|
+
# this one brings no separate entry point -- there is nothing to initialise
|
|
197
|
+
# before a view exists -- so `main` sits at the bottom of test_win32_view.cpp,
|
|
198
|
+
# as it does on the AppKit side.
|
|
199
|
+
set(BASALT_WIN32_TEST_SOURCES
|
|
200
|
+
${BASALT_TEST_HARNESS}
|
|
201
|
+
tests/test_win32_view.cpp
|
|
202
|
+
# What actually reached the pixels. Needs no display and no window, which is
|
|
203
|
+
# why this platform can assert it and the other two cannot; see the file.
|
|
204
|
+
tests/test_win32_paint.cpp
|
|
205
|
+
# Picking. In the view layer rather than beside a touch dispatcher, so that
|
|
206
|
+
# testing it needs no React Native -- the same arrangement AppKit settled on.
|
|
207
|
+
tests/test_win32_hittest.cpp
|
|
208
|
+
# DirectWrite measurement, against RnWin32TextLayout alone.
|
|
209
|
+
tests/test_win32_text.cpp
|
|
210
|
+
# The resize modes, against a real bitmap and real pixels.
|
|
211
|
+
tests/test_win32_image.cpp
|
|
212
|
+
# The UIA mapping. The React Native role name is what the cross-platform diff
|
|
213
|
+
# compares; this is where the platform half is checked.
|
|
214
|
+
tests/test_win32_accessibility.cpp
|
|
215
|
+
# A hidden title bar's geometry: the caption buttons and the drag regions.
|
|
216
|
+
tests/test_win32_titlebar.cpp)
|
|
217
|
+
|
|
218
|
+
# ---------------------------------------------------------------------------
|
|
219
|
+
# basalt_win32_mounting — the Windows half of the Fabric mounting manager.
|
|
220
|
+
#
|
|
221
|
+
# The mutation walk is not here: it is in the shared half, in
|
|
222
|
+
# core/MountingWalk.h. What is here is what is genuinely Windows about mounting,
|
|
223
|
+
# plus the four seams a platform owes the core.
|
|
224
|
+
#
|
|
225
|
+
# Skipped when the build was not pointed at a React Native, so the view layer
|
|
226
|
+
# above still builds and tests on a Windows box with nothing but a compiler.
|
|
227
|
+
# ---------------------------------------------------------------------------
|
|
228
|
+
if(TARGET basalt_core)
|
|
229
|
+
add_library(basalt_win32_mounting STATIC
|
|
230
|
+
win32/Win32MountingManager.cpp
|
|
231
|
+
# Mouse messages -> React Native touches. In the library rather than in the
|
|
232
|
+
# host so that tests can drive it, which is the only way the touch state
|
|
233
|
+
# machine is provable without a cursor.
|
|
234
|
+
win32/Win32Focus.cpp
|
|
235
|
+
win32/Win32KeyEvents.cpp
|
|
236
|
+
# Why Windows cannot show a notification; see the file.
|
|
237
|
+
${BASALT_PACKAGE_WIN32_SOURCES}
|
|
238
|
+
# The AppUserModelID and the Start Menu shortcut behind it, which is what
|
|
239
|
+
# makes a notification say which application it came from.
|
|
240
|
+
win32/Win32Packaging.cpp
|
|
241
|
+
win32/Win32TouchDispatcher.cpp
|
|
242
|
+
# <ScrollView>: the offset, the unthrottled state write-back, the wheel and
|
|
243
|
+
# the commands. Routing the wheel is this platform's alone -- there is no
|
|
244
|
+
# responder chain and no per-widget controller to attach one to.
|
|
245
|
+
win32/Win32ScrollView.cpp
|
|
246
|
+
# <TextInput>: a real EDIT control, which is a child window rather than a
|
|
247
|
+
# painted view -- so it is also the only component whose peer the host has
|
|
248
|
+
# to position, forward messages to, and answer colour questions for.
|
|
249
|
+
win32/Win32TextInput.cpp
|
|
250
|
+
# <Image> pixels: the fetch and the decode, both off the UI thread. The
|
|
251
|
+
# fetch itself is core/ImageBytes.cpp in the shared half.
|
|
252
|
+
win32/Win32ImageLoader.cpp
|
|
253
|
+
# Which components this platform claims. See core/ComponentRegistry.h, and
|
|
254
|
+
# note this and Win32MountingManager::hasComponent must agree.
|
|
255
|
+
win32/ComponentRegistryWin32.cpp
|
|
256
|
+
# AttributedString -> RnWin32TextLayout. Shared by measurement and painting,
|
|
257
|
+
# so they agree, which is the whole reason it is one file.
|
|
258
|
+
win32/DirectWriteLayout.cpp
|
|
259
|
+
# Replaces React Native's stub TextLayoutManager; see the shared half's
|
|
260
|
+
# cmake/ReactNativeCore.cmake for why the stub has to leave the build.
|
|
261
|
+
win32/DirectWriteLayoutManager.cpp
|
|
262
|
+
# Windows' implementation of core/FontRegistry.h -- the seam phase 17 named.
|
|
263
|
+
win32/FontRegistryDirectWrite.cpp
|
|
264
|
+
# ...and of core/ColorScheme.h.
|
|
265
|
+
win32/ColorSchemeWin32.cpp
|
|
266
|
+
# ...and of core/PlatformServices.h, which is also where postToUiThread
|
|
267
|
+
# lives -- the marshalling the mounting manager depends on.
|
|
268
|
+
win32/PlatformServicesWin32.cpp
|
|
269
|
+
# The window's title bar: DWM's colours and dark mode, and the caption the
|
|
270
|
+
# host draws when an app hides the system's. And BasaltWindow, the module
|
|
271
|
+
# JavaScript reaches it through.
|
|
272
|
+
# Accepting a file or text dragged onto the window; see
|
|
273
|
+
# core/DragAndDrop.h for the model the three hosts share.
|
|
274
|
+
win32/Win32DropTarget.cpp
|
|
275
|
+
win32/Win32TitleBar.cpp
|
|
276
|
+
# A window's size, position and full-screen state; see core/WindowControl.h.
|
|
277
|
+
win32/Win32WindowControl.cpp
|
|
278
|
+
# The application menu; see core/MenuModel.h for why the three differ.
|
|
279
|
+
win32/Win32MenuBar.cpp
|
|
280
|
+
win32/Win32WindowModule.cpp)
|
|
281
|
+
target_compile_options(basalt_win32_mounting PRIVATE ${BASALT_WIN32_WARNINGS})
|
|
282
|
+
target_include_directories(basalt_win32_mounting PUBLIC win32)
|
|
283
|
+
target_link_libraries(basalt_win32_mounting PUBLIC basalt_win32_view basalt_core)
|
|
284
|
+
|
|
285
|
+
# @shopify/react-native-skia, when the build was pointed at an app that has
|
|
286
|
+
# it. See ../../basalt-core/native/cmake/Skia.cmake.
|
|
287
|
+
#
|
|
288
|
+
# Here rather than on basalt_core, for the reason the AppKit package gives:
|
|
289
|
+
# a platform context is a host's dependency. The Windows one reaches
|
|
290
|
+
# DirectWrite and the Win32 DPI call, and core/portability_probe.cpp links
|
|
291
|
+
# the core with no toolkit on purpose.
|
|
292
|
+
if(TARGET skia_core)
|
|
293
|
+
target_link_libraries(basalt_win32_mounting PUBLIC skia_core)
|
|
294
|
+
target_sources(basalt_win32_mounting PUBLIC $<TARGET_OBJECTS:skia_core>)
|
|
295
|
+
target_compile_definitions(basalt_win32_mounting PUBLIC BASALT_HAS_SKIA=1)
|
|
296
|
+
# This host's half: the TurboModule the package asks for by name, the
|
|
297
|
+
# platform context it hands to Skia, and the peer behind a `<Canvas>`.
|
|
298
|
+
# See win32/Win32SkiaModule.h and win32/Win32SkiaPeer.h.
|
|
299
|
+
target_sources(basalt_win32_mounting PRIVATE
|
|
300
|
+
win32/Win32SkiaModule.cpp
|
|
301
|
+
win32/Win32SkiaContext.cpp
|
|
302
|
+
# AppKitSkiaPeer.mm's opposite number. Where that one hands the package a
|
|
303
|
+
# Metal layer, this renders into memory and lets the Direct2D walk draw
|
|
304
|
+
# the result -- this host has no layer tree to hang a canvas in.
|
|
305
|
+
win32/Win32SkiaPeer.cpp
|
|
306
|
+
# The unicode factory the package asks for by name on anything that is
|
|
307
|
+
# not Apple, answered with the backend that is actually linked here.
|
|
308
|
+
win32/Win32SkiaUnicode.cpp)
|
|
309
|
+
endif()
|
|
310
|
+
# shell32 for ShellExecute; comctl32 for SetWindowSubclass, which is how a
|
|
311
|
+
# <TextInput>'s EDIT peer is subclassed without breaking anything else that
|
|
312
|
+
# subclasses it later.
|
|
313
|
+
# shell32 for Shell_NotifyIcon and SHGetKnownFolderPath, ole32 for the
|
|
314
|
+
# IShellLink that writes the Start Menu shortcut, propsys for the property
|
|
315
|
+
# store that puts the AppUserModelID on it.
|
|
316
|
+
target_link_libraries(basalt_win32_mounting PUBLIC shell32 comctl32 ole32 propsys)
|
|
317
|
+
# dwmapi for the title bar's colours and dark mode.
|
|
318
|
+
target_link_libraries(basalt_win32_mounting PUBLIC dwmapi)
|
|
319
|
+
|
|
320
|
+
# -------------------------------------------------------------------------
|
|
321
|
+
# basalt_win32 — a ReactHost, Hermes, and one surface in an HWND.
|
|
322
|
+
# -------------------------------------------------------------------------
|
|
323
|
+
add_executable(basalt_win32
|
|
324
|
+
win32/main_win32.cpp
|
|
325
|
+
# The event beat. Not an observer on Windows: there is no "about to wait"
|
|
326
|
+
# hook, so the message loop itself is here. See the header.
|
|
327
|
+
win32/Win32RunLoopObserver.cpp
|
|
328
|
+
win32/Win32AnimationChoreographer.cpp)
|
|
329
|
+
target_compile_options(basalt_win32 PRIVATE ${BASALT_WIN32_WARNINGS})
|
|
330
|
+
target_link_libraries(basalt_win32 PRIVATE basalt_win32_mounting)
|
|
331
|
+
if(BASALT_PACKAGE_WIN32_LINK_LIBRARIES)
|
|
332
|
+
target_link_libraries(basalt_win32 PRIVATE ${BASALT_PACKAGE_WIN32_LINK_LIBRARIES})
|
|
333
|
+
endif()
|
|
334
|
+
|
|
335
|
+
# Real mutations into real views, with no JavaScript anywhere. The checkpoint
|
|
336
|
+
# between "the mounting manager compiles" and "React Native runs": a mistake
|
|
337
|
+
# in the Create/Insert/Update/Remove/Delete handling shows up in a picture
|
|
338
|
+
# rather than in review.
|
|
339
|
+
add_executable(mount_harness_win32 win32/mount_harness_win32.cpp)
|
|
340
|
+
target_compile_options(mount_harness_win32 PRIVATE ${BASALT_WIN32_WARNINGS})
|
|
341
|
+
target_link_libraries(mount_harness_win32 PRIVATE basalt_win32_mounting)
|
|
342
|
+
|
|
343
|
+
list(APPEND BASALT_WIN32_TEST_SOURCES
|
|
344
|
+
${BASALT_CORE_TESTS}
|
|
345
|
+
# Key events, and the mapping under test. Here rather than in the
|
|
346
|
+
# unconditional set above, which is where they were: core/KeyEvents.h
|
|
347
|
+
# speaks in facebook::react::Tag and includes ReactPrimitives.h for it, so
|
|
348
|
+
# anything touching it needs a React Native to have been found. The view
|
|
349
|
+
# layer deliberately has not found one -- that is what lets it build on a
|
|
350
|
+
# Windows box with nothing but a compiler -- and the release workflow's
|
|
351
|
+
# MSBuild job is exactly that build, so it failed there and nowhere else.
|
|
352
|
+
# This host is still the only one that can check the table, and the
|
|
353
|
+
# Windows CI shards, which do have React Native, still do.
|
|
354
|
+
tests/test_win32_key_events.cpp
|
|
355
|
+
# Selecting text with a pointer, here for the same reason and found the
|
|
356
|
+
# same way: it drives a Win32TouchDispatcher and asserts against
|
|
357
|
+
# core/TextSelection.h, both of which speak React Native, and it sat in
|
|
358
|
+
# the unconditional set above from the day it was written. The MSBuild job
|
|
359
|
+
# is the only build without a React Native, so it failed there and nowhere
|
|
360
|
+
# else -- the second time this file has learnt that, which is why the
|
|
361
|
+
# rule is now in the comment above rather than in a commit message.
|
|
362
|
+
tests/test_win32_selection.cpp
|
|
363
|
+
win32/Win32KeyEvents.cpp
|
|
364
|
+
# A package's own tests; see the AppKit package for why they sit with core's.
|
|
365
|
+
${BASALT_PACKAGE_TESTS}
|
|
366
|
+
# Deliberately the same nine questions tests/test_mounting.cpp asks of GTK
|
|
367
|
+
# and tests/test_appkit_mounting.mm asks of AppKit, in the same order with
|
|
368
|
+
# the same tags. Most of what they test is whether the sharing still holds.
|
|
369
|
+
tests/test_win32_mounting.cpp
|
|
370
|
+
# The image loader: the cache, the failure paths, and the two lifetimes.
|
|
371
|
+
# In the RN-dependent set because the fetch is core/ImageBytes.cpp.
|
|
372
|
+
tests/test_win32_imageloader.cpp
|
|
373
|
+
# Animated GIFs: the frames WIC decodes and the pacing core shares. Here
|
|
374
|
+
# for the same reason as the loader's own tests -- the fixtures are `data:`
|
|
375
|
+
# URIs, read by core/ImageBytes.cpp -- even though most of the file is the
|
|
376
|
+
# view layer's.
|
|
377
|
+
tests/test_win32_animated_image.cpp
|
|
378
|
+
# The touch state machine and the gesture handover, asking what
|
|
379
|
+
# tests/test_appkit_input.mm asks of AppKit.
|
|
380
|
+
tests/test_win32_input.cpp
|
|
381
|
+
# <ScrollView>: the clamp, the throttle, the state write-back, the wheel's
|
|
382
|
+
# innermost-first routing and the commands.
|
|
383
|
+
tests/test_win32_focus.cpp
|
|
384
|
+
tests/test_win32_scrollview.cpp
|
|
385
|
+
# <TextInput>. The only tests here that make a window, because a text
|
|
386
|
+
# field's peer is one -- see the file.
|
|
387
|
+
tests/test_win32_textinput.cpp
|
|
388
|
+
# The clipboard, and what happens when another program has it open.
|
|
389
|
+
tests/test_win32_clipboard.cpp
|
|
390
|
+
# The caption actions with no window attached. Here rather than beside
|
|
391
|
+
# test_win32_titlebar.cpp because Win32TitleBar is in basalt_win32_mounting,
|
|
392
|
+
# which only exists when basalt_core does; its neighbour is pure geometry.
|
|
393
|
+
tests/test_win32_titlebar_actions.cpp)
|
|
394
|
+
endif()
|
|
395
|
+
|
|
396
|
+
# ---------------------------------------------------------------------------
|
|
397
|
+
# Still to come:
|
|
398
|
+
#
|
|
399
|
+
# mount_harness_win32 real ShadowViewMutations, no JavaScript, rendered
|
|
400
|
+
# to a PNG -- the checkpoint between "the mounting
|
|
401
|
+
# manager compiles" and "React Native runs".
|
|
402
|
+
# basalt_win32 a ReactHost, Hermes, and one surface in an HWND.
|
|
403
|
+
#
|
|
404
|
+
# And the components this platform does not claim yet: <ScrollView>, which
|
|
405
|
+
# needs onScroll and scroll state, and <TextInput>, which needs an EDIT peer.
|
|
406
|
+
# ---------------------------------------------------------------------------
|
|
407
|
+
|
|
408
|
+
# Without React Native there is no basalt_core to link, and the harness calls
|
|
409
|
+
# `basalt::installCrashHandler` whatever it is linked against -- so this build
|
|
410
|
+
# compiles that one file itself. The MSBuild job in release.yml is the only
|
|
411
|
+
# build that gets here, which is why the link error it answered with was
|
|
412
|
+
# invisible to every CI run.
|
|
413
|
+
if(NOT TARGET basalt_core)
|
|
414
|
+
list(APPEND BASALT_WIN32_TEST_SOURCES ${BASALT_CRASH_HANDLER})
|
|
415
|
+
endif()
|
|
416
|
+
|
|
417
|
+
add_executable(basalt_win32_tests ${BASALT_WIN32_TEST_SOURCES})
|
|
418
|
+
target_compile_options(basalt_win32_tests PRIVATE ${BASALT_WIN32_WARNINGS})
|
|
419
|
+
target_include_directories(basalt_win32_tests PRIVATE ${BASALT_TEST_INCLUDE})
|
|
420
|
+
# basalt_win32_mounting already carries basalt_win32_view; naming both makes the
|
|
421
|
+
# linker warn about a duplicate library rather than doing anything useful.
|
|
422
|
+
if(TARGET basalt_win32_mounting)
|
|
423
|
+
target_link_libraries(basalt_win32_tests PRIVATE basalt_win32_mounting)
|
|
424
|
+
if(BASALT_PACKAGE_WIN32_LINK_LIBRARIES)
|
|
425
|
+
target_link_libraries(basalt_win32_tests PRIVATE ${BASALT_PACKAGE_WIN32_LINK_LIBRARIES})
|
|
426
|
+
endif()
|
|
427
|
+
else()
|
|
428
|
+
target_link_libraries(basalt_win32_tests PRIVATE basalt_win32_view)
|
|
429
|
+
endif()
|