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.
Files changed (115) hide show
  1. package/README.md +10 -10
  2. package/docs/README.md +160 -314
  3. package/docs/accessibility.md +176 -229
  4. package/docs/appearance.md +77 -176
  5. package/docs/click-to-component.md +18 -51
  6. package/docs/clipboard.md +40 -59
  7. package/docs/components.md +518 -1036
  8. package/docs/dbus.md +61 -133
  9. package/docs/debugging.md +152 -245
  10. package/docs/desktop-calendar.md +51 -88
  11. package/docs/desktop.md +222 -347
  12. package/docs/devtools.md +50 -167
  13. package/docs/drag-and-drop.md +126 -204
  14. package/docs/ecosystem/animation.md +91 -125
  15. package/docs/ecosystem/data-fetching.md +38 -53
  16. package/docs/ecosystem/dev-tooling.md +159 -202
  17. package/docs/ecosystem/forms.md +61 -97
  18. package/docs/ecosystem/headless.md +64 -89
  19. package/docs/ecosystem/i18n.md +18 -21
  20. package/docs/ecosystem/icons.md +93 -126
  21. package/docs/ecosystem/layout.md +42 -52
  22. package/docs/ecosystem/routing.md +18 -29
  23. package/docs/ecosystem/state.md +71 -88
  24. package/docs/ecosystem/testing.md +131 -157
  25. package/docs/ecosystem/theming.md +119 -165
  26. package/docs/ecosystem.md +145 -179
  27. package/docs/elements.md +1096 -1774
  28. package/docs/embedding.md +83 -132
  29. package/docs/events.md +412 -695
  30. package/docs/extending.md +784 -1326
  31. package/docs/eyedropper.md +63 -122
  32. package/docs/filedialog.md +71 -107
  33. package/docs/frame.md +195 -339
  34. package/docs/gl.md +65 -62
  35. package/docs/globalmenu.md +63 -146
  36. package/docs/macos.md +531 -3234
  37. package/docs/notifications.md +33 -47
  38. package/docs/packaging.md +166 -309
  39. package/docs/permissions.md +9 -14
  40. package/docs/react-features.md +81 -106
  41. package/docs/remote.md +32 -76
  42. package/docs/scale.md +72 -186
  43. package/docs/styling.md +329 -547
  44. package/docs/system.md +200 -280
  45. package/docs/testing.md +63 -83
  46. package/docs/typescript.md +6 -48
  47. package/docs/uri-schemes.md +67 -107
  48. package/docs/wayland-backend.md +200 -459
  49. package/docs/windows-integrations.md +75 -131
  50. package/docs/windows.md +343 -1367
  51. package/package.json +3 -2
  52. package/src/Reconciler.js +2 -2
  53. package/src/a11y.js +1 -1
  54. package/src/backend/context2d.js +3 -3
  55. package/src/bootstrap.js +1 -1
  56. package/src/cocoa/app.js +6 -6
  57. package/src/cocoa/bezels.js +1 -1
  58. package/src/cocoa/fonts.js +1 -1
  59. package/src/cocoa/globalmenu.js +1 -1
  60. package/src/cocoa/keymap.js +1 -1
  61. package/src/cocoa/panewindow.js +1 -1
  62. package/src/cocoa/player.js +1 -1
  63. package/src/cocoa/presenter.js +2 -2
  64. package/src/cocoa/promotion.js +1 -1
  65. package/src/cocoa/relaunch.js +1 -1
  66. package/src/cocoa/threaded.js +1 -1
  67. package/src/cocoa/video.js +1 -1
  68. package/src/cocoa/window.js +4 -4
  69. package/src/components/Menu.js +7 -2
  70. package/src/components/Switch.js +1 -1
  71. package/src/components/native.js +1 -1
  72. package/src/dnd.js +2 -2
  73. package/src/glnodes.js +1 -1
  74. package/src/grid.js +1 -1
  75. package/src/imagedecode-worker.js +32 -0
  76. package/src/imagedecode.js +140 -2
  77. package/src/layouts.js +1 -1
  78. package/src/nodes/animation.js +1 -1
  79. package/src/nodes/invalidate.js +1 -1
  80. package/src/nodes/layouthost.js +1 -1
  81. package/src/nodes/video.js +19 -8
  82. package/src/nodes/window/droptarget.js +1 -1
  83. package/src/ntk.d.ts +12 -0
  84. package/src/pacing.js +1 -1
  85. package/src/refresh/index.js +2 -1
  86. package/src/types/video.d.ts +5 -2
  87. package/src/videobackend.js +28 -0
  88. package/src/videoframes.js +29 -16
  89. package/src/wayland/app.js +27 -0
  90. package/src/wayland/video.js +376 -0
  91. package/src/win32/a11y.js +1 -1
  92. package/src/win32/app.js +2 -2
  93. package/src/win32/fonts.js +1 -1
  94. package/src/win32/glarea.js +4 -4
  95. package/src/win32/overlay.js +1 -1
  96. package/src/win32/panewindow.js +3 -3
  97. package/src/win32/shell.js +1 -1
  98. package/src/win32/window.js +2 -2
  99. package/src/windowid.js +1 -1
  100. package/src/xvideo.js +189 -0
  101. package/docs/architecture/accessibility.md +0 -470
  102. package/docs/architecture/animation.md +0 -707
  103. package/docs/architecture/container-queries.md +0 -525
  104. package/docs/architecture/custom-layout.md +0 -334
  105. package/docs/architecture/drag-and-drop.md +0 -941
  106. package/docs/architecture/element-layer-contents.md +0 -622
  107. package/docs/architecture/frame-pacing.md +0 -255
  108. package/docs/architecture/grid-layout.md +0 -358
  109. package/docs/architecture/protocol-efficiency.md +0 -357
  110. package/docs/architecture/video.md +0 -1149
  111. package/docs/architecture/windowed-regions.md +0 -854
  112. package/docs/glx.md +0 -137
  113. package/docs/wayland.md +0 -545
  114. package/docs/windows-embedding.md +0 -271
  115. package/docs/windows-gl.md +0 -221
