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,339 @@
|
|
|
1
|
+
// basalt-core — GTK4 view layer
|
|
2
|
+
//
|
|
3
|
+
// Deliberately free of React Native headers: this file only knows about
|
|
4
|
+
// absolute frames and paint properties. The mounting manager translates
|
|
5
|
+
// Fabric's ShadowViewMutation stream into calls on this API, so the widget
|
|
6
|
+
// layer can be built and exercised without the RN C++ core present.
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <gtk/gtk.h>
|
|
11
|
+
#include <pango/pango.h>
|
|
12
|
+
|
|
13
|
+
G_BEGIN_DECLS
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// RnLayout — a GtkLayoutManager that does no layout of its own.
|
|
17
|
+
//
|
|
18
|
+
// Yoga has already computed absolute frames by the time a mutation reaches us,
|
|
19
|
+
// so this places each child at the rect the shadow tree assigned it. Measuring
|
|
20
|
+
// returns zero: RN is the sole source of truth for size.
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
#define RN_TYPE_LAYOUT (rn_layout_get_type())
|
|
24
|
+
G_DECLARE_FINAL_TYPE(RnLayout, rn_layout, RN, LAYOUT, GtkLayoutManager)
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// RnView — the GTK peer of a Fabric <View>.
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
#define RN_TYPE_VIEW (rn_view_get_type())
|
|
31
|
+
G_DECLARE_FINAL_TYPE(RnView, rn_view, RN, VIEW, GtkWidget)
|
|
32
|
+
|
|
33
|
+
RnView *rn_view_new(int tag);
|
|
34
|
+
|
|
35
|
+
// As above, but with an accessible role.
|
|
36
|
+
//
|
|
37
|
+
// GTK4 has no per-instance role setter: a role is a construct-only property, or
|
|
38
|
+
// is set once per widget class. RnView is one class for every React Native
|
|
39
|
+
// view, so the role has to be chosen when the widget is made. That is possible
|
|
40
|
+
// because Fabric delivers a view's props with the Create mutation that makes
|
|
41
|
+
// it -- but it does mean accessibilityRole cannot change afterwards.
|
|
42
|
+
RnView *rn_view_new_with_role(int tag, GtkAccessibleRole role);
|
|
43
|
+
|
|
44
|
+
// Fabric tag, for debugging and hit-test attribution.
|
|
45
|
+
int rn_view_get_tag(RnView *self);
|
|
46
|
+
|
|
47
|
+
// Frame in parent coordinates, straight from LayoutMetrics::frame.
|
|
48
|
+
void rn_view_set_frame(RnView *self, float x, float y, float width, float height);
|
|
49
|
+
void rn_view_get_frame(RnView *self, graphene_rect_t *out);
|
|
50
|
+
|
|
51
|
+
// BaseViewProps::backgroundColor. Passing has_color = FALSE paints nothing.
|
|
52
|
+
void rn_view_set_background_color(RnView *self, gboolean has_color, const GdkRGBA *color);
|
|
53
|
+
|
|
54
|
+
// BaseViewProps::opacity.
|
|
55
|
+
void rn_view_set_opacity(RnView *self, double opacity);
|
|
56
|
+
|
|
57
|
+
// Corner radii, in the order top-left, top-right, bottom-right, bottom-left.
|
|
58
|
+
// Each is a width/height pair, because React Native's radii are elliptical.
|
|
59
|
+
// Pass NULL for square corners.
|
|
60
|
+
void rn_view_set_border_radii(RnView *self, const graphene_size_t radii[4]);
|
|
61
|
+
|
|
62
|
+
// Border widths and colours, in the order top, right, bottom, left -- which is
|
|
63
|
+
// the order GTK's border node wants and the order CSS names them in.
|
|
64
|
+
void rn_view_set_borders(RnView *self, const float widths[4], const GdkRGBA colors[4]);
|
|
65
|
+
|
|
66
|
+
// BaseViewProps::transform, already resolved by React Native.
|
|
67
|
+
//
|
|
68
|
+
// Applied in the layout manager rather than at paint time, so that GTK's own
|
|
69
|
+
// hit testing follows it: a transformed view is picked where it appears, not
|
|
70
|
+
// where its frame says it is. Anchored on the view's centre, which is what
|
|
71
|
+
// every other React Native platform does and what transformOrigin is measured
|
|
72
|
+
// against. Pass NULL for identity.
|
|
73
|
+
void rn_view_set_transform(RnView *self, const graphene_matrix_t *matrix);
|
|
74
|
+
|
|
75
|
+
// `backfaceVisibility: 'hidden'`. A view whose transform has turned it away
|
|
76
|
+
// from the viewer is not drawn, and nor are its children -- which is what a
|
|
77
|
+
// card's back should do, and what takes it out of hit testing too, since
|
|
78
|
+
// `gtk_widget_pick` skips a widget that is not visible.
|
|
79
|
+
//
|
|
80
|
+
// Whether it has turned away is `basalt::facesAway`; see core/Backface.h for
|
|
81
|
+
// why the rule is shared rather than left to each toolkit.
|
|
82
|
+
void rn_view_set_hides_back_face(RnView *self, gboolean hides);
|
|
83
|
+
|
|
84
|
+
// `display: 'none'`. Separate from the back face above because the two are
|
|
85
|
+
// independent reasons to hide the same widget, and Fabric applies them through
|
|
86
|
+
// different calls -- props, then layout metrics.
|
|
87
|
+
void rn_view_set_hidden(RnView *self, gboolean hidden);
|
|
88
|
+
|
|
89
|
+
// BaseViewProps::zIndex. GTK paints in child order, so this reorders painting
|
|
90
|
+
// without touching the child list that mutations index into.
|
|
91
|
+
void rn_view_set_z_index(RnView *self, int z_index);
|
|
92
|
+
|
|
93
|
+
// `pointerEvents`, which decides what a press can land on rather than what is
|
|
94
|
+
// drawn. CSS's four values, and React Native's.
|
|
95
|
+
//
|
|
96
|
+
// GTK expresses exactly one of them. `none` is `can-target`, which makes
|
|
97
|
+
// `gtk_widget_pick` skip the widget and everything inside it, so a press
|
|
98
|
+
// reaches whatever is behind -- which is precisely the semantics. The other two
|
|
99
|
+
// have no equivalent, so they are stored here and resolved by the hit test;
|
|
100
|
+
// see GtkTouchDispatcher.cpp.
|
|
101
|
+
typedef enum {
|
|
102
|
+
RN_POINTER_EVENTS_AUTO,
|
|
103
|
+
RN_POINTER_EVENTS_NONE,
|
|
104
|
+
RN_POINTER_EVENTS_BOX_NONE,
|
|
105
|
+
RN_POINTER_EVENTS_BOX_ONLY,
|
|
106
|
+
} RnPointerEvents;
|
|
107
|
+
|
|
108
|
+
void rn_view_set_pointer_events(RnView *self, RnPointerEvents mode);
|
|
109
|
+
RnPointerEvents rn_view_get_pointer_events(RnView *self);
|
|
110
|
+
|
|
111
|
+
// Whether this view takes keyboard focus, and therefore whether Tab stops on
|
|
112
|
+
// it.
|
|
113
|
+
//
|
|
114
|
+
// React Native has a `focusable` prop and it does not reach this platform:
|
|
115
|
+
// ReactCommon parses it only into Android's and tvOS's HostPlatformViewProps,
|
|
116
|
+
// and the C++ host's is a bare alias of BaseViewProps. What does reach here is
|
|
117
|
+
// `accessible`, which is what <Pressable> sets on everything it renders and
|
|
118
|
+
// what an app sets on anything else it means as a control -- so that is the
|
|
119
|
+
// signal, and it is also the one both desktops use for their own focus rings.
|
|
120
|
+
// See GtkFocus.h.
|
|
121
|
+
//
|
|
122
|
+
// GTK owns the chain: a focusable widget joins the window's focus order, so Tab
|
|
123
|
+
// and Shift+Tab work without this project deciding what "next" means.
|
|
124
|
+
void rn_view_set_focusable(RnView *self, gboolean focusable);
|
|
125
|
+
gboolean rn_view_get_focusable(RnView *self);
|
|
126
|
+
|
|
127
|
+
// The text of a <Paragraph>, already laid out.
|
|
128
|
+
//
|
|
129
|
+
// A Paragraph is a View that also paints text, so it gets no separate widget
|
|
130
|
+
// type: same box model, same frame, same children. The mounting manager builds
|
|
131
|
+
// the layout from the shadow view's AttributedString -- Pango is part of the
|
|
132
|
+
// GTK stack, so taking a PangoLayout here keeps this file free of React Native
|
|
133
|
+
// types the way the rest of it is.
|
|
134
|
+
//
|
|
135
|
+
// Takes its own reference. Pass NULL to clear. `color` is the colour to paint
|
|
136
|
+
// glyphs that carry no foreground attribute of their own.
|
|
137
|
+
void rn_view_set_text_layout(RnView *self, PangoLayout *layout, const GdkRGBA *color);
|
|
138
|
+
|
|
139
|
+
// How an image fills its frame. Mirrors React Native's ImageResizeMode, minus
|
|
140
|
+
// Repeat, which needs a repeating pattern node rather than one texture draw.
|
|
141
|
+
typedef enum {
|
|
142
|
+
RN_IMAGE_FIT_COVER,
|
|
143
|
+
RN_IMAGE_FIT_CONTAIN,
|
|
144
|
+
RN_IMAGE_FIT_STRETCH,
|
|
145
|
+
RN_IMAGE_FIT_CENTER,
|
|
146
|
+
// Tiled from the top left at the image's own size, which is what CSS
|
|
147
|
+
// `repeat` and React Native's `resizeMode: 'repeat'` mean. Every toolkit
|
|
148
|
+
// here has a primitive for it; centring, which is what this used to fall
|
|
149
|
+
// back to, is a different picture rather than a rougher one.
|
|
150
|
+
RN_IMAGE_FIT_REPEAT,
|
|
151
|
+
} RnImageFit;
|
|
152
|
+
|
|
153
|
+
// The decoded pixels of an <Image>. Takes its own reference; pass NULL to clear.
|
|
154
|
+
//
|
|
155
|
+
// Like the text layout above, this is a GTK type rather than a React Native
|
|
156
|
+
// one, so the widget layer stays free of RN headers. GtkImageLoader produces
|
|
157
|
+
// the texture and GtkMountingManager chooses the fit.
|
|
158
|
+
void rn_view_set_texture(RnView *self, GdkTexture *texture, RnImageFit fit);
|
|
159
|
+
|
|
160
|
+
// `tintColor`: recolours the image, keeping its alpha. An icon drawn as a
|
|
161
|
+
// silhouette is the usual reason -- one asset, any colour.
|
|
162
|
+
//
|
|
163
|
+
// Separate from the texture because it arrives from the props and the texture
|
|
164
|
+
// arrives from a loader callback, and either can land first.
|
|
165
|
+
void rn_view_set_image_tint(RnView *self, gboolean has_tint, const GdkRGBA *tint);
|
|
166
|
+
|
|
167
|
+
// Called on the GTK main thread when this widget's own allocation changes.
|
|
168
|
+
//
|
|
169
|
+
// The host attaches one to a surface root to drive
|
|
170
|
+
// ReactHost::setSurfaceConstraints. GTK4 removed GtkWidget::size-allocate, and
|
|
171
|
+
// a layout manager's allocate is the supported replacement: it is the one
|
|
172
|
+
// place a widget is told the size it actually got.
|
|
173
|
+
typedef void (*RnViewResizeFunc)(RnView *self, int width, int height, gpointer user_data);
|
|
174
|
+
void rn_view_set_resize_callback(RnView *self, RnViewResizeFunc callback, gpointer user_data);
|
|
175
|
+
|
|
176
|
+
// Clip children to this view's bounds.
|
|
177
|
+
//
|
|
178
|
+
// Off by default, because React Native's default is overflow: visible. A
|
|
179
|
+
// <ScrollView> needs it, and so does any view with overflow: 'hidden'.
|
|
180
|
+
void rn_view_set_clips_children(RnView *self, gboolean clips);
|
|
181
|
+
|
|
182
|
+
// Shift children by a scroll offset, in points.
|
|
183
|
+
//
|
|
184
|
+
// Applied in the layout manager rather than by moving frames, so the frames
|
|
185
|
+
// Fabric assigned stay untouched and GTK's own hit testing follows the shift
|
|
186
|
+
// for free: a child allocated at its scrolled position is picked there.
|
|
187
|
+
void rn_view_set_scroll_offset(RnView *self, double offset_x, double offset_y);
|
|
188
|
+
|
|
189
|
+
// The overlay scrollbars this view draws over its own content. Computed by the
|
|
190
|
+
// scroll manager from core/ScrollIndicator.h, because the geometry is the same
|
|
191
|
+
// on all three desktops and the drawing is not.
|
|
192
|
+
//
|
|
193
|
+
// Lengths of zero mean "no indicator on that axis", which is what content that
|
|
194
|
+
// fits produces.
|
|
195
|
+
void rn_view_set_scroll_indicators(RnView *self,
|
|
196
|
+
double vertical_offset,
|
|
197
|
+
double vertical_length,
|
|
198
|
+
double horizontal_offset,
|
|
199
|
+
double horizontal_length);
|
|
200
|
+
void rn_view_get_scroll_offset(RnView *self, double *offset_x, double *offset_y);
|
|
201
|
+
|
|
202
|
+
// A textual description of the widget tree rooted here, one indented line per
|
|
203
|
+
// view.
|
|
204
|
+
//
|
|
205
|
+
// This is what makes the full stack testable rather than merely watchable.
|
|
206
|
+
// Everything below GDK has unit tests, but the path from JavaScript through
|
|
207
|
+
// React, Fabric and the mounting manager can only be exercised by running the
|
|
208
|
+
// real host -- and until now the only way to check the result was to look at a
|
|
209
|
+
// screenshot. A dump can be asserted on.
|
|
210
|
+
//
|
|
211
|
+
// Returns a newly allocated string; free with g_free.
|
|
212
|
+
char *rn_view_describe_tree(RnView *self);
|
|
213
|
+
|
|
214
|
+
// Turns this view into a text field, or back.
|
|
215
|
+
//
|
|
216
|
+
// The editable is a real GtkText -- the widget behind GtkEntry -- parented
|
|
217
|
+
// inside this one and sized to its whole frame. Using GTK's own editable rather
|
|
218
|
+
// than drawing a cursor on a PangoLayout is what brings input methods,
|
|
219
|
+
// selection, the clipboard and every keybinding a Linux user expects, none of
|
|
220
|
+
// which is worth reimplementing.
|
|
221
|
+
//
|
|
222
|
+
// Returns the editable, or NULL after clearing.
|
|
223
|
+
GtkWidget *rn_view_set_editable(RnView *self, gboolean editable, gboolean multiline);
|
|
224
|
+
|
|
225
|
+
// The border and padding to hold the native peer inside. Yoga has already
|
|
226
|
+
// resolved these into React Native's content inset; without them a <TextInput>
|
|
227
|
+
// renders its text flush against its own border, ignoring paddingHorizontal.
|
|
228
|
+
void rn_view_set_peer_insets(RnView *self, const GtkBorder *insets);
|
|
229
|
+
void rn_view_get_peer_insets(RnView *self, GtkBorder *out);
|
|
230
|
+
GtkWidget *rn_view_get_editable(RnView *self);
|
|
231
|
+
|
|
232
|
+
// --- Controls ----------------------------------------------------------------
|
|
233
|
+
//
|
|
234
|
+
// The three components that are a toolkit control rather than a box:
|
|
235
|
+
// <ActivityIndicator> and <RefreshControl> are a GtkSpinner, <Switch> is a
|
|
236
|
+
// GtkSwitch. Parented and sized exactly the way the <TextInput> peer above is
|
|
237
|
+
// -- a non-RnView child fills the view's inner rect -- because it is the same
|
|
238
|
+
// arrangement for the same reason: GTK's own widget brings the theme, the
|
|
239
|
+
// animation and the accessibility with it, and none of that is worth drawing
|
|
240
|
+
// by hand.
|
|
241
|
+
typedef enum {
|
|
242
|
+
RN_CONTROL_NONE,
|
|
243
|
+
RN_CONTROL_SPINNER,
|
|
244
|
+
RN_CONTROL_SWITCH,
|
|
245
|
+
} RnControlKind;
|
|
246
|
+
|
|
247
|
+
// Installs the control this view stands for, replacing any other kind, or
|
|
248
|
+
// removes it for RN_CONTROL_NONE. Returns the control widget, or NULL.
|
|
249
|
+
GtkWidget *rn_view_set_control(RnView *self, RnControlKind kind);
|
|
250
|
+
GtkWidget *rn_view_get_control(RnView *self);
|
|
251
|
+
RnControlKind rn_view_get_control_kind(RnView *self);
|
|
252
|
+
|
|
253
|
+
// What `describe_tree` prints for this control, which core/DesktopControls.h
|
|
254
|
+
// writes so that three hosts cannot describe the same switch differently. NULL
|
|
255
|
+
// or empty prints nothing.
|
|
256
|
+
void rn_view_set_control_description(RnView *self, const char *description);
|
|
257
|
+
|
|
258
|
+
// Whether this control is disabled. Kept on the view rather than read back off
|
|
259
|
+
// the widget because `sensitive` is GTK's word for two different things, and
|
|
260
|
+
// only React Native's `disabled` should stop a press.
|
|
261
|
+
void rn_view_set_control_disabled(RnView *self, gboolean disabled);
|
|
262
|
+
gboolean rn_view_get_control_disabled(RnView *self);
|
|
263
|
+
|
|
264
|
+
// --- React DevTools' overlay --------------------------------------------------
|
|
265
|
+
//
|
|
266
|
+
// The rectangles a `DebuggingOverlay` draws: an inspected element's blue box,
|
|
267
|
+
// or an outline around everything that just re-rendered. Set from
|
|
268
|
+
// GtkMountingManager, which parses them; see core/DebuggingOverlay.h.
|
|
269
|
+
//
|
|
270
|
+
// Eight floats per rectangle -- x, y, width, height, then r, g, b, a -- and a
|
|
271
|
+
// flag for whether to fill. A plain array rather than the core struct because
|
|
272
|
+
// this file has no React Native in it and is not about to start.
|
|
273
|
+
void rn_view_set_highlights(RnView *self,
|
|
274
|
+
const float *rectangles,
|
|
275
|
+
const gboolean *filled,
|
|
276
|
+
int count);
|
|
277
|
+
|
|
278
|
+
// Accessibility, as a screen reader sees it.
|
|
279
|
+
//
|
|
280
|
+
// `label` is the accessible name and `description` the hint; either may be NULL
|
|
281
|
+
// or empty to leave it unset. GTK maps these onto AT-SPI, which is what Orca
|
|
282
|
+
// reads.
|
|
283
|
+
void rn_view_set_accessible_text(RnView *self, const char *label, const char *description);
|
|
284
|
+
|
|
285
|
+
// React Native's own name for the role -- "button", "image", "text" -- kept
|
|
286
|
+
// alongside the GtkAccessibleRole the widget was constructed with.
|
|
287
|
+
//
|
|
288
|
+
// Two vocabularies for one fact, and both are needed. GTK's is what a screen
|
|
289
|
+
// reader reads; React Native's is what `rn_view_describe_tree` reports, so that
|
|
290
|
+
// dump can be compared line by line with the AppKit one without either platform
|
|
291
|
+
// speaking the other's language. That the GTK role was really applied is
|
|
292
|
+
// asserted in tests/test_accessibility.cpp instead.
|
|
293
|
+
//
|
|
294
|
+
// Set from the same computation that picks the GtkAccessibleRole, so the two
|
|
295
|
+
// cannot disagree. Pass NULL or "" for no role.
|
|
296
|
+
void rn_view_set_role_name(RnView *self, const char *name);
|
|
297
|
+
|
|
298
|
+
// The view's `nativeID`, verbatim.
|
|
299
|
+
//
|
|
300
|
+
// Only the hidden title bar reads it, to find the regions an app marked with
|
|
301
|
+
// <TitleBar.DragRegion> and <TitleBar.NoDragRegion>; see
|
|
302
|
+
// core/TitleBarRegions.h for the two names and the rule. Nothing about layout,
|
|
303
|
+
// painting or accessibility looks at it.
|
|
304
|
+
//
|
|
305
|
+
// Kept as the app set it rather than parsed into a flag here, because a view
|
|
306
|
+
// can carry a nativeID for reasons that have nothing to do with the title bar
|
|
307
|
+
// -- an end-to-end test looking a view up by name, most of them -- and this
|
|
308
|
+
// layer has no business deciding which of those meanings was intended.
|
|
309
|
+
//
|
|
310
|
+
// Pass NULL or "" for none.
|
|
311
|
+
void rn_view_set_native_id(RnView *self, const char *native_id);
|
|
312
|
+
// NULL when unset, never the empty string.
|
|
313
|
+
const char *rn_view_get_native_id(RnView *self);
|
|
314
|
+
|
|
315
|
+
// Accessible states. Each is a tri-state: unset leaves GTK's default alone,
|
|
316
|
+
// which is not the same as setting it false.
|
|
317
|
+
typedef enum {
|
|
318
|
+
RN_A11Y_UNSET,
|
|
319
|
+
RN_A11Y_FALSE,
|
|
320
|
+
RN_A11Y_TRUE,
|
|
321
|
+
} RnAccessibleFlag;
|
|
322
|
+
|
|
323
|
+
void rn_view_set_accessible_state(RnView *self,
|
|
324
|
+
RnAccessibleFlag disabled,
|
|
325
|
+
RnAccessibleFlag checked,
|
|
326
|
+
RnAccessibleFlag selected,
|
|
327
|
+
RnAccessibleFlag expanded,
|
|
328
|
+
RnAccessibleFlag busy);
|
|
329
|
+
|
|
330
|
+
// Hidden from assistive technology, for accessible={false} and
|
|
331
|
+
// accessibilityElementsHidden.
|
|
332
|
+
void rn_view_set_accessible_hidden(RnView *self, gboolean hidden);
|
|
333
|
+
|
|
334
|
+
// Child management. Mirrors Insert/Remove mutations; index is the position
|
|
335
|
+
// within the parent's child list, as Fabric numbers it.
|
|
336
|
+
void rn_view_insert_child(RnView *self, RnView *child, int index);
|
|
337
|
+
void rn_view_remove_child(RnView *self, RnView *child);
|
|
338
|
+
|
|
339
|
+
G_END_DECLS
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Exercises the GTK view layer with hand-written frames, standing in for what
|
|
2
|
+
// Fabric would emit. Builds and runs without the React Native C++ core, so the
|
|
3
|
+
// paint and layout path can be verified on its own.
|
|
4
|
+
|
|
5
|
+
#include "RnView.h"
|
|
6
|
+
|
|
7
|
+
static GdkRGBA rgba(float r, float g, float b, float a) {
|
|
8
|
+
GdkRGBA c;
|
|
9
|
+
c.red = r; c.green = g; c.blue = b; c.alpha = a;
|
|
10
|
+
return c;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static RnView *make_box(int tag, float x, float y, float w, float h, GdkRGBA color) {
|
|
14
|
+
RnView *view = rn_view_new(tag);
|
|
15
|
+
rn_view_set_frame(view, x, y, w, h);
|
|
16
|
+
rn_view_set_background_color(view, TRUE, &color);
|
|
17
|
+
return view;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static void on_activate(GtkApplication *app, gpointer /*user_data*/) {
|
|
21
|
+
GtkWidget *window = gtk_application_window_new(app);
|
|
22
|
+
gtk_window_set_title(GTK_WINDOW(window), "basalt-core — mounting skeleton");
|
|
23
|
+
gtk_window_set_default_size(GTK_WINDOW(window), 640, 420);
|
|
24
|
+
|
|
25
|
+
// Root surface.
|
|
26
|
+
RnView *root = make_box(1, 0, 0, 640, 420, rgba(0.12f, 0.13f, 0.16f, 1.0f));
|
|
27
|
+
|
|
28
|
+
// A row of children, absolutely placed the way Yoga would have resolved them.
|
|
29
|
+
RnView *a = make_box(2, 32, 32, 240, 160, rgba(0.30f, 0.55f, 0.95f, 1.0f));
|
|
30
|
+
RnView *b = make_box(3, 296, 32, 240, 160, rgba(0.95f, 0.45f, 0.35f, 1.0f));
|
|
31
|
+
RnView *c = make_box(4, 32, 224, 504, 140, rgba(0.35f, 0.80f, 0.55f, 1.0f));
|
|
32
|
+
|
|
33
|
+
rn_view_insert_child(root, a, 0);
|
|
34
|
+
rn_view_insert_child(root, b, 1);
|
|
35
|
+
rn_view_insert_child(root, c, 2);
|
|
36
|
+
|
|
37
|
+
// Nested child, to prove coordinates are parent-relative.
|
|
38
|
+
RnView *nested = make_box(5, 24, 24, 120, 90, rgba(1.0f, 1.0f, 1.0f, 0.85f));
|
|
39
|
+
rn_view_insert_child(a, nested, 0);
|
|
40
|
+
|
|
41
|
+
// Half-opacity child, to prove the opacity layer.
|
|
42
|
+
RnView *faded = make_box(6, 24, 24, 160, 90, rgba(0.1f, 0.1f, 0.1f, 1.0f));
|
|
43
|
+
rn_view_set_opacity(faded, 0.4);
|
|
44
|
+
rn_view_insert_child(c, faded, 0);
|
|
45
|
+
|
|
46
|
+
gtk_window_set_child(GTK_WINDOW(window), GTK_WIDGET(root));
|
|
47
|
+
gtk_window_present(GTK_WINDOW(window));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
int main(int argc, char **argv) {
|
|
51
|
+
GtkApplication *app =
|
|
52
|
+
gtk_application_new("dev.basalt.skeleton", G_APPLICATION_DEFAULT_FLAGS);
|
|
53
|
+
g_signal_connect(app, "activate", G_CALLBACK(on_activate), nullptr);
|
|
54
|
+
const int status = g_application_run(G_APPLICATION(app), argc, argv);
|
|
55
|
+
g_object_unref(app);
|
|
56
|
+
return status;
|
|
57
|
+
}
|