basalt-win32 0.2.5 → 0.2.6

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.
@@ -19,33 +19,34 @@ Win32AnimationChoreographer::~Win32AnimationChoreographer() {
19
19
  detach();
20
20
  }
21
21
 
22
- void Win32AnimationChoreographer::resume() {
23
- if (running_.exchange(true)) {
24
- return;
25
- }
26
- // Not `SetTimer`. A sixty-hertz WM_TIMER is exactly the arrangement that
27
- // stops working in an app that repaints continuously, which is to say in
28
- // every app with an animation worth running. See win32/Win32UiTimer.h.
29
- timer_ = scheduleUiTimer(kFrameIntervalMs, true, [this] { onFrame(); });
30
- }
31
-
32
- void Win32AnimationChoreographer::pause() {
33
- if (!running_.exchange(false)) {
34
- return;
22
+ void Win32AnimationChoreographer::runningChanged() {
23
+ const std::lock_guard<std::mutex> lock(timerMutex_);
24
+ const bool want = running();
25
+ if (want && timer_ == 0) {
26
+ // Not `SetTimer`. A sixty-hertz WM_TIMER is exactly the arrangement that
27
+ // stops working in an app that repaints continuously, which is to say in
28
+ // every app with an animation worth running. See win32/Win32UiTimer.h.
29
+ timer_ = scheduleUiTimer(kFrameIntervalMs, true, [this] { onFrame(); });
30
+ } else if (!want && timer_ != 0) {
31
+ // Before this returns, nothing of ours is still in flight: `cancelUiTimer`
32
+ // waits out a delivery already on a pool thread, which is what makes the
33
+ // `this` captured above safe to destroy afterwards. It does not take
34
+ // timerMutex_, so waiting here holding it cannot deadlock.
35
+ cancelUiTimer(timer_);
36
+ timer_ = 0;
35
37
  }
36
- // Before this returns, nothing of ours is still in flight: `cancelUiTimer`
37
- // waits out a delivery already on a pool thread, which is what makes the
38
- // `this` captured above safe to destroy afterwards.
39
- cancelUiTimer(timer_);
40
- timer_ = 0;
41
38
  }
42
39
 
43
40
  void Win32AnimationChoreographer::detach() {
44
- pause();
41
+ const std::lock_guard<std::mutex> lock(timerMutex_);
42
+ if (timer_ != 0) {
43
+ cancelUiTimer(timer_);
44
+ timer_ = 0;
45
+ }
45
46
  }
46
47
 
47
48
  void Win32AnimationChoreographer::onFrame() {
48
- if (!running_.load()) {
49
+ if (!running()) {
49
50
  return;
50
51
  }
51
52
  // A steady clock rather than the wall clock: an animation must not jump when
@@ -53,7 +54,7 @@ void Win32AnimationChoreographer::onFrame() {
53
54
  const auto now = std::chrono::steady_clock::now().time_since_epoch();
54
55
  const auto milliseconds =
55
56
  std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(now);
56
- onAnimationFrame(static_cast<facebook::react::AnimationTimestamp>(milliseconds.count()));
57
+ deliverFrame(static_cast<facebook::react::AnimationTimestamp>(milliseconds.count()));
57
58
  }
58
59
 
59
60
  } // namespace basalt
@@ -28,21 +28,20 @@
28
28
 
29
29
  #pragma once
30
30
 
31
- #include <react/renderer/animationbackend/AnimationChoreographer.h>
31
+ #include "DisplayChoreographer.h"
32
32
 
33
- #include <atomic>
34
33
  #include <cstdint>
34
+ #include <mutex>
35
35
 
36
36
  namespace basalt {
37
37
 
38
- class Win32AnimationChoreographer final : public facebook::react::AnimationChoreographer {
38
+ // Also what paces requestAnimationFrame here; core/DisplayChoreographer.h
39
+ // decides when the timer runs.
40
+ class Win32AnimationChoreographer final : public DisplayChoreographer {
39
41
  public:
40
42
  Win32AnimationChoreographer() = default;
41
43
  ~Win32AnimationChoreographer() override;
42
44
 
43
- void resume() override;
44
- void pause() override;
45
-
46
45
  // Stops the timer for good. Called on the way out, before the manager this
47
46
  // feeds is released.
48
47
  void detach();
@@ -50,8 +49,14 @@ class Win32AnimationChoreographer final : public facebook::react::AnimationChore
50
49
  // Called from the timer, on the UI thread.
51
50
  void onFrame();
52
51
 
52
+ protected:
53
+ // Starts or stops the timer to match running(). Any thread.
54
+ void runningChanged() override;
55
+
53
56
  private:
54
- std::atomic<bool> running_{false};
57
+ // runningChanged() can arrive from the JS thread and detach() from the UI
58
+ // thread; the timer id is the one thing they share.
59
+ std::mutex timerMutex_;
55
60
  // A `basalt::UiTimerId` rather than a `SetTimer` handle, and not for
56
61
  // tidiness: WM_TIMER ranks below WM_PAINT, so on this timer an app that
57
62
  // repaints continuously -- anything with a `<Canvas>` -- stopped getting
@@ -38,6 +38,7 @@
38
38
 
39
39
  #include "Win32AnimationChoreographer.h"
40
40
  #include "CrashHandler.h"
41
+ #include "AnimationFrames.h"
41
42
  #include "AppIdentity.h"
42
43
  #include "AppPaths.h"
43
44
  #include "DevMenu.h"
@@ -701,6 +702,15 @@ void installBindings(facebook::jsi::Runtime &runtime) {
701
702
  // runtime. See core/TurboModuleProxy.h.
702
703
  basalt::installTurboModuleProxy(runtime);
703
704
  basalt::installExpoRuntime(runtime);
705
+ // requestAnimationFrame at the display's rate, over React Native's setTimeout(0).
706
+ // After TimerManager's globals, which ReactInstance installs just before this.
707
+ // See core/AnimationFrames.h.
708
+ basalt::AnimationFrames::install(
709
+ runtime, gHost.choreographer, [](std::function<void(facebook::jsi::Runtime &)> task) {
710
+ if (gHost.reactHost != nullptr) {
711
+ gHost.reactHost->runOnRuntimeScheduler(std::move(task));
712
+ }
713
+ });
704
714
  }
705
715
 
706
716
  std::shared_ptr<const ContextContainer> makeContextContainer() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "basalt-win32",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "The Windows view layer for basalt-core: a Win32 and Direct2D view layer, a Fabric mounting manager, and a host. Everything behind them is in basalt-core.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -22,6 +22,6 @@
22
22
  "react-native": "*"
23
23
  },
24
24
  "dependencies": {
25
- "basalt-core": "0.2.5"
25
+ "basalt-core": "0.2.6"
26
26
  }
27
27
  }