package/docs/README.md CHANGED
@@ -1,202 +1,112 @@
1
1
  # react-x11 documentation
2
2
 
3
- react-x11 has **two backends**: X11 (a Linux desktop, a forwarded display,
4
- XQuartz) and Cocoa (a native Mac app, no X server anywhere). The same tree,
5
- components, styles and hooks run on both, and `createRoot()` picks — Cocoa
6
- on macOS where the bridge is installed, X11 otherwise. Every page below is
7
- about both unless it says otherwise; where a backend changes the answer, it
8
- is called out where the answer is. A native Wayland backend exists and is
9
- opt-in ([wayland-backend.md](wayland-backend.md), with its research RFC in
10
- [wayland.md](wayland.md)); Windows ships too
11
- ([windows-integrations.md](windows-integrations.md) for what it reaches,
12
- [windows.md](windows.md) for why it is built the way it is).
3
+ react-x11 renders one React tree to four backends: **X11** (a Linux desktop,
4
+ a forwarded display, XQuartz), **Cocoa** (a native Mac app, no X server
5
+ anywhere), **win32**, and an opt-in native **Wayland** backend. The same
6
+ tree, components, styles and hooks run on all of them, and `createRoot()`
7
+ picks — Cocoa on macOS and win32 on Windows where their bridges are
8
+ installed, X11 otherwise. Every page below is about every backend unless it
9
+ says otherwise; where a backend changes the answer, it is called out where
10
+ the answer is.
13
11
 
