basalt-gtk 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/cli/runLinux.js +29 -0
- package/cli/shared.js +75 -0
- package/native/CMakeLists.txt +362 -0
- package/native/gtk/ColorSchemeGtk.cpp +58 -0
- package/native/gtk/ComponentRegistryGtk.cpp +101 -0
- package/native/gtk/FontRegistryFontconfig.cpp +127 -0
- package/native/gtk/GtkAnimationChoreographer.cpp +73 -0
- package/native/gtk/GtkAnimationChoreographer.h +49 -0
- package/native/gtk/GtkDropTarget.cpp +269 -0
- package/native/gtk/GtkDropTarget.h +40 -0
- package/native/gtk/GtkFocus.cpp +296 -0
- package/native/gtk/GtkFocus.h +113 -0
- package/native/gtk/GtkImageLoader.cpp +128 -0
- package/native/gtk/GtkImageLoader.h +87 -0
- package/native/gtk/GtkKeyEvents.cpp +91 -0
- package/native/gtk/GtkKeyEvents.h +21 -0
- package/native/gtk/GtkMenuBar.cpp +45 -0
- package/native/gtk/GtkMountingManager.cpp +1027 -0
- package/native/gtk/GtkMountingManager.h +146 -0
- package/native/gtk/GtkRunLoopObserver.cpp +77 -0
- package/native/gtk/GtkRunLoopObserver.h +41 -0
- package/native/gtk/GtkScrollView.cpp +626 -0
- package/native/gtk/GtkScrollView.h +209 -0
- package/native/gtk/GtkSkiaContext.cpp +248 -0
- package/native/gtk/GtkSkiaContext.h +62 -0
- package/native/gtk/GtkSkiaModule.cpp +80 -0
- package/native/gtk/GtkSkiaModule.h +51 -0
- package/native/gtk/GtkSkiaPeer.cpp +285 -0
- package/native/gtk/GtkSkiaPeer.h +63 -0
- package/native/gtk/GtkTextInput.cpp +428 -0
- package/native/gtk/GtkTextInput.h +123 -0
- package/native/gtk/GtkTextPeer.cpp +425 -0
- package/native/gtk/GtkTextPeer.h +87 -0
- package/native/gtk/GtkTitleBar.cpp +273 -0
- package/native/gtk/GtkTitleBar.h +96 -0
- package/native/gtk/GtkTitleBarLayout.cpp +45 -0
- package/native/gtk/GtkTitleBarLayout.h +36 -0
- package/native/gtk/GtkTouchDispatcher.cpp +671 -0
- package/native/gtk/GtkTouchDispatcher.h +139 -0
- package/native/gtk/GtkWindowControl.cpp +223 -0
- package/native/gtk/GtkWindowModule.cpp +194 -0
- package/native/gtk/GtkWindowModule.h +62 -0
- package/native/gtk/PangoTextLayout.cpp +295 -0
- package/native/gtk/PangoTextLayout.h +54 -0
- package/native/gtk/PangoTextLayoutManager.cpp +140 -0
- package/native/gtk/PlatformServicesGtk.cpp +583 -0
- package/native/gtk/RnView.cpp +1407 -0
- package/native/gtk/RnView.h +339 -0
- package/native/gtk/demo_layout_gtk.cpp +57 -0
- package/native/gtk/main_gtk.cpp +1981 -0
- package/native/gtk/mount_harness_gtk.cpp +143 -0
- package/native/tests/TestMainGtk.cpp +25 -0
- package/native/tests/notification_stub.cpp +103 -0
- package/native/tests/test_accessibility.cpp +251 -0
- package/native/tests/test_focus.cpp +194 -0
- package/native/tests/test_hittest.cpp +242 -0
- package/native/tests/test_image.cpp +135 -0
- package/native/tests/test_key_events_gtk.cpp +112 -0
- package/native/tests/test_mounting.cpp +415 -0
- package/native/tests/test_scrollview.cpp +258 -0
- package/native/tests/test_skia_texture.cpp +120 -0
- package/native/tests/test_text.cpp +147 -0
- package/native/tests/test_textinput.cpp +598 -0
- package/native/tests/test_titlebar.cpp +137 -0
- package/native/tests/test_titlebar_drag.cpp +138 -0
- package/native/tests/test_version.cpp +49 -0
- package/native/tests/test_view.cpp +162 -0
- package/native/tests/test_viewprops.cpp +254 -0
- package/package.json +26 -0
- package/react-native.config.js +21 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#include "GtkSkiaPeer.h"
|
|
2
|
+
|
|
3
|
+
#include "GtkSkiaModule.h"
|
|
4
|
+
#include "RnView.h"
|
|
5
|
+
#include "SkiaPictureViewComponent.h"
|
|
6
|
+
|
|
7
|
+
#include "PlatformServices.h"
|
|
8
|
+
|
|
9
|
+
#include "include/core/SkCanvas.h"
|
|
10
|
+
#include "include/core/SkColor.h"
|
|
11
|
+
#include "include/core/SkImageInfo.h"
|
|
12
|
+
#include "include/core/SkPixmap.h"
|
|
13
|
+
#include "include/core/SkSurface.h"
|
|
14
|
+
|
|
15
|
+
#include "RNSkPictureView.h"
|
|
16
|
+
#include "RNSkView.h"
|
|
17
|
+
|
|
18
|
+
#include <glog/logging.h>
|
|
19
|
+
|
|
20
|
+
#include <algorithm>
|
|
21
|
+
#include <cmath>
|
|
22
|
+
#include <memory>
|
|
23
|
+
#include <string>
|
|
24
|
+
#include <string_view>
|
|
25
|
+
#include <unordered_map>
|
|
26
|
+
#include <utility>
|
|
27
|
+
|
|
28
|
+
namespace basalt {
|
|
29
|
+
namespace {
|
|
30
|
+
|
|
31
|
+
// The surface a `<Canvas>` renders into, and the thing that hands it over.
|
|
32
|
+
//
|
|
33
|
+
// Only one interface here, where the Win32 peer needs two: this host's view
|
|
34
|
+
// already draws a texture, so presenting is a call rather than a drawing path
|
|
35
|
+
// of its own.
|
|
36
|
+
class GtkSkiaCanvas final : public RNSkia::RNSkCanvasProvider {
|
|
37
|
+
public:
|
|
38
|
+
GtkSkiaCanvas(std::function<void()> requestRedraw,
|
|
39
|
+
std::shared_ptr<RNSkia::RNSkPlatformContext> context,
|
|
40
|
+
RnView *view)
|
|
41
|
+
: RNSkia::RNSkCanvasProvider(std::move(requestRedraw)),
|
|
42
|
+
context_(std::move(context)) {
|
|
43
|
+
// Weakly, because the widget belongs to the mounting registry and is
|
|
44
|
+
// destroyed on a Delete mutation -- which can happen while a picture from
|
|
45
|
+
// the frame before is still on its way to the main thread. A strong
|
|
46
|
+
// reference here would keep a disposed widget alive to be drawn into;
|
|
47
|
+
// a raw pointer would be a use-after-free on the same path.
|
|
48
|
+
g_weak_ref_init(&view_, view);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// No `override`: RNSkCanvasProvider has no virtual destructor. This still
|
|
52
|
+
// runs, because the shared_ptr is built by make_shared<GtkSkiaCanvas> and
|
|
53
|
+
// records the concrete deleter then -- not because anything upcasts safely.
|
|
54
|
+
~GtkSkiaCanvas() { g_weak_ref_clear(&view_); }
|
|
55
|
+
|
|
56
|
+
// --- RNSkCanvasProvider ---------------------------------------------------
|
|
57
|
+
//
|
|
58
|
+
// "Scaled", in the package's vocabulary, means pixels rather than points:
|
|
59
|
+
// the Metal provider multiplies by the pixel density in setSize and reports
|
|
60
|
+
// the product here. Same here, so that `makeImageSnapshot` -- which builds
|
|
61
|
+
// an offscreen provider out of these two numbers -- gets the resolution it
|
|
62
|
+
// would have got on any other host.
|
|
63
|
+
|
|
64
|
+
int getWidth() override { return pixelWidth_; }
|
|
65
|
+
|
|
66
|
+
int getHeight() override { return pixelHeight_; }
|
|
67
|
+
|
|
68
|
+
bool renderToCanvas(const std::function<void(SkCanvas *)> &callback) override {
|
|
69
|
+
if (!isUiThread()) {
|
|
70
|
+
// GdkTexture is a GObject and a widget may only be touched from the
|
|
71
|
+
// thread that owns the main context, so the handover below cannot happen
|
|
72
|
+
// here. Ask for a redraw and let it arrive on the right thread -- the
|
|
73
|
+
// same answer the package's Metal provider gives off the main thread.
|
|
74
|
+
_requestRedraw();
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (surface_ == nullptr) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
callback(surface_->getCanvas());
|
|
81
|
+
|
|
82
|
+
RnView *view = static_cast<RnView *>(g_weak_ref_get(&view_));
|
|
83
|
+
if (view == nullptr) {
|
|
84
|
+
// The widget went away between the picture and this. Not an error: a
|
|
85
|
+
// canvas unmounted mid-frame does exactly that.
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
SkPixmap pixels;
|
|
90
|
+
if (!surface_->peekPixels(&pixels)) {
|
|
91
|
+
// Only a GPU-backed surface cannot be peeked, and this one is raster by
|
|
92
|
+
// construction. A line rather than a silent blank frame, for the day
|
|
93
|
+
// that changes.
|
|
94
|
+
LOG(WARNING) << "react-native-skia: a <Canvas> surface could not be read back";
|
|
95
|
+
g_object_unref(view);
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Copied, not referenced. GdkMemoryTexture takes the bytes as its own and
|
|
100
|
+
// requires them not to change afterwards, and these are about to: the next
|
|
101
|
+
// frame draws into this very surface. The copy is what makes the texture a
|
|
102
|
+
// snapshot rather than a window onto a buffer being overwritten.
|
|
103
|
+
GBytes *bytes = g_bytes_new(pixels.addr(), pixels.computeByteSize());
|
|
104
|
+
// N32Premul is premultiplied BGRA on a little-endian machine, which is
|
|
105
|
+
// what this format names. Skia and GDK agree here, so the copy above is a
|
|
106
|
+
// memcpy rather than a conversion -- worth stating, because if that ever
|
|
107
|
+
// stops being true the picture goes blue and nothing says why.
|
|
108
|
+
GdkTexture *texture = gdk_memory_texture_new(pixelWidth_,
|
|
109
|
+
pixelHeight_,
|
|
110
|
+
GDK_MEMORY_B8G8R8A8_PREMULTIPLIED,
|
|
111
|
+
bytes,
|
|
112
|
+
pixels.rowBytes());
|
|
113
|
+
g_bytes_unref(bytes);
|
|
114
|
+
|
|
115
|
+
// STRETCH, because the surface was made at exactly this view's size: there
|
|
116
|
+
// is nothing to fit. Any other mode would be a no-op that costs a
|
|
117
|
+
// comparison, and would quietly letterbox if the two ever disagreed.
|
|
118
|
+
rn_view_set_texture(view, texture, RN_IMAGE_FIT_STRETCH);
|
|
119
|
+
g_object_unref(texture);
|
|
120
|
+
g_object_unref(view);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// In points, as the package's own providers take it: the density is applied
|
|
125
|
+
// here rather than by the caller.
|
|
126
|
+
void setSize(int width, int height) {
|
|
127
|
+
const float density = context_->getPixelDensity();
|
|
128
|
+
const int pixelWidth =
|
|
129
|
+
std::max(0, static_cast<int>(std::lround(static_cast<float>(width) * density)));
|
|
130
|
+
const int pixelHeight =
|
|
131
|
+
std::max(0, static_cast<int>(std::lround(static_cast<float>(height) * density)));
|
|
132
|
+
if (pixelWidth == pixelWidth_ && pixelHeight == pixelHeight_) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
pixelWidth_ = pixelWidth;
|
|
136
|
+
pixelHeight_ = pixelHeight;
|
|
137
|
+
surface_ = nullptr;
|
|
138
|
+
if (pixelWidth_ > 0 && pixelHeight_ > 0) {
|
|
139
|
+
surface_ = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(pixelWidth_, pixelHeight_));
|
|
140
|
+
if (surface_ == nullptr) {
|
|
141
|
+
LOG(WARNING) << "react-native-skia: could not make a " << pixelWidth_ << "x"
|
|
142
|
+
<< pixelHeight_ << " surface for a <Canvas>";
|
|
143
|
+
} else {
|
|
144
|
+
// A raster surface is not promised zeroed pixels, and there is a
|
|
145
|
+
// window between this and the first picture in which the canvas is
|
|
146
|
+
// drawn. Uninitialised memory is a striking thing to put on screen.
|
|
147
|
+
surface_->getCanvas()->clear(SK_ColorTRANSPARENT);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// The picture drawn at the old size has to be drawn again at this one, and
|
|
151
|
+
// nothing else would ask.
|
|
152
|
+
_requestRedraw();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private:
|
|
156
|
+
std::shared_ptr<RNSkia::RNSkPlatformContext> context_;
|
|
157
|
+
GWeakRef view_;
|
|
158
|
+
|
|
159
|
+
sk_sp<SkSurface> surface_;
|
|
160
|
+
int pixelWidth_ = 0;
|
|
161
|
+
int pixelHeight_ = 0;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// The package's view, holding the canvas above.
|
|
165
|
+
//
|
|
166
|
+
// `RNSkAppleView.h` is this in template form and cannot be included here: its
|
|
167
|
+
// first import is the Apple platform context, which is Objective-C++ over an
|
|
168
|
+
// RCTBridge. A `<Canvas>` needs exactly one RNSkView subclass, so this is that
|
|
169
|
+
// one rather than a template over the one.
|
|
170
|
+
class GtkSkiaPictureView final : public RNSkia::RNSkPictureView {
|
|
171
|
+
public:
|
|
172
|
+
GtkSkiaPictureView(const std::shared_ptr<RNSkia::RNSkPlatformContext> &context, RnView *view)
|
|
173
|
+
: RNSkia::RNSkPictureView(
|
|
174
|
+
context,
|
|
175
|
+
std::make_shared<GtkSkiaCanvas>(
|
|
176
|
+
// Bound before the base class is constructed, exactly as the
|
|
177
|
+
// package's own views bind it: nothing calls it until a
|
|
178
|
+
// picture arrives, by which time this object is whole.
|
|
179
|
+
std::bind(&RNSkia::RNSkView::requestRedraw, this),
|
|
180
|
+
context,
|
|
181
|
+
view)) {}
|
|
182
|
+
|
|
183
|
+
// `getCanvasProvider` is protected on RNSkView, which is why this is a
|
|
184
|
+
// member rather than a cast at the call site.
|
|
185
|
+
std::shared_ptr<GtkSkiaCanvas> canvas() {
|
|
186
|
+
return std::static_pointer_cast<GtkSkiaCanvas>(getCanvasProvider());
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
struct Attached {
|
|
191
|
+
std::shared_ptr<GtkSkiaPictureView> view;
|
|
192
|
+
// The id it was registered under, kept so the unregister matches: a view
|
|
193
|
+
// whose nativeID changed would otherwise leave the old registration behind,
|
|
194
|
+
// pointing at a surface nothing draws into.
|
|
195
|
+
size_t nativeId = 0;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
std::unordered_map<facebook::react::Tag, Attached> &attached() {
|
|
199
|
+
static std::unordered_map<facebook::react::Tag, Attached> map;
|
|
200
|
+
return map;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// `<Canvas>` stringifies a counter into nativeID. Anything else on a
|
|
204
|
+
// SkiaPictureView is not ours to interpret.
|
|
205
|
+
bool parseNativeId(const char *text, size_t &out) {
|
|
206
|
+
if (text == nullptr || *text == '\0') {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
const std::string value(text);
|
|
210
|
+
try {
|
|
211
|
+
size_t consumed = 0;
|
|
212
|
+
const unsigned long long parsed = std::stoull(value, &consumed);
|
|
213
|
+
if (consumed != value.size()) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
out = static_cast<size_t>(parsed);
|
|
217
|
+
return true;
|
|
218
|
+
} catch (const std::exception &) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
} // namespace
|
|
224
|
+
|
|
225
|
+
bool applySkiaCanvas(GtkWidget *view, const facebook::react::ShadowView &shadowView) {
|
|
226
|
+
if (view == nullptr || shadowView.componentName == nullptr ||
|
|
227
|
+
std::string_view(shadowView.componentName) !=
|
|
228
|
+
facebook::react::SkiaPictureViewComponentName) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const auto tag = shadowView.tag;
|
|
233
|
+
// In points, which is what the canvas wants: it applies the pixel density
|
|
234
|
+
// itself, and passing pixels would square it on a scaled display.
|
|
235
|
+
const auto &frame = shadowView.layoutMetrics.frame;
|
|
236
|
+
const int width = static_cast<int>(frame.size.width);
|
|
237
|
+
const int height = static_cast<int>(frame.size.height);
|
|
238
|
+
|
|
239
|
+
size_t nativeId = 0;
|
|
240
|
+
if (!parseNativeId(rn_view_get_native_id(RN_VIEW(view)), nativeId)) {
|
|
241
|
+
// Not an error: a SkiaPictureView can mount before its nativeID has been
|
|
242
|
+
// applied, and the next updateView carries it.
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
RNSkia::RNSkManager *manager = GtkSkiaModule::manager();
|
|
247
|
+
if (manager == nullptr) {
|
|
248
|
+
LOG(WARNING) << "SkiaPictureView tag " << tag
|
|
249
|
+
<< " mounted before RNSkiaModule.install ran, so it has no canvas";
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
auto &entry = attached()[tag];
|
|
254
|
+
if (entry.view == nullptr) {
|
|
255
|
+
entry.view = std::make_shared<GtkSkiaPictureView>(manager->getPlatformContext(),
|
|
256
|
+
RN_VIEW(view));
|
|
257
|
+
entry.nativeId = nativeId;
|
|
258
|
+
manager->setSkiaView(nativeId, entry.view);
|
|
259
|
+
LOG(INFO) << "SkiaPictureView tag " << tag << " registered as Skia view " << nativeId;
|
|
260
|
+
} else if (entry.nativeId != nativeId) {
|
|
261
|
+
// The id moved. Re-register rather than leave the manager pointing the old
|
|
262
|
+
// surface at the new id's pictures.
|
|
263
|
+
manager->unregisterSkiaView(entry.nativeId);
|
|
264
|
+
entry.nativeId = nativeId;
|
|
265
|
+
manager->setSkiaView(nativeId, entry.view);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (width > 0 && height > 0) {
|
|
269
|
+
entry.view->canvas()->setSize(width, height);
|
|
270
|
+
}
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
void forgetSkiaCanvas(facebook::react::Tag tag) {
|
|
275
|
+
auto it = attached().find(tag);
|
|
276
|
+
if (it == attached().end()) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (RNSkia::RNSkManager *manager = GtkSkiaModule::manager()) {
|
|
280
|
+
manager->unregisterSkiaView(it->second.nativeId);
|
|
281
|
+
}
|
|
282
|
+
attached().erase(it);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
} // namespace basalt
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// The GTK half of a `<Canvas>`: a raster surface, handed over as a texture.
|
|
2
|
+
//
|
|
3
|
+
// The third of these, and the shortest, because this host already had the
|
|
4
|
+
// seam. AppKit gives the package a CAMetalLayer and lets it present; Win32 has
|
|
5
|
+
// neither a layer tree nor a view that is a window, so win32/Win32SkiaPeer.h
|
|
6
|
+
// invents `RnWin32Painter` and draws inside the Direct2D walk. Here an RnView
|
|
7
|
+
// is a real GtkWidget that already knows how to draw a `GdkTexture` -- it is
|
|
8
|
+
// how `<Image>` works -- so a canvas is a view whose texture is replaced every
|
|
9
|
+
// frame, and `rn_view_set_texture` is the whole presentation path.
|
|
10
|
+
//
|
|
11
|
+
// What that buys is the same thing the Win32 peer argues for, and here it
|
|
12
|
+
// comes from GTK rather than from us: the canvas is clipped by `overflow:
|
|
13
|
+
// hidden`, moved by a ScrollView's offset, faded by `opacity` and turned by
|
|
14
|
+
// `transform`, because the widget above it does those things to its own
|
|
15
|
+
// children. None of it is code in this file.
|
|
16
|
+
//
|
|
17
|
+
// ## Raster, and what a GPU path would have to answer
|
|
18
|
+
//
|
|
19
|
+
// Each frame is drawn by Skia into a CPU surface and copied once into a
|
|
20
|
+
// GdkTexture. The archives carry Ganesh over GL -- `skia_use_gl=true` and
|
|
21
|
+
// `skia_use_egl=true` -- so the GPU is not missing, it is unclaimed, and the
|
|
22
|
+
// reason is in gtk/GtkSkiaContext.h: Ganesh wants a `GrDirectContext` built on
|
|
23
|
+
// a current GL context, and GtkGLArea only makes one current inside its own
|
|
24
|
+
// `render` signal. Claiming it means inverting who calls whom -- `requestRedraw`
|
|
25
|
+
// becoming `gtk_gl_area_queue_render`, and the package's draw running inside
|
|
26
|
+
// GTK's callback rather than when the picture arrives. That is a design
|
|
27
|
+
// question rather than a port, and it replaces this file without touching
|
|
28
|
+
// anything that includes it.
|
|
29
|
+
//
|
|
30
|
+
// The cost of raster meanwhile is one copy per frame, in the size of the
|
|
31
|
+
// canvas rather than the size of the app.
|
|
32
|
+
|
|
33
|
+
#pragma once
|
|
34
|
+
|
|
35
|
+
#include <react/renderer/core/ReactPrimitives.h>
|
|
36
|
+
#include <react/renderer/mounting/ShadowView.h>
|
|
37
|
+
|
|
38
|
+
#include <gtk/gtk.h>
|
|
39
|
+
|
|
40
|
+
namespace basalt {
|
|
41
|
+
|
|
42
|
+
// Gives `view` a Skia canvas if `shadowView` is a SkiaPictureView, updating its
|
|
43
|
+
// size if it already has one. False when the component is something else, so
|
|
44
|
+
// the caller can treat this as a filter rather than asking twice.
|
|
45
|
+
//
|
|
46
|
+
// No repaint callback, where the Win32 one needs one: setting a texture on a
|
|
47
|
+
// widget queues its own redraw, because that is what `gtk_widget_queue_draw`
|
|
48
|
+
// is for and `rn_view_set_texture` already calls it. Windows repaints on
|
|
49
|
+
// demand and had to be told; GTK does not.
|
|
50
|
+
//
|
|
51
|
+
// Safe to call before `install` has run: without a manager there is nothing to
|
|
52
|
+
// register with, so it says so in the log and leaves the view alone rather
|
|
53
|
+
// than building a surface no picture could ever reach.
|
|
54
|
+
bool applySkiaCanvas(GtkWidget *view, const facebook::react::ShadowView &shadowView);
|
|
55
|
+
|
|
56
|
+
// Unregisters the canvas for `tag`, if it had one. Called when the mounting
|
|
57
|
+
// walk forgets a tag, which is the one moment a view is known to be finished
|
|
58
|
+
// with -- and it matters more here than the tag bookkeeping suggests: a canvas
|
|
59
|
+
// left registered is a surface the package keeps rendering into, once per
|
|
60
|
+
// picture, for a widget nobody will draw again.
|
|
61
|
+
void forgetSkiaCanvas(facebook::react::Tag tag);
|
|
62
|
+
|
|
63
|
+
} // namespace basalt
|