@geastack/core 0.1.35 → 0.1.37

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/gea_app_entry.cpp CHANGED
@@ -297,24 +297,31 @@ void Application::frame(int timestampMs)
297
297
  gea::host::runAnimationFrameCallbacks(static_cast<double>(timestampMs));
298
298
  applicationFramePhaseSet(ApplicationFramePhase::CallbackMicrotasks);
299
299
  generated::drainMicrotasks();
300
+ recordFramePhase(ApplicationFramePhase::AnimationFrameCallbacks, phaseClockUs() - startUs);
300
301
  // The build already proves whether network services are reachable. Keep their
301
302
  // callback pumps out of offline frame loops, while still servicing local workers.
302
303
  #if !defined(GEA_EMBEDDED_NETWORK_SERVICES_DISABLED) || !GEA_EMBEDDED_NETWORK_SERVICES_DISABLED
303
304
  applicationFramePhaseSet(ApplicationFramePhase::WebSocketCallbacks);
305
+ startUs = phaseClockUs();
304
306
  gea::host::websocket::runCallbacks();
307
+ recordFramePhase(ApplicationFramePhase::WebSocketCallbacks, phaseClockUs() - startUs);
305
308
  applicationFramePhaseSet(ApplicationFramePhase::RtcCallbacks);
309
+ startUs = phaseClockUs();
306
310
  gea::host::rtc::runCallbacks();
311
+ recordFramePhase(ApplicationFramePhase::RtcCallbacks, phaseClockUs() - startUs);
307
312
  #else
308
313
  gea::host::workers::Context::runMainPending();
309
314
  #endif
310
315
  applicationFramePhaseSet(ApplicationFramePhase::VideoPresentation);
316
+ startUs = phaseClockUs();
311
317
  gea::host::video::presentFrames();
318
+ recordFramePhase(ApplicationFramePhase::VideoPresentation, phaseClockUs() - startUs);
312
319
  #if !defined(GEA_EMBEDDED_NETWORK_SERVICES_DISABLED) || !GEA_EMBEDDED_NETWORK_SERVICES_DISABLED
313
320
  applicationFramePhaseSet(ApplicationFramePhase::HttpRequests);
321
+ startUs = phaseClockUs();
314
322
  gea::host::http::runRequests();
323
+ recordFramePhase(ApplicationFramePhase::HttpRequests, phaseClockUs() - startUs);
315
324
  #endif
316
- recordFramePhase(ApplicationFramePhase::AnimationFrameCallbacks, phaseClockUs() - startUs);
317
-
318
325
  // Apply the coalesced style recompute for everything changed above, so layout
319
326
  // and render below see final styles. Measured as its own phase: a city/theme
320
327
  // class change near the root cascades a full-subtree recompute here, and it was