14
- - [macos.md](macos.md) — the Cocoa backend: what a retained layer tree
15
- changes about a renderer built for a drawing protocol, the two presenters
16
- (a bitmap surface per window, and a CALayer per node) and which one is the
17
- measured default, text through CoreText, input off an `NSApplication`
18
- pump driven by Node's loop, native controls, the menu bar, layer
19
- promotion, running as an app bundle, and what does not map — no window
20
- manager, no cross-process embedding. Also the design record for the parts
21
- still ahead.
22
- - [elements.md](elements.md) — the host elements: `<window>`, `<popup>`,
12
+ - [macos.md](macos.md) — the Cocoa backend: choosing it, its options,
13
+ windowing, text, input, native controls, the menu bar, app bundles, and
14
+ what does not map (no window manager, no cross-process embedding).
15
+ - [elements.md](elements.md) — the host elements (`<window>`, `<popup>`,
23
16
  `<box>`, `<text>`, `<textinput>`, `<textarea>`, `<image>`, `<canvas>`,
24
- `<svg>`, `<foreign>`, their props and refs — including
17
+ `<svg>`, `<foreign>`), their props and refs — including
25
18
  [selecting read-only text](elements.md#selecting-text) with `selectable`.
26
19
  - [styling.md](styling.md) — the `style` prop: layout and paint properties,
27
- `:hover`/`:focus`/`:active`/`:disabled` blocks, transitions, theme tokens,
28
- window size and container queries, `createStyles`, and
29
- [a font file of your own](styling.md#a-font-file-of-your-own) —
30
- `openFont`/`loadFont`/`useFont`.
31
- - [components.md](components.md) — widget components built on the
32
- primitives: theming, the basic controls (`Button`, `Checkbox`,
33
- `Radio`/`RadioGroup`, `Switch`, `ProgressBar`), `Select`, `Slider`,
34
- `Tooltip`, `Dialog`, `MenuBar`/`ContextMenu`, `Tabs`, `Table`,
35
- `SplitPane`, and the `useAnchor` popup placement hook.
36
- - [globalmenu.md](globalmenu.md) — handing a window's menu bar to wherever
37
- the platform keeps menus, with no configuration: the macOS menu bar on the
38
- cocoa backend, the desktop's panel over `com.canonical.dbusmenu` where one
39
- is running, and the drawn bar everywhere else. The item vocabulary
40
- `MenuBar` shares with all three, why detection means "a panel is running"
41
- rather than "one could be started", the diff that decides between patching
42
- properties and invalidating a layout, why `Control` in a shortcut means ⌘
43
- on a Mac, and the menu host in `scripts/` for seeing the D-Bus path work
44
- on a desktop that has none.
20
+ state blocks, transitions, theme tokens, container queries, `createStyles`,
21
+ and [a font file of your own](styling.md#a-font-file-of-your-own).
22
+ - [components.md](components.md) — the widgets (`Button`, `Checkbox`,
23
+ `Radio`, `Switch`, `ProgressBar`, `Select`, `Slider`, `Tooltip`, `Dialog`,
24
+ `MenuBar`/`ContextMenu`, `Tabs`, `Table`, `SplitPane`), theming, and the
25
+ `useAnchor` popup placement hook.
26
+ - [globalmenu.md](globalmenu.md) — a `MenuBar` handed to wherever the
27
+ platform keeps menus: the macOS menu bar, a desktop panel over
28
+ `com.canonical.dbusmenu`, or the drawn bar.
45
29
  - [events.md](events.md) — the synthetic event system: dispatch phases,
46
- event object shape, focus, cursors, default actions.
47
- - [accessibility.md](accessibility.md) — screen readers see react-x11 apps:
48
- the built-in AT-SPI2 bridge, the standard `role`/`aria-*` props on every
49
- element, what the defaults already say, what each widget announces,
50
- `announce()`, driving controls from assistive technology, the no-bus
51
- compatibility ladder, and how to test all of it without a desktop. The
52
- design record behind it — no mirror tree, the event pipeline, what was
53
- rejected — is
54
- [architecture/accessibility.md](architecture/accessibility.md).
55
- - [react-features.md](react-features.md) — what your React knowledge buys
56
- you here and where a DOM habit breaks: `useLayoutEffect` vs `useEffect`,
57
- measuring a node without `getBoundingClientRect()`, what a `ref` hands
58
- back, `<popup>` instead of `createPortal`, where to put an error boundary
59
- so the window survives, and which React APIs are simply not available.
60
- - [drag-and-drop.md](drag-and-drop.md) — accepting drops and starting
61
- drags, over XDND and in-app: `dropAccept` matching, the payload
62
- (`e.files`, `e.getData`, live `e.items`), `dragData` and lazy payloads,
63
- the `useDropTarget`/`useDragSource` hooks, drag previews, what GTK and
64
- Firefox actually offer, and how to drive a drag in a test.
65
- - [clipboard.md](clipboard.md) — copy and paste beyond the built-in text
66
- controls: `useClipboard()`, the CLIPBOARD/PRIMARY split, offering several
67
- flavours of one payload, the `text`/`files`/`uris` groups shared with drag
68
- and drop, `watch()`, and why a copy carries a timestamp — and what the
69
- pasteboard does differently on macOS.
30
+ event objects, focus, cursors, default actions.
31
+ - [accessibility.md](accessibility.md) — screen readers: the AT-SPI2 bridge,
32
+ `role`/`aria-*` on every element, what the widgets announce, `announce()`,
33
+ and testing it all without a desktop.
34
+ - [react-features.md](react-features.md) — where React knowledge carries
35
+ over and where a DOM habit breaks: effects, measuring a node, refs,
36
+ `<popup>` instead of `createPortal`, error boundaries, missing APIs.
37
+ - [drag-and-drop.md](drag-and-drop.md) — accepting drops and starting drags,
38
+ in-app and with other applications: `dropAccept`, payloads,
39
+ `useDropTarget`/`useDragSource`, previews, and driving a drag in a test.
40
+ - [clipboard.md](clipboard.md) — `useClipboard()`: CLIPBOARD and PRIMARY,
41
+ several flavours of one payload, the `text`/`files`/`uris` groups,
42
+ `watch()`, and the macOS pasteboard.
70
43
  - [typescript.md](typescript.md) — the bundled types: one tsconfig option,
71
- why JSX comes from `react-x11/jsx-runtime` rather than an augmentation,
72
- and how the declarations are kept from drifting.
44
+ and JSX from `react-x11/jsx-runtime`.
73
45
  - [extending.md](extending.md) — `registerElement()` and the subpath
74
- exports: adding a host element from outside the package, the node
75
- contract, the two definition fields that fail far from their cause, and
76
- the damage seam an element that draws a whole scene reads and claims.
77
- - [gl.md](gl.md) — `<glarea>`, a GL surface in the layout, and the three
78
- ways underneath it: indirect GLX, the direct GPU backend, and CGL into a
79
- layer on Cocoa. `glPolicy`, what each can draw, `<shaderMaterial>` — GLSL
80
- with three.js's names — and `<effectComposer>` post-processing, both on
81
- the direct ones.
82
- - [glx.md](glx.md) — how a 3D scene works over indirect GLX: what the
83
- protocol encodes, why display lists are mandatory, and what can never work.
46
+ exports: a host element from outside the package, the node contract, and
47
+ the damage seam for an element that draws a whole scene.
48
+ - [gl.md](gl.md) — `<glarea>`, a GL surface in the layout: `glPolicy`, the
49
+ backends underneath, `<shaderMaterial>` and `<effectComposer>`.
84
50
  - [embedding.md](embedding.md) — `<foreign>`: another application's window
85
- inside yours. XEmbed and the plain-reparent path most clients actually
86
- want, why unmount hands the window back rather than destroying it, and
87
- the rule that keeps an app's chords from being swallowed by the client.
88
- **X11 only** — cross-process window embedding does not exist on macOS.
89
- - [frame.md](frame.md) — `<Frame>`: a pane of your own application in a
90
- process of its own, embedded and laid out like any other child. What the
91
- process boundary buys (parallelism, crash and leak isolation), what it
92
- does not (it is not a security boundary), and the two ways it is realized
93
- — a `<foreign>` window on X11, shared IOSurfaces on Cocoa.
51
+ inside yours, over XEmbed or a plain reparent. **X11 only.**
52
+ - [frame.md](frame.md) — `<Frame>`: a pane of your own app in a process of
53
+ its own; what the process boundary buys, and that it is not a security
54
+ boundary.
94
55
  - [testing.md](testing.md) — `react-x11/test`: render, query, drive and
95
- assert on real pixels, against a real X server in your test process. No
96
- display, no xvfb — and no Cocoa: the harness drives the **X11** backend.
97
- - [desktop.md](desktop.md) — what an app tells the desktop about itself
98
- beyond drawing. Startup notification: why the launcher's busy cursor spins
99
- for 15 seconds without it, when an app counts as "started", and the seams
100
- for saying otherwise.
101
- - [dbus.md](dbus.md) — the bus every desktop-integration feature sits on:
102
- `useSessionBus()` / `useSystemBus()` with nothing to wrap, the imperative
103
- `sessionBus()` pair underneath, why one process is one connection and one
104
- identity, and why "there is no bus" is a first-class configuration rather
105
- than an error.
106
- - [uri-schemes.md](uri-schemes.md) — being the app a `myapp://…` link opens:
107
- `registerApplication()` and the two dispatch paths a real desktop uses (only
108
- one of which is D-Bus), why a second copy of the app has to forward and
109
- exit, `useAppOpen()`, and the timestamp without which the window does not
110
- actually come forward. Also: why a loopback port is the better answer for a
111
- login, and the `.desktop` half that is an install step rather than code.
112
- - [filedialog.md](filedialog.md) — open, save and pick a folder:
113
- `useFileDialog()`, the four-rung ladder (a native panel on the cocoa
114
- backend, the desktop's own portal, `osascript` under XQuartz, a browser
115
- react-x11 draws itself), why cancelling is
116
- `null` rather than a throw, and the places the backends genuinely differ.
117
- - [permissions.md](permissions.md) — may the app use the camera, the
118
- microphone, the screen, the accessibility APIs: `usePermission()`, the
119
- five-word status vocabulary (`'unknown'` is the machine's answer, not the
120
- permission's), the cocoa backend's TCC rung and the Settings-pane rung any
121
- Mac has, and why Linux answers `'unknown'` until the device portals land.
122
- - [notifications.md](notifications.md) — a banner outside the app's own
123
- windows: `notify()` and `useNotifier()`, the four-rung ladder (the cocoa
124
- backend's notification centre, `org.freedesktop.Notifications`,
125
- `osascript`, `notify-send`), updating a banner in place, what the user
126
- did with it, and why the shell-out rungs cannot report back.
127
- - [desktop-calendar.md](desktop-calendar.md) — the user's real events, with
128
- no credential and no OAuth: `useDesktopCalendarEvents()`, the three-rung
129
- ladder (EventKit through the bridge, EventKit through an `osascript` child,
130
- Evolution Data Server over the bus), why `end` is exclusive everywhere, and
131
- why `'denied'` and `'unavailable'` are different words.
132
- - [eyedropper.md](eyedropper.md) — sample a colour from the screen:
133
- `useEyedropper()`/`pickScreenColor()`, the three-rung ladder (macOS's
134
- `NSColorSampler`, the portal's own picker, a crosshair grab on plain X11),
135
- the interface `version` property that gates the portal rung where
136
- `hasService()` cannot, and why the grab's whole lifecycle — including the
137
- `<popup grab>` it displaces — belongs to core.
138
- - [appearance.md](appearance.md) — light or dark, the accent colour,
139
- contrast and reduced motion: `useSystemAppearance()`, `<ThemeProvider dark>`
140
- for apps that only want to follow the desktop, why the answer is remembered
141
- on disk so the first frame is not a flash, and what each rung of the ladder
142
- can actually answer.
143
- - [scale.md](scale.md) — HiDPI: every length you write is a logical pixel,
144
- `createRoot({ scale: 'auto' })` resolves how many device pixels one is
145
- worth (environment → XSETTINGS/`Xft.dpi` → audited RandR millimetres →
146
- the resolution class), `useScale()`, per-monitor answers on
147
- `useScreens()`, and why a virtual machine's EDID needs the audit.
148
- - [system.md](system.md) — the machine around the app: `useScreens()` for the
149
- monitor layout, `useWindowState()` for what the window manager actually did,
150
- `useIdle()`/`useKeepAwake()`, `useKeyboardState()` for Caps Lock and the live
151
- layout, `useDesktopSettings()` for the timings the built-in controls already
152
- follow, and `useLocale()`. Also what each one answers on a display with the
153
- extension missing, and why `obscured` is always false under a compositor.
154
- - [remote.md](remote.md) — the flagship case: running the app on one
155
- machine and drawing to a display on another. `ssh -X` vs `-Y`, what the
156
- protocol costs on a link, the other X servers, and why Xwayland works
157
- where native Wayland structurally cannot.
158
- - [wayland.md](wayland.md) — the research RFC for a native Wayland
159
- backend: a second target beside X11, not a migration. What the protocol
160
- actually changes, the fd transport (why the prototype is Bun-first), the
161
- rendering tiers from a pure-JS span compositor to GPU 2d over x11-dri,
162
- what maps and what is gone by design, and the phased plan.
163
- - [wayland-backend.md](wayland-backend.md) — the Wayland backend as built:
164
- GLES over dma-buf into a backing target, xdg-shell with deferred acks,
165
- client-side decorations, the XKB keymap reader, the in-process test
166
- compositor; what was measured (the protocol layer is not the cost, and
167
- no native protocol bridge was built), and what is still open.
56
+ assert on real pixels against an in-process X server. No display, and
57
+ always the **X11** backend.
58
+ - [desktop.md](desktop.md) — what an app tells the desktop beyond drawing:
59
+ startup notification, the launcher badge and Dock menu, the tray, feature
60
+ discovery, and turning it all off.
61
+ - [dbus.md](dbus.md) — the session and system bus: `useSessionBus()` /
62
+ `useSystemBus()`, `sessionBus()`, and "no bus" as a normal configuration.
63
+ - [uri-schemes.md](uri-schemes.md) — being the app a `myapp://…` link
64
+ opens: `registerApplication()`, `useAppOpen()`, single-instance
65
+ forwarding, and the `.desktop` half.
66
+ - [filedialog.md](filedialog.md) — `useFileDialog()`: open, save and pick a
67
+ folder, through a native panel, the desktop portal, `osascript` or a drawn
68
+ browser; cancelling is `null`.
69
+ - [permissions.md](permissions.md) — `usePermission()` for the camera, the
70
+ microphone, the screen and the accessibility APIs, and its five-word
71
+ status vocabulary.
72
+ - [notifications.md](notifications.md) — `notify()` and `useNotifier()`:
73
+ banners through the best available rung, updated in place, and what the
74
+ user did with them.
75
+ - [desktop-calendar.md](desktop-calendar.md) — `useDesktopCalendarEvents()`:
76
+ the user's real events, with no credential, via EventKit or Evolution
77
+ Data Server.
78
+ - [eyedropper.md](eyedropper.md) — `useEyedropper()`/`pickScreenColor()`:
79
+ sample a colour from the screen.
80
+ - [appearance.md](appearance.md) — light or dark, accent, contrast, reduced
81
+ motion: `useSystemAppearance()` and `<ThemeProvider dark>`.
82
+ - [scale.md](scale.md) — HiDPI: logical pixels, `createRoot({ scale: 'auto'
83
+ })`, `useScale()`, and per-monitor answers.
84
+ - [system.md](system.md) — the machine around the app: `useScreens()`,
85
+ `useWindowState()`, `useIdle()`/`useKeepAwake()`, `useKeyboardState()`,
86
+ `useDesktopSettings()`, `useLocale()`.
87
+ - [remote.md](remote.md) — running on one machine and drawing to a display
88
+ on another: `ssh -X` vs `-Y`, what the protocol costs on a link, the other
89
+ X servers.
90
+ - [wayland-backend.md](wayland-backend.md) — the opt-in native Wayland
91
+ backend: what runs, and what is still open.
92
+ - [windows.md](windows.md) — the win32 backend: choosing it, installing the
93
+ bridge, what maps and what does not.
168
94
  - [windows-integrations.md](windows-integrations.md) — what an app on
169
- Windows can actually reach, measured rather than inferred: the table of
170
- what works, the gaps that cost an app something today (drag and drop, IME,
171
- UI Automation) with the route for each, the integrations that are blocked
172
- on package identity rather than missing, and the things Windows has that
173
- no other desktop does.
174
- - [windows.md](windows.md) — the design record behind it, written as a PRD
175
- before any of it existed. Where Windows
176
- sits between the Wayland and macOS inversions (the client rasterizes, into
177
- retained composition surfaces that keep the damage model intact), a UI
178
- thread of the addon's own so that Windows' modal loops never freeze JS,
179
- Direct2D and DirectWrite behind the contracts the Cocoa backend already
180
- proved, why the bridge is our own mechanism-only addon rather than
181
- anything on npm, what maps and what is gone, the phased plan, and what to
182
- probe first on a Windows machine.
183
- - [security.md](security.md) — the threat model, plainly: X11 has no
184
- isolation between clients, `$XAUTHORITY` is a password, and what
185
- react-x11 does and does not defend against.
186
- - [packaging.md](packaging.md) — five ways to ship an app, the esbuild flags
187
- that are load-bearing, and the two macOS distribution tracks: Developer ID
188
- takes node or bun, the App Store's sandbox takes node only.
95
+ Windows can reach today, and the gaps.
96
+ - [security.md](security.md) — the threat model: X11 has no isolation
97
+ between clients, `$XAUTHORITY` is a password, and what react-x11 does and
98
+ does not defend against.
99
+ - [packaging.md](packaging.md) — five ways to ship an app, the load-bearing
100
+ esbuild flags, and macOS signing for Developer ID and the App Store.
189
101
  - [devtools.md](devtools.md) — React DevTools integration and other
190
102
  debugging aids.
191
- - [debugging.md](debugging.md) — runtime diagnostics: protocol tracing
192
- (`REACT_X11_TRACE`, `startTrace()`), repaint flashing and full-repaint
193
- warnings (`REACT_X11_DEBUG_PAINT`), invalidation reasons.
103
+ - [debugging.md](debugging.md) — runtime diagnostics: `REACT_X11_TRACE` and
104
+ `startTrace()`, `REACT_X11_DEBUG_PAINT`, invalidation reasons, and the
105
+ switches that turn one optimisation off.
194
106
  - [click-to-component.md](click-to-component.md) — Alt+Click a rendered
195
107
  element to open its JSX source line in your editor.
196
108
  - [ecosystem.md](ecosystem.md) — which npm packages work with react-x11 and
197
- which do not: the rule that decides it, a compatibility table across 12
198
- categories, and a register of the verbatim errors the incompatible ones
199
- produce. Per-category pages:
109
+ which do not, and why. Per category:
200
110
  [state](ecosystem/state.md), [data fetching](ecosystem/data-fetching.md),
201
111
  [forms](ecosystem/forms.md), [icons](ecosystem/icons.md),
202
112
  [theming](ecosystem/theming.md), [animation](ecosystem/animation.md),
@@ -205,71 +115,9 @@ opt-in ([wayland-backend.md](wayland-backend.md), with its research RFC in
205
115
  [i18n](ecosystem/i18n.md), [testing](ecosystem/testing.md),
206
116
  [dev tooling](ecosystem/dev-tooling.md).
207
117
 
208
- ## Design records
209
-
210
- `architecture/` holds the documents behind the bigger pieces: measured,
211
- written against a named commit, and kept as the record of _why_ rather than
212
- the reference for _what_. Some describe what shipped; some are proposals
213
- that have not been built, and say so at the top.
214
-
215
- - [architecture/frame-pacing.md](architecture/frame-pacing.md) — the
216
- design record behind `frameRate`: why a window fed off an input path
217
- paints screens nobody sees, the token bucket over paint time that holds
218
- it to a budget, where it lives on both backends, and what it measured.
219
- - [architecture/element-layer-contents.md](architecture/element-layer-contents.md)
220
- — the design record for the other half of a streaming element's frame on
221
- macOS: why an element with a retained surface pays a composite and the
222
- window swapchain's catch-up copy to move pixels it already has, what the
223
- platform does with an element-owned IOSurface (spiked in pixels), and the
224
- presentable `Surface` plus `presentedSurface()` policy that would remove
225
- both. Not built.
226
- - [architecture/video.md](architecture/video.md) — the design record for
227
- video, reviewed against the four backends: why no X11 extension decodes
228
- anything and the one that did is dead, what a decoded frame costs through
229
- core `PutImage` and what Xv would change, the VideoToolbox and Core
230
- Animation ladder on macOS measured end to end, the YUV surface that is
231
- blank through `render(in:)` and drawn on screen (probed, and it reverses
232
- the first version's Cocoa design), what a frame sink costs through a
233
- plain layer, the Media Foundation plan for Windows with the probes it
234
- owes, a `<video>` element with two sources — `frames` everywhere, `src`
235
- where the platform has a player — on the sprite seam, and how `<Html>`
236
- and `<MediaPlayer>` consume it. Not built.
237
- - [architecture/animation.md](architecture/animation.md) — what the style
238
- vocabulary cannot say today (a fade, a move that does not reflow, a
239
- timeline that ends), who should interpolate it, and what offloading a
240
- transition to Core Animation costs and buys.
241
- - [architecture/container-queries.md](architecture/container-queries.md) —
242
- why a container's size is an output of layout where a window's is an
243
- input, the resolve-after-a-pass loop that follows, and the oscillation it
244
- can produce. Implemented; [styling.md](styling.md#container-queries) is
245
- the reference.
246
- - [architecture/custom-layout.md](architecture/custom-layout.md) — why an
247
- arrangement that depends on a layout output has to run inside the pass
248
- rather than in an effect, the two seams that do — a `layout` that arranges
249
- a box's children and a `position` that moves one node, with `sticky` now
250
- the built-in one — how a layout's children become yoga trees of their own,
251
- and what they cost. Implemented; [styling.md](styling.md#custom-layouts)
252
- is the reference.
253
- - [architecture/grid-layout.md](architecture/grid-layout.md) — CSS Grid as
254
- a layout on that seam, written the way CSS writes it (`display: 'grid'`,
255
- `gridTemplateColumns`): why the style is flat, the spec's placement and
256
- track sizing and what is left out, how it is held to Chrome, and what it
257
- costs against flexbox — more than it should have, until the seam
258
- remembered what it asks a child. Implemented;
259
- [styling.md](styling.md#grid) is the reference.
260
- - [architecture/drag-and-drop.md](architecture/drag-and-drop.md) — XDND on
261
- both sides: where the advertisement lives when every control is drawn into
262
- one window, what the drag-source half costs, and the API review that
263
- produced the one in [drag-and-drop.md](drag-and-drop.md).
264
- - [architecture/accessibility.md](architecture/accessibility.md) — the
265
- AT-SPI2 bridge with no mirror tree: what it exposes, the event pipeline,
266
- and the alternatives that lost.
267
- - [architecture/protocol-efficiency.md](architecture/protocol-efficiency.md)
268
- — a request-by-request audit of one hovered checkbox, across react-x11,
269
- ntk and node-x11, and the fixes it produced.
270
- - [architecture/windowed-regions.md](architecture/windowed-regions.md) —
271
- when an X11 subwindow pays for itself and when it does not, measured
272
- against three servers. Research; nothing here is built.
118
+ Contributors: the design records behind these pages — history, rejected
119
+ alternatives, measurements, plans — are in
120
+ [design/README.md](../design/README.md), which does not ship.
273
121
 
274
122
  ## Entry points
275
123
 
@@ -280,11 +128,12 @@ import { createRoot, Select } from 'react-x11';
280
128
  ### `await createRoot(options?)` → `{ app, render(element), unmount() }`
281
129
 
282
130
  The entry point. With no options it opens a connection to whichever backend
283
- this machine has: the **Cocoa** bridge on macOS, or the X server named by
284
- `$DISPLAY`. On a Mac without `@windowkit/appkit` installed it falls back to
285
- X11, once and out loud, so an XQuartz setup keeps working. The returned
286
- `app` is that backend's app object — the [ntk](https://github.com/sidorares/ntk)
287
- App and its one X connection on X11.
131
+ this machine has: the **Cocoa** bridge on macOS, the **win32** bridge on
132
+ Windows, or the X server named by `$DISPLAY`. Without the bridge installed
133
+ it falls back to X11, once and out loud, so an XQuartz, WSLg or Cygwin
134
+ setup keeps working. The returned `app` is that backend's app object — the
135
+ [ntk](https://github.com/sidorares/ntk) App and its one X connection on
136
+ X11.
288
137
 
289
138
  **Every root without `app` opens its own connection and owns it**, so two
290
139
  roots are two independent trees, and `await root.unmount()` closes what it
@@ -292,38 +141,36 @@ opened — without which the socket stays up and the process does not exit.
292
141
  A root given an `app` borrows it and never closes it: that connection
293
142
  belongs to whoever made it.
294
143
 
295
- One thing to know about `'auto'` before it surprises you: on macOS it
296
- answers Cocoa, and **`$DISPLAY` in the environment does not change that.**
297
- Naming an X endpoint _in code_ — `display` or `stream` — does, because an
298
- ignored connection option would be worse than either answer; from the
299
- environment, say `REACT_X11_BACKEND=x11`. See
300
- [remote.md](remote.md) for the case this actually comes up in.
144
+ On macOS `'auto'` answers Cocoa, and **`$DISPLAY` in the environment does
145
+ not change that.** Naming an X endpoint _in code_ — `display` or `stream` —
146
+ does; from the environment, say `REACT_X11_BACKEND=x11`
147
+ ([remote.md](remote.md)).
301
148
 
302
- | option | |
303
- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
304
- | `backend` | `'auto'` (default), `'x11'` or `'cocoa'`. Naming `'cocoa'` makes the bridge required rather than preferred |
305
- | `app` | render into a connection you already have — the option a backend choice is ignored for |
306
- | `cocoa` | that backend's knobs: `presenter`, `promote`, `frameInterval`, `pumpInterval`, `appName`, `activationPolicy`, `exitOnQuit` ([macos.md](macos.md)) |
307
- | `scale` | device pixels per logical pixel: `'auto'` (default) or a number ([scale.md](scale.md)) |
308
- | `frameRate` | how windows pace frames under a flood: `'display'` (default) or `'adaptive'` ([elements.md](elements.md#framerate--pacing-the-frames-under-a-flood)) |
309
- | `desktop` | `false`, or `{ appearance, a11y, globalMenu }` — the three things that dial the session bus ([desktop.md](desktop.md)) |
310
- | `startupNotification` | freedesktop startup notification, on by default; `false`, or the id ([desktop.md](desktop.md)) |
311
- | `compose` | dead keys and Compose: the built-in table by default, `'system'`, `{ file }`/`{ sequences }`, or `false` |
312
- | `accelerators` | which keysym a shortcut matches: `'latin'` (default), `'layout'`, or a table |
313
- | `restoreFocusOnReveal` | whether a revealed subtree takes the keyboard back. Default `true` |
314
- | `textStripBelow` | the size under which `<text>` paints as a strip of ink rather than glyphs. Default 6; `0` never |
315
- | `display` | **X11.** `':1'`, `'host:0.0'`, a socket path. Default `$DISPLAY`. Naming one chooses the X11 backend |
316
- | `stream` | **X11.** an already-connected duplex stream — also a backend choice |
317
- | `fontSource` | **X11.** pluggable system-font lookup — ntk's docs/fonts.md |
318
- | `glPolicy` `glxVisual` | **X11.** which GL backend `<glarea>` draws through, and a visual for it ([gl.md](gl.md)) |
319
- | `onXError` | **X11.** protocol errors nothing claimed. Default warns |
320
- | `onUncaughtError` `onCaughtError` `onRecoverableError` | `(error, errorInfo)`; default logs the component stack |
321
- | `onDisconnect(reason, err)` | **X11.** the connection ended — `'closed'` or `'error'` |
149
+ | option | |
150
+ | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
151
+ | `backend` | `'auto'` (default), `'x11'`, `'cocoa'`, `'win32'` or `'wayland'` (opt-in; `'auto'` never picks it). Naming a bridge backend makes the bridge required rather than preferred |
152
+ | `app` | render into a connection you already have — the option a backend choice is ignored for |
153
+ | `cocoa` | that backend's knobs: `presenter`, `promote`, `frameInterval`, `pumpInterval`, `appName`, `activationPolicy`, `exitOnQuit` ([macos.md](macos.md)) |
154
+ | `scale` | device pixels per logical pixel: `'auto'` (default) or a number ([scale.md](scale.md)) |
155
+ | `frameRate` | how windows pace frames under a flood: `'display'` (default) or `'adaptive'` ([elements.md](elements.md#framerate--pacing-the-frames-under-a-flood)) |
156
+ | `desktop` | `false`, or `{ appearance, a11y, globalMenu }` — the three things that dial the session bus ([desktop.md](desktop.md)) |
157
+ | `startupNotification` | freedesktop startup notification, on by default; `false`, or the id ([desktop.md](desktop.md)) |
158
+ | `compose` | dead keys and Compose: the built-in table by default, `'system'`, `{ file }`/`{ sequences }`, or `false` |
159
+ | `accelerators` | which keysym a shortcut matches: `'latin'` (default), `'layout'`, or a table |
160
+ | `restoreFocusOnReveal` | whether a revealed subtree takes the keyboard back. Default `true` |
161
+ | `textStripBelow` | the size under which `<text>` paints as a strip of ink rather than glyphs. Default 6; `0` never |
162
+ | `display` | **X11.** `':1'`, `'host:0.0'`, a socket path. Default `$DISPLAY`. Naming one chooses the X11 backend |
163
+ | `stream` | **X11.** an already-connected duplex stream — also a backend choice |
164
+ | `fontSource` | **X11.** pluggable system-font lookup — ntk's docs/fonts.md |
165
+ | `glPolicy` `glxVisual` | **X11.** which GL backend `<glarea>` draws through, and a visual for it ([gl.md](gl.md)) |
166
+ | `onXError` | **X11.** protocol errors nothing claimed. Default warns |
167
+ | `onUncaughtError` `onCaughtError` `onRecoverableError` | `(error, errorInfo)`; default logs the component stack |
168
+ | `onDisconnect(reason, err)` | **X11.** the connection ended — `'closed'` or `'error'` |
322
169
 
323
170
  `display`, `stream`, `fontSource`, `glxVisual`, `glPolicy` and `onXError` go
324
- straight to ntk's `createClient`. Anything else it understands, build the
325
- client yourself and pass it as `app` — which is also how the hermetic tests
326
- drive the renderer against node-x11's in-process X server:
171
+ straight to ntk's `createClient`. For anything else it understands, build
172
+ the client yourself and pass it as `app`. A `stream` reaches a server that
173
+ is not on `$DISPLAY` — node-x11's in-process one, for instance:
327
174
 
328
175
  ```js
329
176
  import xserver from 'x11/lib/xserver/index.js';
@@ -340,43 +187,41 @@ input event rather than a render. See
340
187
  [events.md](events.md#when-a-handler-throws).
341
188
 
342
189
  `onDisconnect` fires when an X connection ends without being asked to —
343
- server exit, ssh drop, kill — and not for one this root closed. It invites
344
- a reconnect loop, so: **a reconnect is not a reconnect.** Every window id,
345
- pixmap, glyph set and font is invalidated with the connection. Tear the
346
- root down and build a new one; nothing survives, and react-x11 promises
347
- nothing more than telling you it happened.
190
+ server exit, ssh drop, kill — and not for one this root closed. **A
191
+ reconnect is not a reconnect:** every window id, pixmap, glyph set and font
192
+ is invalidated with the connection, so tear the root down and build a new
193
+ one.
348
194
 
349
- `root.render(element, callback?)` flushes the mount or update synchronously
350
- (`updateContainerSync` + `flushSyncWork`); painting happens a frame later on
351
- the window's frame clock.
195
+ `root.render(element, callback?)` flushes the mount or update
196
+ synchronously (`updateContainerSync` + `flushSyncWork`); painting happens a
197
+ frame later on the window's frame clock.
352
198
 
353
199
  ## Environment variables
354
200
 
355
201
  Every one of these has an option or a prop that says the same thing in code;
356
- the variable exists for the cases where you cannot edit the call — someone
357
- else's app, a `.desktop` launcher, an A/B run. `npx react-x11 help` prints
358
- every one the renderer reads, the diagnostic switches included, grouped and
359
- with what each does.
202
+ the variable is for when you cannot edit the call — someone else's app, a
203
+ `.desktop` launcher, an A/B run. `npx react-x11 help` prints every one the
204
+ renderer reads, the diagnostic switches included.
360
205
 
361
206
  **Choosing a backend and a display**
362
207
 
363
- | variable | effect |
364
- | ---------------------------- | ------------------------------------------------------------------------ |
365
- | `DISPLAY` | X server to connect to (standard X11) |
366
- | `REACT_X11_BACKEND` | `x11`, `cocoa` or `wayland`, overriding `backend` and the default |
367
- | `REACT_X11_GL_DEVICE` | Wayland: the DRM node to render on, where `glPolicy.devicePath` is unset |
368
- | `REACT_X11_SCALE` | device pixels per logical pixel; outranks even a pinned `scale` number |
369
- | `REACT_X11_FRAME_RATE` | `display` or `adaptive`, overriding `frameRate` and the props |
370
- | `REACT_X11_TEXT_STRIP_BELOW` | the `textStripBelow` size, for a process that cannot pass the option |
208
+ | variable | effect |
209
+ | ---------------------------- | -------------------------------------------------------------------------- |
210
+ | `DISPLAY` | X server to connect to (standard X11) |
211
+ | `REACT_X11_BACKEND` | `x11`, `cocoa`, `win32` or `wayland`, overriding `backend` and the default |
212
+ | `REACT_X11_GL_DEVICE` | Wayland: the DRM node to render on, where `glPolicy.devicePath` is unset |
213
+ | `REACT_X11_SCALE` | device pixels per logical pixel; outranks even a pinned `scale` number |
214
+ | `REACT_X11_FRAME_RATE` | `display` or `adaptive`, overriding `frameRate` and the props |
215
+ | `REACT_X11_TEXT_STRIP_BELOW` | the `textStripBelow` size, for a process that cannot pass the option |
371
216
 
372
217
  **Turning desktop integration off**
373
218
 
374
- | variable | effect |
375
- | ----------------------------- | --------------------------------------------------------------------- |
376
- | `REACT_X11_A11Y` | set at all: log why the AT-SPI bridge did not start. `0` turns it off |
377
- | `NO_AT_BRIDGE=1` | the freedesktop spelling of the same off switch |
378
- | `REACT_X11_NO_GLOBAL_MENU=1` | `MenuBar` always draws its own bar |
379
- | `REACT_X11_NO_TRANSPARENCY=1` | pretend there is no compositor ([debugging.md](debugging.md)) |
219
+ | variable | effect |
220
+ | ----------------------------- | ---------------------------------------------------------------------------------------- |
221
+ | `REACT_X11_A11Y` | set at all: log why the AT-SPI bridge did not start. `0` turns it off |
222
+ | `NO_AT_BRIDGE=1` | the freedesktop spelling of the same off switch |
223
+ | `REACT_X11_NO_GLOBAL_MENU=1` | `MenuBar` always draws its own bar |
224
+ | `REACT_X11_NO_TRANSPARENCY=1` | pretend there is no compositor ([debugging.md](debugging.md#react_x11_no_transparency1)) |
380
225
 
381
226
  **Development and diagnostics**
382
227
 
@@ -401,10 +246,11 @@ with what each does.
401
246
  | `REACT_X11_COCOA_PANE_STRETCH` | `behind` (default), `never` or `always`: when a `<Frame>` pane's last frame is stretched while a resize waits on the next ([frame.md](frame.md)) |
402
247
  | `REACT_X11_CALAYERS_PATH` | load the bridge from a checkout or an extracted tarball instead of the package |
403
248
 
404
- There are a handful more that exist only to switch off one optimisation
405
- while measuring it — `REACT_X11_NO_PAINT_CACHE`, `REACT_X11_NO_SCROLL_BLIT`,
406
- `REACT_X11_NO_PANE_SHAPE`,
407
- `REACT_X11_NO_BOUNDS_CACHE`, `REACT_X11_NO_STROKE_CHUNKING`,
408
- `REACT_X11_NO_SCOPED_FLOORS`, `REACT_X11_NO_UNREAD_WIDTHS`,
409
- `REACT_X11_NO_REFIT_HOLD`, `REACT_X11_NO_APPEARANCE_CACHE`. They are development instruments, not API,
410
- and they are documented where the thing they disable is.
249
+ A handful more exist only to switch off one optimisation while measuring it
250
+ — `REACT_X11_NO_PAINT_CACHE`, `REACT_X11_NO_SCROLL_BLIT`,
251
+ `REACT_X11_NO_PANE_SHAPE`, `REACT_X11_NO_BOUNDS_CACHE`,
252
+ `REACT_X11_NO_STROKE_CHUNKING`, `REACT_X11_NO_SCOPED_FLOORS`,
253
+ `REACT_X11_NO_UNREAD_WIDTHS`, `REACT_X11_NO_REFIT_HOLD`,
254
+ `REACT_X11_NO_APPEARANCE_CACHE`. They are development instruments, not API,
255
+ documented in [debugging.md](debugging.md) or where the thing they disable
256
+ is.