@geastack/apple 0.2.8
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 +202 -0
- package/README.md +54 -0
- package/dist/index.d.ts +127 -0
- package/dist/index.js +3076 -0
- package/generated/AVFoundation.d.ts +112 -0
- package/generated/ActivityKit.d.ts +7 -0
- package/generated/AppKit.d.ts +268 -0
- package/generated/CoreGraphics.d.ts +18 -0
- package/generated/CoreLocation.d.ts +28 -0
- package/generated/CoreMedia.d.ts +8 -0
- package/generated/Dispatch.d.ts +2 -0
- package/generated/Foundation.d.ts +13 -0
- package/generated/MapKit.d.ts +28 -0
- package/generated/Metal.d.ts +91 -0
- package/generated/MetalKit.d.ts +22 -0
- package/generated/Photos.d.ts +5 -0
- package/generated/QuartzCore.d.ts +12 -0
- package/generated/SwiftData.d.ts +11 -0
- package/generated/UIKit.d.ts +187 -0
- package/package.json +123 -0
- package/runtime/AVFoundation.js +136 -0
- package/runtime/ActivityKit.js +18 -0
- package/runtime/AppKit.js +313 -0
- package/runtime/CoreGraphics.js +15 -0
- package/runtime/CoreLocation.js +30 -0
- package/runtime/CoreMedia.js +7 -0
- package/runtime/Dispatch.js +11 -0
- package/runtime/Foundation.js +21 -0
- package/runtime/MapKit.js +22 -0
- package/runtime/Metal.js +126 -0
- package/runtime/MetalKit.js +15 -0
- package/runtime/Photos.js +9 -0
- package/runtime/QuartzCore.js +9 -0
- package/runtime/SwiftData.js +29 -0
- package/runtime/UIKit.js +242 -0
- package/runtime/empty.js +1 -0
- package/targets/ios/Info.plist.in +25 -0
- package/targets/ios/README.md +46 -0
- package/targets/ios/build-ios.sh +395 -0
- package/targets/ios/detect-development-team.mjs +109 -0
- package/targets/ios/generate-resident-entry.mjs +67 -0
- package/targets/ios/generate-resident-registry.mjs +162 -0
- package/targets/ios/generate-xcode-project.mjs +520 -0
- package/targets/ios/main/canvas_view.h +7 -0
- package/targets/ios/main/canvas_view.mm +94 -0
- package/targets/ios/main/font_registry.h +17 -0
- package/targets/ios/main/font_registry.mm +129 -0
- package/targets/ios/main/image_bridge.h +13 -0
- package/targets/ios/main/image_bridge.mm +53 -0
- package/targets/ios/main/ios_apps.c +28 -0
- package/targets/ios/main/ios_camera.mm +446 -0
- package/targets/ios/main/ios_display.mm +344 -0
- package/targets/ios/main/ios_main.mm +811 -0
- package/targets/ios/main/ios_memory.cpp +55 -0
- package/targets/ios/main/ios_renderer.h +20 -0
- package/targets/ios/main/ios_renderer.mm +27 -0
- package/targets/ios/main/ios_root_background.cpp +20 -0
- package/targets/ios/main/ios_root_background.h +11 -0
- package/targets/ios/main/ios_sensors.mm +244 -0
- package/targets/ios/main/ios_timers.mm +53 -0
- package/targets/ios/main/renderer/ios_renderer_internal.h +65 -0
- package/targets/ios/main/renderer/ios_renderer_support.mm +111 -0
- package/targets/ios/main/renderer/native_button.mm +179 -0
- package/targets/ios/main/renderer/native_label.mm +161 -0
- package/targets/ios/main/renderer/native_scroll_container.mm +279 -0
- package/targets/ios/main/renderer/view_reconciler.mm +274 -0
- package/targets/macos/Info.plist.in +26 -0
- package/targets/macos/README.md +131 -0
- package/targets/macos/build-child-lifecycle.sh +119 -0
- package/targets/macos/build-macos.sh +2156 -0
- package/targets/macos/check-module-graph-freshness.mjs +82 -0
- package/targets/macos/compiler-input-fingerprint.mjs +32 -0
- package/targets/macos/finalize-apple-native-output.mjs +77 -0
- package/targets/macos/generate-resident-entry.mjs +80 -0
- package/targets/macos/generate-resident-registry.mjs +141 -0
- package/targets/macos/heavy-build-lock.sh +176 -0
- package/targets/macos/main/canvas_view.h +9 -0
- package/targets/macos/main/canvas_view.mm +176 -0
- package/targets/macos/main/color_convert.h +18 -0
- package/targets/macos/main/color_convert.mm +39 -0
- package/targets/macos/main/font_registry.h +35 -0
- package/targets/macos/main/font_registry.mm +350 -0
- package/targets/macos/main/image_bridge.h +16 -0
- package/targets/macos/main/image_bridge.mm +52 -0
- package/targets/macos/main/macos_app_platform.mm +95 -0
- package/targets/macos/main/macos_apps.c +31 -0
- package/targets/macos/main/macos_device_control.mm +56 -0
- package/targets/macos/main/macos_display.mm +484 -0
- package/targets/macos/main/macos_host_device_control.mm +95 -0
- package/targets/macos/main/macos_main.mm +839 -0
- package/targets/macos/main/macos_memory.cpp +31 -0
- package/targets/macos/main/macos_native_shell.h +31 -0
- package/targets/macos/main/macos_native_shell.mm +396 -0
- package/targets/macos/main/macos_network.mm +253 -0
- package/targets/macos/main/macos_renderer.h +39 -0
- package/targets/macos/main/macos_renderer.mm +1969 -0
- package/targets/macos/main/macos_sensors.cpp +148 -0
- package/targets/macos/main/macos_smoke_app.cpp +65 -0
- package/targets/macos/main/macos_timers.mm +52 -0
- package/targets/macos/main/press_bridge.h +21 -0
- package/targets/macos/main/press_bridge.mm +72 -0
- package/targets/macos/main/thermalright_hid_display.h +14 -0
- package/targets/macos/main/thermalright_hid_display.mm +995 -0
- package/targets/macos/native-artifact-provenance.mjs +421 -0
- package/targets/macos/order-compile-edges.mjs +64 -0
- package/targets/macos/preflight-hard-muted-artifact.mjs +93 -0
- package/targets/macos/prune-generated-modules.mjs +147 -0
- package/targets/macos/sync-resources.mjs +153 -0
- package/targets/shared/analyze-audio-capture.mjs +131 -0
- package/targets/shared/apple_audio.mm +1194 -0
- package/targets/shared/apple_audio_selftest.mm +602 -0
- package/targets/shared/apple_audio_testing.h +34 -0
- package/targets/shared/build-audio-selftest.sh +50 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#include "memory.h"
|
|
2
|
+
|
|
3
|
+
#include <cstddef>
|
|
4
|
+
#include <cstdlib>
|
|
5
|
+
|
|
6
|
+
namespace gea::framework::memory {
|
|
7
|
+
|
|
8
|
+
void *Allocator::allocatePreferSpiram(std::size_t size, std::size_t alignment)
|
|
9
|
+
{
|
|
10
|
+
if (size == 0) return nullptr;
|
|
11
|
+
if (alignment <= alignof(std::max_align_t)) return std::malloc(size);
|
|
12
|
+
void *ptr = nullptr;
|
|
13
|
+
if (posix_memalign(&ptr, alignment, size) != 0) return nullptr;
|
|
14
|
+
return ptr;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void *Allocator::reallocatePreferSpiram(void *ptr, std::size_t size)
|
|
18
|
+
{
|
|
19
|
+
if (size == 0) {
|
|
20
|
+
std::free(ptr);
|
|
21
|
+
return nullptr;
|
|
22
|
+
}
|
|
23
|
+
return std::realloc(ptr, size);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void Allocator::free(void *ptr) noexcept
|
|
27
|
+
{
|
|
28
|
+
std::free(ptr);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
} // namespace gea::framework::memory
|
|
32
|
+
|
|
33
|
+
namespace gea::platform::memory {
|
|
34
|
+
|
|
35
|
+
std::uint32_t Memory::internalFree() { return 0; }
|
|
36
|
+
std::uint32_t Memory::internalLargestFreeBlock() { return 0; }
|
|
37
|
+
std::uint32_t Memory::internalMinimumFree() { return 0; }
|
|
38
|
+
std::uint32_t Memory::psramFree() { return 0; }
|
|
39
|
+
std::uint32_t Memory::currentTaskStackHighWaterMark() { return 0; }
|
|
40
|
+
std::uint32_t Memory::geaMainStackBytes() { return 0; }
|
|
41
|
+
std::uint32_t Memory::geaInitStackBytes() { return 0; }
|
|
42
|
+
std::uint32_t Memory::appFrameStackWords() { return 0; }
|
|
43
|
+
std::uint32_t Memory::appFrameStackBytes() { return 0; }
|
|
44
|
+
std::uint32_t Memory::displayFlushConfiguredRows() { return 0; }
|
|
45
|
+
std::uint32_t Memory::displayFlushConfiguredDepth() { return 0; }
|
|
46
|
+
std::uint32_t Memory::displayFlushBufferMaxBytes() { return 0; }
|
|
47
|
+
std::uint32_t Memory::displayFlushRows() { return 0; }
|
|
48
|
+
std::uint32_t Memory::displayFlushDepth() { return 0; }
|
|
49
|
+
std::uint32_t Memory::displayFlushBufferBytes() { return 0; }
|
|
50
|
+
|
|
51
|
+
// No internal/external split here, so there is nothing to hold back for the
|
|
52
|
+
// display; the caller treats nullptr as "no reserve" and carries on.
|
|
53
|
+
void *Memory::reserveInternalDma(std::size_t) { return nullptr; }
|
|
54
|
+
void Memory::releaseInternalDma(void *) {}
|
|
55
|
+
} // namespace gea::platform::memory
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#ifdef __OBJC__
|
|
4
|
+
@class UIView;
|
|
5
|
+
#else
|
|
6
|
+
struct UIView;
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
namespace gea::ios {
|
|
10
|
+
|
|
11
|
+
class IosRenderer {
|
|
12
|
+
public:
|
|
13
|
+
static IosRenderer &instance();
|
|
14
|
+
|
|
15
|
+
void sync(UIView *parentForRoot, int rootNodeId);
|
|
16
|
+
void teardown();
|
|
17
|
+
bool hasNativeTree() const;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
} // namespace gea::ios
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#include "ios_renderer.h"
|
|
2
|
+
#include "renderer/ios_renderer_internal.h"
|
|
3
|
+
|
|
4
|
+
namespace gea::ios {
|
|
5
|
+
|
|
6
|
+
IosRenderer &IosRenderer::instance()
|
|
7
|
+
{
|
|
8
|
+
static IosRenderer renderer;
|
|
9
|
+
return renderer;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
void IosRenderer::sync(UIView *parentForRoot, int rootNodeId)
|
|
13
|
+
{
|
|
14
|
+
renderer::syncNativeTree(parentForRoot, rootNodeId);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void IosRenderer::teardown()
|
|
18
|
+
{
|
|
19
|
+
renderer::teardownNativeTree();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
bool IosRenderer::hasNativeTree() const
|
|
23
|
+
{
|
|
24
|
+
return renderer::hasNativeTree();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
} // namespace gea::ios
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#include "ios_root_background.h"
|
|
2
|
+
|
|
3
|
+
#include "ui/tree_internal.h"
|
|
4
|
+
|
|
5
|
+
namespace gea::ios {
|
|
6
|
+
|
|
7
|
+
bool mountedRootBackgroundColor(gea::framework::graphics::pixel::native_t *outColor)
|
|
8
|
+
{
|
|
9
|
+
auto &tree = gea::embedded::ui::Tree::instance();
|
|
10
|
+
const int root = tree.mountedRoot();
|
|
11
|
+
if (root < 0 || root >= tree.nodeCount()) return false;
|
|
12
|
+
|
|
13
|
+
const auto &style = tree.node(root).style;
|
|
14
|
+
if (!style.has_bg) return false;
|
|
15
|
+
|
|
16
|
+
if (outColor) *outColor = style.bg_color;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
} // namespace gea::ios
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#include "imu.h"
|
|
2
|
+
#include "touch.h"
|
|
3
|
+
|
|
4
|
+
#import <CoreMotion/CoreMotion.h>
|
|
5
|
+
#import <Foundation/Foundation.h>
|
|
6
|
+
|
|
7
|
+
#include <algorithm>
|
|
8
|
+
#include <cmath>
|
|
9
|
+
|
|
10
|
+
namespace gea::platform::sensors {
|
|
11
|
+
|
|
12
|
+
namespace {
|
|
13
|
+
|
|
14
|
+
constexpr NSTimeInterval kMotionUpdateInterval = 1.0 / 60.0;
|
|
15
|
+
constexpr double kPi = 3.14159265358979323846;
|
|
16
|
+
constexpr double kRadiansToDegrees = 180.0 / kPi;
|
|
17
|
+
constexpr double kStandardGravity = 9.80665;
|
|
18
|
+
|
|
19
|
+
double g_gyro_bias_x = 0.0;
|
|
20
|
+
double g_gyro_bias_y = 0.0;
|
|
21
|
+
double g_gyro_bias_z = 0.0;
|
|
22
|
+
|
|
23
|
+
struct Acceleration {
|
|
24
|
+
double x = 0.0;
|
|
25
|
+
double y = 0.0;
|
|
26
|
+
double z = 1.0;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
struct RotationRate {
|
|
30
|
+
double x = 0.0;
|
|
31
|
+
double y = 0.0;
|
|
32
|
+
double z = 0.0;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
Acceleration mapCoreMotionAccelerationToGea(Acceleration raw)
|
|
36
|
+
{
|
|
37
|
+
return { raw.y, -raw.x, raw.z };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
RotationRate mapCoreMotionRotationRateToGea(RotationRate raw)
|
|
41
|
+
{
|
|
42
|
+
return { raw.y, -raw.x, raw.z };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
CMMotionManager *motionManager()
|
|
46
|
+
{
|
|
47
|
+
static CMMotionManager *manager = nil;
|
|
48
|
+
static dispatch_once_t onceToken;
|
|
49
|
+
dispatch_once(&onceToken, ^{
|
|
50
|
+
manager = [[CMMotionManager alloc] init];
|
|
51
|
+
});
|
|
52
|
+
return manager;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
void startMotionUpdates()
|
|
56
|
+
{
|
|
57
|
+
CMMotionManager *manager = motionManager();
|
|
58
|
+
if (manager.deviceMotionAvailable) {
|
|
59
|
+
manager.deviceMotionUpdateInterval = kMotionUpdateInterval;
|
|
60
|
+
if (!manager.deviceMotionActive) {
|
|
61
|
+
[manager startDeviceMotionUpdates];
|
|
62
|
+
}
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (manager.accelerometerAvailable && !manager.accelerometerActive) {
|
|
67
|
+
manager.accelerometerUpdateInterval = kMotionUpdateInterval;
|
|
68
|
+
[manager startAccelerometerUpdates];
|
|
69
|
+
}
|
|
70
|
+
if (manager.gyroAvailable && !manager.gyroActive) {
|
|
71
|
+
manager.gyroUpdateInterval = kMotionUpdateInterval;
|
|
72
|
+
[manager startGyroUpdates];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
Acceleration currentAcceleration()
|
|
77
|
+
{
|
|
78
|
+
startMotionUpdates();
|
|
79
|
+
|
|
80
|
+
CMMotionManager *manager = motionManager();
|
|
81
|
+
CMDeviceMotion *motion = manager.deviceMotion;
|
|
82
|
+
if (motion) {
|
|
83
|
+
CMAcceleration gravity = motion.gravity;
|
|
84
|
+
CMAcceleration userAcceleration = motion.userAcceleration;
|
|
85
|
+
return mapCoreMotionAccelerationToGea({
|
|
86
|
+
(gravity.x + userAcceleration.x) * kStandardGravity,
|
|
87
|
+
(gravity.y + userAcceleration.y) * kStandardGravity,
|
|
88
|
+
(gravity.z + userAcceleration.z) * kStandardGravity,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
CMAccelerometerData *data = manager.accelerometerData;
|
|
93
|
+
if (data) {
|
|
94
|
+
CMAcceleration acceleration = data.acceleration;
|
|
95
|
+
return mapCoreMotionAccelerationToGea({
|
|
96
|
+
acceleration.x * kStandardGravity,
|
|
97
|
+
acceleration.y * kStandardGravity,
|
|
98
|
+
acceleration.z * kStandardGravity,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
RotationRate currentRotationRate()
|
|
106
|
+
{
|
|
107
|
+
startMotionUpdates();
|
|
108
|
+
|
|
109
|
+
CMMotionManager *manager = motionManager();
|
|
110
|
+
CMDeviceMotion *motion = manager.deviceMotion;
|
|
111
|
+
if (motion) {
|
|
112
|
+
CMRotationRate rate = motion.rotationRate;
|
|
113
|
+
return mapCoreMotionRotationRateToGea({
|
|
114
|
+
rate.x * kRadiansToDegrees,
|
|
115
|
+
rate.y * kRadiansToDegrees,
|
|
116
|
+
rate.z * kRadiansToDegrees,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
CMGyroData *data = manager.gyroData;
|
|
121
|
+
if (data) {
|
|
122
|
+
CMRotationRate rate = data.rotationRate;
|
|
123
|
+
return mapCoreMotionRotationRateToGea({
|
|
124
|
+
rate.x * kRadiansToDegrees,
|
|
125
|
+
rate.y * kRadiansToDegrees,
|
|
126
|
+
rate.z * kRadiansToDegrees,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
int tiltFromAxis(double axisMetersPerSecondSquared)
|
|
134
|
+
{
|
|
135
|
+
const double axisG = axisMetersPerSecondSquared / kStandardGravity;
|
|
136
|
+
const int value = static_cast<int>(axisG * 70.0);
|
|
137
|
+
return std::clamp(value, -100, 100);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
} // namespace
|
|
141
|
+
|
|
142
|
+
void Accelerometer::init()
|
|
143
|
+
{
|
|
144
|
+
startMotionUpdates();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
void Accelerometer::close()
|
|
148
|
+
{
|
|
149
|
+
CMMotionManager *manager = motionManager();
|
|
150
|
+
if (manager.deviceMotionActive) [manager stopDeviceMotionUpdates];
|
|
151
|
+
if (manager.accelerometerActive) [manager stopAccelerometerUpdates];
|
|
152
|
+
if (manager.gyroActive) [manager stopGyroUpdates];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
void Accelerometer::calibrateBias()
|
|
156
|
+
{
|
|
157
|
+
RotationRate rate = currentRotationRate();
|
|
158
|
+
g_gyro_bias_x = rate.x;
|
|
159
|
+
g_gyro_bias_y = rate.y;
|
|
160
|
+
g_gyro_bias_z = rate.z;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
int Accelerometer::tiltX()
|
|
164
|
+
{
|
|
165
|
+
return tiltFromAxis(currentAcceleration().y);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
int Accelerometer::tiltY()
|
|
169
|
+
{
|
|
170
|
+
return tiltFromAxis(-currentAcceleration().x);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
double Accelerometer::accelerationX()
|
|
174
|
+
{
|
|
175
|
+
return currentAcceleration().x;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
double Accelerometer::accelerationY()
|
|
179
|
+
{
|
|
180
|
+
return currentAcceleration().y;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
double Accelerometer::accelerationZ()
|
|
184
|
+
{
|
|
185
|
+
return currentAcceleration().z;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
double Accelerometer::gyroscopeX()
|
|
189
|
+
{
|
|
190
|
+
return currentRotationRate().x - g_gyro_bias_x;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
double Accelerometer::gyroscopeY()
|
|
194
|
+
{
|
|
195
|
+
return currentRotationRate().y - g_gyro_bias_y;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
double Accelerometer::gyroscopeZ()
|
|
199
|
+
{
|
|
200
|
+
return currentRotationRate().z - g_gyro_bias_z;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
void Accelerometer::setWebTilt(int, int) {}
|
|
204
|
+
|
|
205
|
+
} // namespace gea::platform::sensors
|
|
206
|
+
|
|
207
|
+
namespace gea::platform::touch {
|
|
208
|
+
|
|
209
|
+
namespace {
|
|
210
|
+
bool g_touching = false;
|
|
211
|
+
int g_touch_x = 0;
|
|
212
|
+
int g_touch_y = 0;
|
|
213
|
+
} // namespace
|
|
214
|
+
|
|
215
|
+
extern "C" void gea_ios_touch_set_state(int touching, int x, int y)
|
|
216
|
+
{
|
|
217
|
+
g_touching = touching != 0;
|
|
218
|
+
g_touch_x = x;
|
|
219
|
+
g_touch_y = y;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
void Touchscreen::setObserver(Observer) {}
|
|
223
|
+
bool Touchscreen::init() { return true; }
|
|
224
|
+
int Touchscreen::read(int *x, int *y)
|
|
225
|
+
{
|
|
226
|
+
if (x) *x = g_touch_x;
|
|
227
|
+
if (y) *y = g_touch_y;
|
|
228
|
+
return g_touching ? 1 : 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
int Touchscreen::readCached(int *x, int *y)
|
|
232
|
+
{
|
|
233
|
+
if (x) *x = g_touch_x;
|
|
234
|
+
if (y) *y = g_touch_y;
|
|
235
|
+
return g_touching ? 1 : 0;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
void Touchscreen::consumeLatestMove(int *x, int *y)
|
|
239
|
+
{
|
|
240
|
+
if (x) *x = g_touch_x;
|
|
241
|
+
if (y) *y = g_touch_y;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
} // namespace gea::platform::touch
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
#include "services/frame_scheduler.h"
|
|
4
|
+
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include <mach/mach_time.h>
|
|
7
|
+
|
|
8
|
+
namespace {
|
|
9
|
+
|
|
10
|
+
int millis_since_boot()
|
|
11
|
+
{
|
|
12
|
+
static mach_timebase_info_data_t tb = {0, 0};
|
|
13
|
+
if (tb.denom == 0) mach_timebase_info(&tb);
|
|
14
|
+
const std::uint64_t ns = mach_absolute_time() * tb.numer / tb.denom;
|
|
15
|
+
return static_cast<int>(ns / 1000000ULL);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
int g_frame_interval_ms = gea::framework::services::FrameScheduler::kDefaultFrameIntervalMs;
|
|
19
|
+
|
|
20
|
+
} // namespace
|
|
21
|
+
|
|
22
|
+
extern "C" int gea_embedded_now_ms(void)
|
|
23
|
+
{
|
|
24
|
+
return millis_since_boot();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
namespace gea::framework::services {
|
|
28
|
+
|
|
29
|
+
EventQueue FrameScheduler::createEventQueue() { return EventQueue{}; }
|
|
30
|
+
EventQueue FrameScheduler::eventQueue() { return EventQueue{}; }
|
|
31
|
+
bool FrameScheduler::sendEvent(const gea::framework::events::Event &, int) { return true; }
|
|
32
|
+
bool FrameScheduler::receiveEvent(gea::framework::events::Event *) { return false; }
|
|
33
|
+
void FrameScheduler::start(EventQueue) {}
|
|
34
|
+
void FrameScheduler::runFrame(const FrameCallbacks &callbacks)
|
|
35
|
+
{
|
|
36
|
+
if (callbacks.frame) callbacks.frame(millis_since_boot(), callbacks.context);
|
|
37
|
+
}
|
|
38
|
+
void FrameScheduler::setFrameIntervalMs(int intervalMs)
|
|
39
|
+
{
|
|
40
|
+
if (intervalMs < kMinFrameIntervalMs) intervalMs = kMinFrameIntervalMs;
|
|
41
|
+
if (intervalMs > kMaxFrameIntervalMs) intervalMs = kMaxFrameIntervalMs;
|
|
42
|
+
g_frame_interval_ms = intervalMs;
|
|
43
|
+
}
|
|
44
|
+
int FrameScheduler::frameIntervalMs() { return g_frame_interval_ms; }
|
|
45
|
+
void FrameScheduler::setFrameRate(double fps)
|
|
46
|
+
{
|
|
47
|
+
if (fps <= 0.0) return;
|
|
48
|
+
setFrameIntervalMs(static_cast<int>(1000.0 / fps + 0.5));
|
|
49
|
+
}
|
|
50
|
+
double FrameScheduler::frameRate() { return 1000.0 / static_cast<double>(g_frame_interval_ms); }
|
|
51
|
+
int FrameScheduler::nowMs() { return millis_since_boot(); }
|
|
52
|
+
|
|
53
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <UIKit/UIKit.h>
|
|
4
|
+
|
|
5
|
+
#include "ui/node_model.h"
|
|
6
|
+
|
|
7
|
+
#include <cstdint>
|
|
8
|
+
#include <string>
|
|
9
|
+
|
|
10
|
+
@class GeaCanvasView;
|
|
11
|
+
|
|
12
|
+
@interface GeaNativeLabel : UILabel
|
|
13
|
+
@property(nonatomic, assign) BOOL geaUseBitmapFont;
|
|
14
|
+
@property(nonatomic, copy) NSString *geaBitmapText;
|
|
15
|
+
@property(nonatomic, strong) UIColor *geaBitmapColor;
|
|
16
|
+
@property(nonatomic, assign) CGFloat geaBitmapGlyphScale;
|
|
17
|
+
@property(nonatomic, assign) NSInteger geaBitmapTextDecoration;
|
|
18
|
+
@property(nonatomic, assign) BOOL geaHostedByNativeButtonTitle;
|
|
19
|
+
@end
|
|
20
|
+
|
|
21
|
+
@interface GeaNativeButton : UIButton
|
|
22
|
+
@property(nonatomic, assign) int nodeId;
|
|
23
|
+
- (void)handleTouchDown:(id)sender;
|
|
24
|
+
- (void)handleTouchDrag:(id)sender;
|
|
25
|
+
- (void)handleTouchUpInside:(id)sender;
|
|
26
|
+
- (void)handleTouchUpOutside:(id)sender;
|
|
27
|
+
- (void)handleTouchCancel:(id)sender;
|
|
28
|
+
@end
|
|
29
|
+
|
|
30
|
+
@interface GeaNativeScrollContainer : UIScrollView <UIScrollViewDelegate>
|
|
31
|
+
@property(nonatomic, assign) int nodeId;
|
|
32
|
+
@property(nonatomic, assign) BOOL syncingFromTree;
|
|
33
|
+
@property(nonatomic, strong) UIView *contentView;
|
|
34
|
+
@property(nonatomic, strong) UILabel *debugTelemetryLabel;
|
|
35
|
+
@property(nonatomic, strong) UILabel *debugTopMarkerLabel;
|
|
36
|
+
@property(nonatomic, strong) UILabel *debugBottomMarkerLabel;
|
|
37
|
+
@property(nonatomic, assign) CGFloat minObservedContentOffsetY;
|
|
38
|
+
@property(nonatomic, assign) CGFloat maxObservedContentOffsetY;
|
|
39
|
+
- (void)updateScrollTelemetryWithScale:(CGFloat)scale;
|
|
40
|
+
- (void)commitNativeScrollTopWithScale:(CGFloat)scale;
|
|
41
|
+
@end
|
|
42
|
+
|
|
43
|
+
namespace gea::ios::renderer {
|
|
44
|
+
|
|
45
|
+
UIColor *rgb565ToUIColor(gea::framework::graphics::pixel::native_t color);
|
|
46
|
+
CGFloat canvasScaleForView(UIView *view);
|
|
47
|
+
void dispatchSyntheticTap(UIView *rootView, CGPoint point);
|
|
48
|
+
bool isScrollableNode(const gea::embedded::ui::Node &node);
|
|
49
|
+
NSMutableDictionary<NSNumber *, UIView *> *nodeIdToView();
|
|
50
|
+
NSString *NSStringFromText(const std::string &value);
|
|
51
|
+
NSTextAlignment textAlignmentForStyle(int align);
|
|
52
|
+
NSMutableDictionary *textAttributes(UIFont *font, UIColor *color, int textDecoration);
|
|
53
|
+
|
|
54
|
+
void applyTextProps(GeaNativeLabel *label, const gea::embedded::ui::Node &node, CGFloat scale);
|
|
55
|
+
void applyButtonProps(GeaNativeButton *button, const gea::embedded::ui::Node &node, int nodeId, CGFloat scale);
|
|
56
|
+
void applyScrollProps(GeaNativeScrollContainer *scrollView,
|
|
57
|
+
const gea::embedded::ui::Node &node,
|
|
58
|
+
int nodeId,
|
|
59
|
+
CGFloat scale);
|
|
60
|
+
|
|
61
|
+
void syncNativeTree(UIView *parentForRoot, int rootNodeId);
|
|
62
|
+
void teardownNativeTree();
|
|
63
|
+
bool hasNativeTree();
|
|
64
|
+
|
|
65
|
+
} // namespace gea::ios::renderer
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#include "ios_renderer_internal.h"
|
|
2
|
+
|
|
3
|
+
#include "display.h"
|
|
4
|
+
#include "events.h"
|
|
5
|
+
#include "pixel.h"
|
|
6
|
+
#include "ui/tree_internal.h"
|
|
7
|
+
|
|
8
|
+
#include <algorithm>
|
|
9
|
+
#include <cmath>
|
|
10
|
+
#include <cstdlib>
|
|
11
|
+
#include <cstring>
|
|
12
|
+
|
|
13
|
+
extern "C" void gea_ios_touch_set_state(int touching, int x, int y);
|
|
14
|
+
|
|
15
|
+
namespace gea::ios::renderer {
|
|
16
|
+
|
|
17
|
+
UIColor *rgb565ToUIColor(gea::framework::graphics::pixel::native_t color)
|
|
18
|
+
{
|
|
19
|
+
// Style colours are native pixels (RGBA8888 on iOS) — unpack the full 8-bit
|
|
20
|
+
// channels so native UIKit views render true colour, not 565-quantized.
|
|
21
|
+
int r, g, b, a;
|
|
22
|
+
gea::framework::graphics::pixel::unpackNative8(color, &r, &g, &b, &a);
|
|
23
|
+
return [UIColor colorWithRed:static_cast<CGFloat>(r) / 255.0
|
|
24
|
+
green:static_cast<CGFloat>(g) / 255.0
|
|
25
|
+
blue:static_cast<CGFloat>(b) / 255.0
|
|
26
|
+
alpha:1.0];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
CGFloat canvasScaleForView(UIView *view)
|
|
30
|
+
{
|
|
31
|
+
auto *canvas = gea::platform::display::Display::canvas();
|
|
32
|
+
if (!view || !canvas || canvas->width() <= 0 || view.bounds.size.width <= 0) return 1.0;
|
|
33
|
+
return view.bounds.size.width / static_cast<CGFloat>(canvas->width());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void dispatchSyntheticTap(UIView *rootView, CGPoint point)
|
|
37
|
+
{
|
|
38
|
+
auto *canvas = gea::platform::display::Display::canvas();
|
|
39
|
+
if (!rootView || !canvas || canvas->width() <= 0 || canvas->height() <= 0) return;
|
|
40
|
+
const CGFloat scale = canvasScaleForView(rootView);
|
|
41
|
+
int x = std::clamp(static_cast<int>(std::lround(point.x / std::max<CGFloat>(scale, 0.0001))),
|
|
42
|
+
0,
|
|
43
|
+
std::max(0, canvas->width() - 1));
|
|
44
|
+
int y = std::clamp(static_cast<int>(std::lround(point.y / std::max<CGFloat>(scale, 0.0001))),
|
|
45
|
+
0,
|
|
46
|
+
std::max(0, canvas->height() - 1));
|
|
47
|
+
|
|
48
|
+
auto fireTouch = [&](gea::framework::events::TouchPhase phase, bool touching) {
|
|
49
|
+
gea_ios_touch_set_state(touching ? 1 : 0, x, y);
|
|
50
|
+
gea::framework::events::Event event{};
|
|
51
|
+
event.type = gea::framework::events::EventType::Touch;
|
|
52
|
+
event.touchPhase = phase;
|
|
53
|
+
event.touching = touching;
|
|
54
|
+
event.x = x;
|
|
55
|
+
event.y = y;
|
|
56
|
+
gea::framework::events::TouchRuntime::dispatchEvent(event);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
gea::framework::events::TouchRuntime::resetGestureState();
|
|
60
|
+
fireTouch(gea::framework::events::TouchPhase::Down, true);
|
|
61
|
+
fireTouch(gea::framework::events::TouchPhase::Up, false);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
bool isScrollableNode(const gea::embedded::ui::Node &node)
|
|
65
|
+
{
|
|
66
|
+
using gea::embedded::ui::NodeType;
|
|
67
|
+
if (node.type == NodeType::VirtualList) return node.layout.scroll_content_height > node.layout.height;
|
|
68
|
+
return node.style.overflow == 2 && node.layout.scroll_content_height > node.layout.height;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
NSMutableDictionary<NSNumber *, UIView *> *nodeIdToView()
|
|
72
|
+
{
|
|
73
|
+
static NSMutableDictionary<NSNumber *, UIView *> *map = [NSMutableDictionary new];
|
|
74
|
+
return map;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
NSString *NSStringFromText(const std::string &value)
|
|
78
|
+
{
|
|
79
|
+
return [NSString stringWithUTF8String:value.empty() ? "" : value.c_str()] ?: @"";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
NSTextAlignment textAlignmentForStyle(int align)
|
|
83
|
+
{
|
|
84
|
+
switch (align) {
|
|
85
|
+
case 1: return NSTextAlignmentCenter;
|
|
86
|
+
case 2: return NSTextAlignmentRight;
|
|
87
|
+
default: return NSTextAlignmentLeft;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static void addTextDecorationAttributes(NSMutableDictionary *attrs, int textDecoration)
|
|
92
|
+
{
|
|
93
|
+
if (!attrs) return;
|
|
94
|
+
NSNumber *style = @((NSInteger)NSUnderlineStyleSingle);
|
|
95
|
+
if (textDecoration == 1) {
|
|
96
|
+
attrs[NSUnderlineStyleAttributeName] = style;
|
|
97
|
+
} else if (textDecoration == 2) {
|
|
98
|
+
attrs[NSStrikethroughStyleAttributeName] = style;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
NSMutableDictionary *textAttributes(UIFont *font, UIColor *color, int textDecoration)
|
|
103
|
+
{
|
|
104
|
+
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
|
|
105
|
+
attrs[NSFontAttributeName] = font ?: [UIFont systemFontOfSize:16];
|
|
106
|
+
attrs[NSForegroundColorAttributeName] = color ?: UIColor.whiteColor;
|
|
107
|
+
addTextDecorationAttributes(attrs, textDecoration);
|
|
108
|
+
return attrs;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
} // namespace gea::ios::renderer
|