@@ -0,0 +1,33 @@
1
+ #pragma once
2
+
3
+ // A layer painted UNDER the retained UI tree, in the same flush.
4
+ //
5
+ // A native renderer that owns the whole screen (gea3d) cannot stream its frame
6
+ // to the panel on its own while a UI tree is mounted: the UI's next dirty-rect
7
+ // flush copies the framebuffer, which never held that frame, over it. Instead
8
+ // it registers a painter here and marks the canvas dirty; the tree's refresh
9
+ // then calls the painter for each dirty rect (clipped to it, drawing into the
10
+ // bound canvas) before it replays the nodes, so the HUD lands on top and the
11
+ // panel sees one composited image.
12
+ namespace gea::framework::display
13
+ {
14
+ class Underlay
15
+ {
16
+ public:
17
+ // Fills [x0, x1] x [y0, y1] (inclusive, screen coordinates) of
18
+ // Display::canvas(), honouring its current clip.
19
+ using Paint = void (*)(int x0, int y0, int x1, int y1, void *user);
20
+
21
+ // True when a retained UI tree is mounted and refreshes on its own, so a
22
+ // registered underlay will be painted. False for direct-canvas apps,
23
+ // which present their frames themselves.
24
+ static bool composited();
25
+ // Registers the painter for the screen area it covers; replaces any
26
+ // previous one. The caller marks the area dirty to have it repainted.
27
+ static void set(Paint paint, void *user, int x0, int y0, int x1, int y1);
28
+ static void clear();
29
+ static bool active();
30
+ // Paints the part of [x0, x1] x [y0, y1] the underlay covers.
31
+ static void paint(int x0, int y0, int x1, int y1);
32
+ };
33
+ } // namespace gea::framework::display
package/index.d.ts CHANGED
@@ -270,6 +270,9 @@ export interface Style {
270
270
  bottom?: StyleLength
271
271
  zIndex?: number
272
272
  backgroundColor?: string
273
+ objectFit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
274
+ /** CSS image alignment on web; embedded image fitting currently centers the image. */
275
+ objectPosition?: string
273
276
  color?: string
274
277
  opacity?: number
275
278
  blinkInterval?: number
@@ -655,6 +658,8 @@ export interface GeaEmbeddedImage {
655
658
  readonly height: number
656
659
  readonly frameCount: number
657
660
  readonly isAnimated: boolean
661
+ /** Decode deferred pixels into the shared image cache; false on failure. */
662
+ decode(): boolean
658
663
  play(): void
659
664
  pause(): void
660
665
  seek(frame: number): void
@@ -2156,8 +2161,9 @@ export interface PcmAudioStream {
2156
2161
  /** Capture and upload on the native socket worker, independently of UI callbacks. */
2157
2162
  pipeTo(socket: WebSocketInstance, prefix: string, suffix: string): void
2158
2163
  /** Decode matching PCM packets on the native receive worker; control messages still reach JS. */
2159
- receiveFrom(socket: WebSocketInstance, prefix: string, suffix: string): void
2160
- /** Read the next 40ms capture block, or an empty string if not ready. */
2164
+ /** Startup delay defaults to 200 ms; use zero for an upstream A/V playback clock. */
2165
+ receiveFrom(socket: WebSocketInstance, prefix: string, suffix: string, startupMs?: number): void
2166
+ /** Read the next 20ms capture block, or an empty string if not ready. */
2161
2167
  readBase64(): string
2162
2168
  writeBase64(data: string): void
2163
2169
  resetPlayback(interrupted?: boolean): void
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geastack/core",
3
- "version": "0.1.35",
3
+ "version": "0.1.37",
4
4
  "description": "GeaStack app API, reactivity headers, runtime sources, and type declarations.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -65,8 +65,8 @@
65
65
  "@babel/types": "^7.23.0",
66
66
  "@geajs/core": "1.5.1",
67
67
  "@geajs/vite-plugin": "1.5.0",
68
- "@geastack/compiler": "^1.0.20",
69
- "@geastack/geatsc-plugin-gea": "^0.1.15",
68
+ "@geastack/compiler": "^1.0.22",
69
+ "@geastack/geatsc-plugin-gea": "^0.1.19",
70
70
  "opentype.js": "^2.0.0",
71
71
  "vite": "^8.0.0"
72
72
  }
package/runtime.cpp CHANGED
@@ -125,9 +125,10 @@ void run_app_frame(int timestampMs, void *context)
125
125
  if (!animationsScanned) {
126
126
  animationsScanned = true;
127
127
  gea::css::DeclarativeAnimations::scanAndStart(nowMs);
128
- gea::embedded::ui::StyleSheet::instance().startCssAnimations(nowMs);
129
128
  }
130
129
 
130
+ // Start CSS tracks added by later conditional mounts, retaining existing timelines.
131
+ gea::embedded::ui::StyleSheet::instance().startCssAnimations(nowMs);
131
132
  gea::css::AnimationEngine::instance().tick(nowMs);
132
133
  // Render-only while settings overlays the frozen application.
133
134
  const bool refreshOnly = SettingsSurface::instance().active();
@@ -66,8 +66,11 @@ const embeddedFontExtraCodepoints = [
66
66
  0x00a9, // copyright
67
67
  0x00ab, // left double guillemet
68
68
  0x00b0, // degree
69
+ 0x00b1, // plus-minus
70
+ 0x00b5, // micro sign (µs, µF)
69
71
  0x00b7, // middle dot (common UI separator; only appears in dynamic strings)
70
72
  0x00bb, // right double guillemet
73
+ 0x00d7, // multiplication sign (close buttons, 2× scale)
71
74
  0x2010, // hyphen
72
75
  0x2011, // non-breaking hyphen
73
76
  0x2013, // en dash
@@ -120,6 +120,14 @@ gea_native_object_rel() {
120
120
  printf '%s.%s.o\n' "$rel" "$kind"
121
121
  }
122
122
 
123
+ gea_native_input_is_newer() {
124
+ # macOS Bash 3.2's builtin -nt compares whole seconds. Generated sources
125
+ # (especially consecutive mutations of one path) can change after an object
126
+ # was built within that same second. The system test preserves subsecond
127
+ # timestamps for sources, headers and objects that require relinking.
128
+ /bin/test "$1" -nt "$2"
129
+ }
130
+
123
131
  gea_native_depfile_has_newer_input() {
124
132
  local depfile="$1"
125
133
  local obj="$2"
@@ -128,7 +136,7 @@ gea_native_depfile_has_newer_input() {
128
136
  while IFS= read -r dep; do
129
137
  [[ -n "$dep" ]] || continue
130
138
  dep="${dep//\\ / }"
131
- if [[ -e "$dep" && "$dep" -nt "$obj" ]]; then
139
+ if [[ -e "$dep" ]] && gea_native_input_is_newer "$dep" "$obj"; then
132
140
  return 0
133
141
  fi
134
142
  done < <(sed -e ':again' -e '/\\$/N' -e 's/\\\n/ /' -e 'tagain' -e 's/^[^:]*: //' "$depfile" | tr ' ' '\n' | sed -e 's/\\$//' -e '/^$/d')
@@ -140,7 +148,7 @@ gea_native_needs_compile() {
140
148
  local obj="$2"
141
149
  [[ -f "$obj" ]] || return 0
142
150
  [[ -f "$obj.d" ]] || return 0
143
- [[ "$src" -nt "$obj" ]] && return 0
151
+ gea_native_input_is_newer "$src" "$obj" && return 0
144
152
  gea_native_depfile_has_newer_input "$obj.d" "$obj" && return 0
145
153
  return 1
146
154
  }
@@ -207,7 +215,7 @@ gea_native_link_needs_rebuild() {
207
215
  [[ "$(cat "$sigFile")" == "$signature" ]] || return 0
208
216
  local obj
209
217
  for obj in "${GEA_NATIVE_OBJECTS[@]}"; do
210
- [[ "$obj" -nt "$output" ]] && return 0
218
+ gea_native_input_is_newer "$obj" "$output" && return 0
211
219
  done
212
220
  return 1
213
221
  }