react-x11 2.52.0 → 2.54.0
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/README.md +10 -10
- package/docs/README.md +160 -314
- package/docs/accessibility.md +176 -229
- package/docs/appearance.md +77 -176
- package/docs/click-to-component.md +18 -51
- package/docs/clipboard.md +40 -59
- package/docs/components.md +518 -1036
- package/docs/dbus.md +61 -133
- package/docs/debugging.md +152 -245
- package/docs/desktop-calendar.md +51 -88
- package/docs/desktop.md +222 -347
- package/docs/devtools.md +50 -167
- package/docs/drag-and-drop.md +126 -204
- package/docs/ecosystem/animation.md +91 -125
- package/docs/ecosystem/data-fetching.md +38 -53
- package/docs/ecosystem/dev-tooling.md +159 -202
- package/docs/ecosystem/forms.md +61 -97
- package/docs/ecosystem/headless.md +64 -89
- package/docs/ecosystem/i18n.md +18 -21
- package/docs/ecosystem/icons.md +93 -126
- package/docs/ecosystem/layout.md +42 -52
- package/docs/ecosystem/routing.md +18 -29
- package/docs/ecosystem/state.md +71 -88
- package/docs/ecosystem/testing.md +131 -157
- package/docs/ecosystem/theming.md +119 -165
- package/docs/ecosystem.md +145 -179
- package/docs/elements.md +1096 -1774
- package/docs/embedding.md +83 -132
- package/docs/events.md +412 -695
- package/docs/extending.md +784 -1326
- package/docs/eyedropper.md +63 -122
- package/docs/filedialog.md +71 -107
- package/docs/frame.md +195 -339
- package/docs/gl.md +65 -62
- package/docs/globalmenu.md +63 -146
- package/docs/macos.md +531 -3234
- package/docs/notifications.md +33 -47
- package/docs/packaging.md +166 -309
- package/docs/permissions.md +9 -14
- package/docs/react-features.md +81 -106
- package/docs/remote.md +32 -76
- package/docs/scale.md +72 -186
- package/docs/styling.md +329 -547
- package/docs/system.md +200 -280
- package/docs/testing.md +63 -83
- package/docs/typescript.md +6 -48
- package/docs/uri-schemes.md +67 -107
- package/docs/wayland-backend.md +200 -459
- package/docs/windows-integrations.md +75 -131
- package/docs/windows.md +343 -1367
- package/package.json +3 -2
- package/src/Reconciler.js +2 -2
- package/src/a11y.js +1 -1
- package/src/backend/context2d.js +3 -3
- package/src/bootstrap.js +1 -1
- package/src/cocoa/app.js +6 -6
- package/src/cocoa/bezels.js +1 -1
- package/src/cocoa/fonts.js +1 -1
- package/src/cocoa/globalmenu.js +1 -1
- package/src/cocoa/keymap.js +1 -1
- package/src/cocoa/panewindow.js +1 -1
- package/src/cocoa/player.js +1 -1
- package/src/cocoa/presenter.js +2 -2
- package/src/cocoa/promotion.js +1 -1
- package/src/cocoa/relaunch.js +1 -1
- package/src/cocoa/threaded.js +1 -1
- package/src/cocoa/video.js +1 -1
- package/src/cocoa/window.js +4 -4
- package/src/components/Menu.js +7 -2
- package/src/components/Switch.js +1 -1
- package/src/components/native.js +1 -1
- package/src/dnd.js +2 -2
- package/src/glnodes.js +1 -1
- package/src/grid.js +1 -1
- package/src/imagedecode-worker.js +32 -0
- package/src/imagedecode.js +140 -2
- package/src/layouts.js +1 -1
- package/src/nodes/animation.js +1 -1
- package/src/nodes/invalidate.js +1 -1
- package/src/nodes/layouthost.js +1 -1
- package/src/nodes/video.js +19 -8
- package/src/nodes/window/droptarget.js +1 -1
- package/src/ntk.d.ts +12 -0
- package/src/pacing.js +1 -1
- package/src/refresh/index.js +2 -1
- package/src/types/video.d.ts +5 -2
- package/src/videobackend.js +28 -0
- package/src/videoframes.js +29 -16
- package/src/wayland/app.js +27 -0
- package/src/wayland/video.js +376 -0
- package/src/win32/a11y.js +1 -1
- package/src/win32/app.js +2 -2
- package/src/win32/fonts.js +1 -1
- package/src/win32/glarea.js +4 -4
- package/src/win32/overlay.js +1 -1
- package/src/win32/panewindow.js +3 -3
- package/src/win32/shell.js +1 -1
- package/src/win32/window.js +2 -2
- package/src/windowid.js +1 -1
- package/src/xvideo.js +189 -0
- package/docs/architecture/accessibility.md +0 -470
- package/docs/architecture/animation.md +0 -707
- package/docs/architecture/container-queries.md +0 -525
- package/docs/architecture/custom-layout.md +0 -334
- package/docs/architecture/drag-and-drop.md +0 -941
- package/docs/architecture/element-layer-contents.md +0 -622
- package/docs/architecture/frame-pacing.md +0 -255
- package/docs/architecture/grid-layout.md +0 -358
- package/docs/architecture/protocol-efficiency.md +0 -357
- package/docs/architecture/video.md +0 -1149
- package/docs/architecture/windowed-regions.md +0 -854
- package/docs/glx.md +0 -137
- package/docs/wayland.md +0 -545
- package/docs/windows-embedding.md +0 -271
- package/docs/windows-gl.md +0 -221
package/docs/dbus.md
CHANGED
|
@@ -18,19 +18,14 @@ function ColourScheme() {
|
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
There is **nothing to wrap**. No provider, no prop drilling, no setup step
|
|
21
|
-
for the app author — a component library can call this
|
|
22
|
-
reason it is shaped this way.
|
|
21
|
+
for the app author — a component library can call this.
|
|
23
22
|
|
|
24
23
|
## The rule everything else is subordinate to
|
|
25
24
|
|
|
26
25
|
**Nothing throws at import time, and nothing crashes an app running where
|
|
27
|
-
there is no session bus
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
ssh session on a headless server, in a container, and on Node 20 where the
|
|
31
|
-
transport is not installed at all. The ssh case is not an edge case — it is
|
|
32
|
-
react-x11's flagship persona. **"No bus" is a first-class configuration, not
|
|
33
|
-
a degraded one.**
|
|
26
|
+
there is no session bus** — XQuartz, a bare `startx`, CI, an ssh session on a
|
|
27
|
+
headless server, a container, Node 20 where the transport is not installed.
|
|
28
|
+
**"No bus" is a first-class configuration, not a degraded one.**
|
|
34
29
|
|
|
35
30
|
So `sessionBus()` answers `null` rather than rejecting, and `useSessionBus()`
|
|
36
31
|
reports `'unavailable'` rather than throwing, when:
|
|
@@ -63,27 +58,16 @@ interface BusHandle {
|
|
|
63
58
|
|
|
64
59
|
**The terse path is correct on its own.** `const { bus } = useSessionBus()`
|
|
65
60
|
followed by `if (!bus) return fallback` is right, with no reference to
|
|
66
|
-
`status
|
|
67
|
-
|
|
68
|
-
render identically anyway. The states earn their keep in diagnostics ("why is
|
|
69
|
-
my tray icon missing") and for an app that is itself a service.
|
|
70
|
-
|
|
71
|
-
**"Idle" is not a fourth state.** The first render happens before the effect
|
|
72
|
-
runs, so nothing has been attempted yet — calling that `'connecting'` is a
|
|
73
|
-
small inaccuracy that becomes true within a tick, and an honest fourth state
|
|
74
|
-
would give every consumer a branch that never needs different handling.
|
|
61
|
+
`status`. The states are for diagnostics ("why is my tray icon missing") and
|
|
62
|
+
for an app that is itself a service.
|
|
75
63
|
|
|
76
64
|
**`'unavailable'` is a snapshot, not a verdict.** Failure is not cached: a
|
|
77
|
-
session bus can appear later
|
|
78
|
-
|
|
79
|
-
disable a feature on seeing it. The name invites the opposite reading, which
|
|
80
|
-
is why this paragraph exists.
|
|
65
|
+
session bus can appear later, and the next acquisition retries. Do not
|
|
66
|
+
permanently disable a feature on seeing it.
|
|
81
67
|
|
|
82
|
-
**`'closed'` does not auto-retry
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
knows how to rebuild its bus-side state can call `retry()`; a generic one
|
|
86
|
-
cannot, so the decision is yours.
|
|
68
|
+
**`'closed'` does not auto-retry.** A new connection is a new unique name (see
|
|
69
|
+
[the sharing contract](#the-sharing-contract)), so a hook that knows how to
|
|
70
|
+
rebuild its bus-side state calls `retry()` itself.
|
|
87
71
|
|
|
88
72
|
## The imperative pair
|
|
89
73
|
|
|
@@ -100,58 +84,34 @@ interface BusRef {
|
|
|
100
84
|
}
|
|
101
85
|
```
|
|
102
86
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
- **Host-side code has no component to hang off.** The plumbing that later
|
|
107
|
-
features add — a settings subscriber, a notification sender — is module code
|
|
108
|
-
and event-loop glue, some of which must run with no root mounted at all.
|
|
109
|
-
- **A click handler wants to resolve at click time**, not at render time:
|
|
110
|
-
|
|
111
|
-
```jsx
|
|
112
|
-
<Button
|
|
113
|
-
onClick={async () => {
|
|
114
|
-
await using ref = await sessionBus({ required: true });
|
|
115
|
-
await ref.bus.proxy(/* … */);
|
|
116
|
-
}}
|
|
117
|
-
/>
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
`required: true` is the service-author escape hatch. `null` is right for
|
|
121
|
-
feature-probing plumbing and hides _why_ from an app whose purpose is the bus,
|
|
122
|
-
so `required` converts unavailability into a rejection carrying the cause. The
|
|
123
|
-
default stays never-rejecting; the hooks use `required` internally purely to
|
|
124
|
-
obtain the reason for `cause`.
|
|
125
|
-
|
|
126
|
-
There is **no `busAddress` parameter**, deliberately: a per-call address is
|
|
127
|
-
incoherent under sharing — two callers, two addresses, one socket, which
|
|
128
|
-
would win? The address seam is D-Bus's own, `$DBUS_SESSION_BUS_ADDRESS`, plus
|
|
129
|
-
an `$XDG_RUNTIME_DIR/bus` fallback until
|
|
130
|
-
[dbus-native#389](https://github.com/sidorares/dbus-native/pull/389) lands.
|
|
131
|
-
|
|
132
|
-
On **macOS** there is a third source and it is not a variable: D-Bus
|
|
133
|
-
advertises the socket through launchd, and finding it means running
|
|
134
|
-
`launchctl getenv`. That lookup is asynchronous and happens once per process,
|
|
135
|
-
which is the whole of
|
|
136
|
-
[#417](https://github.com/sidorares/react-x11/issues/417) — `dbus-native`
|
|
137
|
-
would otherwise do it from a synchronous constructor with `spawnSync`, and
|
|
138
|
-
120–150 ms of blocked event loop in front of the first frame is not a price
|
|
139
|
-
for finding out whether there is a bus. See
|
|
140
|
-
[desktop.md](desktop.md#not-blocking-the-first-frame-on-the-bus).
|
|
87
|
+
For host-side code with no component to hang off, and for a click handler that
|
|
88
|
+
wants to resolve at click time rather than render time:
|
|
141
89
|
|
|
142
|
-
|
|
90
|
+
```jsx
|
|
91
|
+
<Button
|
|
92
|
+
onClick={async () => {
|
|
93
|
+
await using ref = await sessionBus({ required: true });
|
|
94
|
+
await ref.bus.proxy(/* … */);
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
```
|
|
143
98
|
|
|
144
|
-
`
|
|
145
|
-
|
|
146
|
-
exported service would be three connections and three identities, and the
|
|
147
|
-
desktop would see three half-applications.
|
|
99
|
+
`required: true` converts unavailability into a rejection carrying the cause —
|
|
100
|
+
for an app whose purpose is the bus. The default never rejects.
|
|
148
101
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
on
|
|
102
|
+
There is **no `busAddress` parameter**: the connection is shared, so the
|
|
103
|
+
address comes from `$DBUS_SESSION_BUS_ADDRESS`, falling back to
|
|
104
|
+
`$XDG_RUNTIME_DIR/bus`. On **macOS** it is looked up from launchd
|
|
105
|
+
(`launchctl getenv`), asynchronously and once per process, so it does not
|
|
106
|
+
block the first frame
|
|
107
|
+
([desktop.md](desktop.md#not-blocking-the-first-frame-on-the-bus)).
|
|
108
|
+
|
|
109
|
+
## One connection, on purpose
|
|
110
|
+
|
|
111
|
+
Every consumer in the process — the global menu, a tray, your own exported
|
|
112
|
+
service — shares **one socket and one unique name**, so the desktop sees one
|
|
113
|
+
application. That is also why these hooks need no provider: two roots on two X
|
|
114
|
+
displays still share one session bus.
|
|
155
115
|
|
|
156
116
|
## Lifecycle: connect on first use, stay connected
|
|
157
117
|
|
|
@@ -162,35 +122,23 @@ The ref count drives the socket's **event-loop hold**, not its existence:
|
|
|
162
122
|
| `>0` | connected, `ref()`d | held open — someone is using the bus |
|
|
163
123
|
| `0` | connected, `unref()`d | not held; the connection stays warm and costs one idle FD |
|
|
164
124
|
|
|
165
|
-
Releasing the last ref does **not** close the connection
|
|
166
|
-
mounts
|
|
167
|
-
|
|
168
|
-
that **every reconnect is a new unique name**, with the daemon forgetting
|
|
169
|
-
match rules and well-known names along with the old connection. StrictMode's
|
|
170
|
-
double-mount becomes two counter flips rather than a full connect/disconnect
|
|
171
|
-
cycle.
|
|
125
|
+
Releasing the last ref does **not** close the connection, so a dialog that
|
|
126
|
+
mounts and unmounts (or StrictMode's double mount) does not reconnect and get
|
|
127
|
+
a new unique name each time.
|
|
172
128
|
|
|
173
129
|
`closeBus(kind)` is the way out for an app that genuinely wants the connection
|
|
174
130
|
gone. Rare, explicit, and never the automatic consequence of an unmount.
|
|
175
131
|
|
|
176
132
|
## The sharing contract
|
|
177
133
|
|
|
178
|
-
One connection with many consumers only works if the things one consumer can
|
|
179
|
-
break for another are named:
|
|
180
|
-
|
|
181
134
|
- **Never close a shared bus.** `release()` is the only lifecycle verb a ref
|
|
182
135
|
holder has. `ref.bus.close()` or `bus.connection.end()` tears the connection
|
|
183
|
-
out from under every other holder
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
- **A dead connection is not resurrected.** `dbus-native`'s reconnect stays
|
|
190
|
-
off: a new socket is a new unique name, and the daemon forgets names and
|
|
191
|
-
match rules with the old one. Refs on the dead connection fail their calls
|
|
192
|
-
with `ConnectionClosedError` and `release()` harmlessly; the next
|
|
193
|
-
`sessionBus()` dials fresh, and mounted hooks move to `'closed'`.
|
|
136
|
+
out from under every other holder.
|
|
137
|
+
- **react-x11 owns the connection's one `'error'` listener.** Do not attach
|
|
138
|
+
your own.
|
|
139
|
+
- **A dead connection is not resurrected.** Refs on it fail their calls with
|
|
140
|
+
`ConnectionClosedError` and `release()` harmlessly; the next `sessionBus()`
|
|
141
|
+
dials fresh (a new unique name), and mounted hooks move to `'closed'`.
|
|
194
142
|
- **App-global stays app-global.** Well-known names (`RequestName` has no
|
|
195
143
|
per-consumer refcount), exported object paths (re-exporting the same path
|
|
196
144
|
and interface replaces silently) and `setValueShapes()` (which flips reply
|
|
@@ -202,7 +150,7 @@ break for another are named:
|
|
|
202
150
|
|
|
203
151
|
An app that wants to _be_ on the bus gets the full `dbus-native` surface
|
|
204
152
|
through `ref.bus`, on the **same connection and unique name** as react-x11's
|
|
205
|
-
own plumbing
|
|
153
|
+
own plumbing:
|
|
206
154
|
|
|
207
155
|
```js
|
|
208
156
|
const ref = await sessionBus({ required: true });
|
|
@@ -211,16 +159,12 @@ ref.bus.exportInterface(impl, '/org/example/MyApp', description);
|
|
|
211
159
|
// hold the ref for as long as you serve: it is what keeps the process alive
|
|
212
160
|
```
|
|
213
161
|
|
|
214
|
-
|
|
215
|
-
it and nothing keeps the process running.
|
|
162
|
+
Release the ref and nothing keeps the process running.
|
|
216
163
|
|
|
217
164
|
The one service react-x11 exports for you is `org.freedesktop.Application`, so
|
|
218
165
|
that a `myapp://…` link opens the app that is already running —
|
|
219
|
-
[uri-schemes.md](uri-schemes.md). It is on this connection
|
|
220
|
-
|
|
221
|
-
different unique name than the one the global menu registers under and the one
|
|
222
|
-
portals build Request paths from, and the desktop's model of "this
|
|
223
|
-
application" would come apart.
|
|
166
|
+
[uri-schemes.md](uri-schemes.md). It is on this same connection, so the app's
|
|
167
|
+
name, its global menu and its portal requests share one identity.
|
|
224
168
|
|
|
225
169
|
## Installing, and Node 20
|
|
226
170
|
|
|
@@ -229,15 +173,12 @@ application" would come apart.
|
|
|
229
173
|
```
|
|
230
174
|
|
|
231
175
|
`dbus-native` declares `engines: ">=22.12.0"` where react-x11 declares
|
|
232
|
-
`">=20.19"`, so **npm skips it on Node 20** and the install succeeds
|
|
233
|
-
|
|
234
|
-
react-x11` still needs no toolchain.
|
|
176
|
+
`">=20.19"`, so **npm skips it on Node 20** and the install still succeeds. No
|
|
177
|
+
compiler and no install script either way.
|
|
235
178
|
|
|
236
179
|
On Node 20, `useSessionBus()` reports `'unavailable'` with a `cause` that says
|
|
237
|
-
the transport is missing
|
|
238
|
-
|
|
239
|
-
here" rather than adding a mode.** To have it on Node 20 anyway, install it
|
|
240
|
-
explicitly:
|
|
180
|
+
the transport is missing — the same path as an ssh session or a Mac without a
|
|
181
|
+
bus. To have it on Node 20 anyway, install it explicitly:
|
|
241
182
|
|
|
242
183
|
```bash
|
|
243
184
|
npm i dbus-native
|
|
@@ -251,27 +192,14 @@ directly and cast; it is the same object.
|
|
|
251
192
|
|
|
252
193
|
## Known sharp edges
|
|
253
194
|
|
|
254
|
-
- **
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
[dbus-native#393](https://github.com/sidorares/dbus-native/issues/393). Small
|
|
258
|
-
window, real bug, tracked upstream.
|
|
259
|
-
- **Identical match rules are refcounted by the daemon, not by the client** —
|
|
260
|
-
[dbus-native#394](https://github.com/sidorares/dbus-native/issues/394).
|
|
261
|
-
Dormant here, since reconnect is off; recorded so that nobody enables
|
|
262
|
-
reconnect without reading it.
|
|
195
|
+
- **A daemon that authenticates and never answers `Hello`** crashes the
|
|
196
|
+
process from inside `dbus-native`, 25 s in, where nothing can catch it. A
|
|
197
|
+
small window, tracked upstream.
|
|
263
198
|
|
|
264
199
|
## Seeing it
|
|
265
200
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
[
|
|
271
|
-
It was built on `Tree`, which now lives there too, and a browser of that shape
|
|
272
|
-
is a component rather than a demonstration of this API.
|
|
273
|
-
|
|
274
|
-
What it demonstrated of _this_ page still holds and is worth knowing: point
|
|
275
|
-
`DBUS_SESSION_BUS_ADDRESS` at nothing and a well-built consumer renders the
|
|
276
|
-
`'unavailable'` state rather than failing to start. That is the degradation
|
|
277
|
-
rule above, and it is the thing to check in your own app.
|
|
201
|
+
Point `DBUS_SESSION_BUS_ADDRESS` at nothing: a well-built consumer renders the
|
|
202
|
+
`'unavailable'` state rather than failing to start. That is the thing to check
|
|
203
|
+
in your own app.
|
|
204
|
+
|
|
205
|
+
Design notes: [design/dbus.md](../design/dbus.md).
|