react-x11 2.52.0 → 2.53.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 +1091 -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/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/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/embedding.md
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
# Embedding other applications: `<foreign>`
|
|
2
2
|
|
|
3
|
-
> **X11 only.**
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
> not offer the primitive. On the Cocoa backend `<foreign>` refuses: it lays
|
|
7
|
-
> out as an empty box, never calls `onReady`, and calls `onError` once — and
|
|
3
|
+
> **X11 only.** macOS offers no primitive for taking another application's
|
|
4
|
+
> window into your own. On the Cocoa backend `<foreign>` lays out as an empty
|
|
5
|
+
> box, never calls `onReady`, and calls `onError` once;
|
|
8
6
|
> `useSupports('embedding')` is false there, so a component can ask before
|
|
9
|
-
> rendering one.
|
|
10
|
-
>
|
|
11
|
-
> shared surfaces instead of reparenting.
|
|
7
|
+
> rendering one. [`<Frame>`](frame.md) does work there: it embeds a pane of
|
|
8
|
+
> _your own_ application through shared surfaces instead of reparenting.
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
`<foreign>` is the one element that shows somebody else's pixels: another
|
|
11
|
+
process's top-level X window, reparented into yours and laid out like any
|
|
12
|
+
other child — a terminal pane, a video surface, a docked tray icon, a
|
|
13
|
+
control-panel applet.
|
|
16
14
|
|
|
17
15
|
```jsx
|
|
18
16
|
<foreign
|
|
@@ -23,36 +21,27 @@ window, reparented into yours and laid out like any other child.
|
|
|
23
21
|
/>
|
|
24
22
|
```
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
teardown holds for a `<Frame>` pane too. The pane's own root window opts in
|
|
35
|
-
with `<window embeddable>`: created **unmapped** — a window waiting to be
|
|
36
|
-
embedded is unmapped, that is what waiting looks like — and mapped by the
|
|
37
|
-
embedder once reparented. On X11 it is an XEmbed client for Tab: `FOCUS_IN`
|
|
38
|
-
with `FIRST` or `LAST` lands on its first or last stop, and Tab off an end of
|
|
39
|
-
its order sends `FOCUS_NEXT` or `FOCUS_PREV`, so Tab goes through a
|
|
40
|
-
react-x11 guest as it goes through any subtree of the host's.
|
|
24
|
+
For a module of **your own application**, use [`<Frame>`](frame.md):
|
|
25
|
+
`<foreign>` plus the process — the fork, the props, the callbacks, the bridged
|
|
26
|
+
theme, the crash fallback. Everything below about stacking, focus and teardown
|
|
27
|
+
holds for a `<Frame>` pane too. The pane's root window opts in with
|
|
28
|
+
`<window embeddable>`: created **unmapped**, which is what waiting to be
|
|
29
|
+
embedded looks like, and mapped by the embedder once reparented. On X11 it
|
|
30
|
+
speaks XEmbed's Tab, so Tab goes through a react-x11 guest as through any
|
|
31
|
+
subtree of the host's.
|
|
41
32
|
|
|
42
33
|
**Being the guest yourself** — a react-x11 app embedded in somebody else's UI
|
|
43
|
-
— is that same prop plus
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
what the element does, what it promises about a window it does not own, and
|
|
55
|
-
what it does with the keyboard.
|
|
34
|
+
— is that same prop plus `windowHandleOf(ref)` (or `useWindowHandle(ref)`):
|
|
35
|
+
the number you hand the host, out of band, the way `xterm -into` is handed
|
|
36
|
+
one. On X11 it is the window's XID, which the host reparents. On Windows it is
|
|
37
|
+
a composition surface handle the host binds to a visual of its own, because a
|
|
38
|
+
window there stops presenting the moment it becomes a child
|
|
39
|
+
([design notes](../design/windows-embedding.md)). `null` means this backend
|
|
40
|
+
has no way to be a guest — the capability, not a failure.
|
|
41
|
+
|
|
42
|
+
The protocol underneath is
|
|
43
|
+
[XEmbed](http://specifications.freedesktop.org/xembed/0.5/). Design notes:
|
|
44
|
+
[design/embedding.md](../design/embedding.md).
|
|
56
45
|
|
|
57
46
|
## Two ways in
|
|
58
47
|
|
|
@@ -79,9 +68,8 @@ is in it — that is the point.
|
|
|
79
68
|
## Most clients do not speak XEmbed
|
|
80
69
|
|
|
81
70
|
`xterm -into`, `mpv --wid`, VLC and Wine set no `_XEMBED_INFO` and want plain
|
|
82
|
-
reparenting.
|
|
83
|
-
|
|
84
|
-
reports which happened:
|
|
71
|
+
reparenting. That is the ordinary case, not an error or a fallback, and it is
|
|
72
|
+
what makes a terminal pane work at all. `onEmbedded` reports which happened:
|
|
85
73
|
|
|
86
74
|
```jsx
|
|
87
75
|
onEmbedded={({ id, xembed, version }) => { … }}
|
|
@@ -96,19 +84,11 @@ client is mapped and unmapped as its own `XEMBED_MAPPED` bit asks.
|
|
|
96
84
|
|
|
97
85
|
Unmounting a `<foreign>` **reparents the client back to the root window and
|
|
98
86
|
drops it from the save set. It never destroys it.** A React tree changing
|
|
99
|
-
shape is not a reason for another application to lose its window
|
|
100
|
-
first test in `test/foreign.test.js` is there to keep it that way.
|
|
87
|
+
shape is not a reason for another application to lose its window.
|
|
101
88
|
|
|
102
89
|
The same holds for `windowId` changing: the client that is leaving is handed
|
|
103
90
|
back before the new one is taken.
|
|
104
91
|
|
|
105
|
-
What this costs is an ordering rule, and it is the one thing worth knowing
|
|
106
|
-
about the implementation: the reparent is issued **synchronously** during
|
|
107
|
-
teardown, because `WindowNode` destroys its own X window in the same turn and
|
|
108
|
-
`DestroyWindow` takes every inferior with it. The save set does not cover
|
|
109
|
-
that — X processes it when a _connection_ closes, not when a window is
|
|
110
|
-
destroyed.
|
|
111
|
-
|
|
112
92
|
`onClientGone` fires when the client is destroyed by its own process, or
|
|
113
93
|
reparented away by someone else. Nothing further is sent to a dead id.
|
|
114
94
|
|
|
@@ -116,32 +96,28 @@ reparented away by someone else. Nothing further is sent to a dead id.
|
|
|
116
96
|
|
|
117
97
|
A released client is a top-level window again, and **a running window manager
|
|
118
98
|
will manage it** — frame it, put it in the taskbar, place it wherever its
|
|
119
|
-
policy says. That is
|
|
120
|
-
|
|
121
|
-
|
|
99
|
+
policy says. That is right for an unmount (`examples/foreign.jsx` is built on
|
|
100
|
+
it: detach the pane and the terminal is simply a terminal window on the
|
|
101
|
+
desktop), and a trap for one thing:
|
|
122
102
|
|
|
123
103
|
> **Do not hand a client from one `<foreign>` to another by unmounting the
|
|
124
104
|
> first and mounting the second with the same `windowId`.**
|
|
125
105
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
does not always happen, which is worse than if it always did.
|
|
106
|
+
In between, the window is parked at the root long enough to be offered to the
|
|
107
|
+
window manager, whose reparent into a frame can arrive _after_ the second pane
|
|
108
|
+
has taken the client and undo it; the second pane then reports `onClientGone`
|
|
109
|
+
for a client that is alive and framed on the desktop. It is a race with
|
|
110
|
+
another process, so it does not always happen.
|
|
132
111
|
|
|
133
|
-
Change `windowId` on **one** node instead
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
the reparent pulls it out and the WM unmanages it — the hazard is only the
|
|
137
|
-
moment right after a release.)
|
|
112
|
+
Change `windowId` on **one** node instead: that path releases and re-embeds in
|
|
113
|
+
order. Re-embedding a window the WM has already framed also works — the
|
|
114
|
+
hazard is only the moment right after a release.
|
|
138
115
|
|
|
139
116
|
## Layout and stacking
|
|
140
117
|
|
|
141
118
|
The rect comes from yoga like any other child, and every change moves the
|
|
142
|
-
client and
|
|
143
|
-
|
|
144
|
-
`ConfigureNotify` (relative to the container it now sits in) cannot answer.
|
|
119
|
+
client and tells it its root-relative position (the synthetic ICCCM
|
|
120
|
+
`ConfigureNotify`).
|
|
145
121
|
|
|
146
122
|
Two consequences of it being a real X window, both shared with
|
|
147
123
|
[`<glarea>`](elements.md#glarea):
|
|
@@ -154,29 +130,15 @@ Two consequences of it being a real X window, both shared with
|
|
|
154
130
|
hit testing, which is exactly right for a terminal or a video surface.
|
|
155
131
|
|
|
156
132
|
`backgroundColor` in the `style` is what shows in the rect before a client
|
|
157
|
-
arrives and after one leaves —
|
|
158
|
-
|
|
159
|
-
everywhere else.
|
|
133
|
+
arrives and after one leaves — the container window's background, painted by
|
|
134
|
+
the server. There is no separate prop for it.
|
|
160
135
|
|
|
161
136
|
## Focus, and who gets the keys
|
|
162
137
|
|
|
163
|
-
X gives the input focus to one window.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
`SendEvent`.
|
|
168
|
-
|
|
169
|
-
**react-x11 does not use a proxy**, and the reason matters if you are reading
|
|
170
|
-
the code expecting one:
|
|
171
|
-
|
|
172
|
-
- A proxy inside our own toplevel means the toplevel sees `FocusOut` the moment
|
|
173
|
-
the client is focused. react-x11 reads that as the window losing focus —
|
|
174
|
-
carets stop blinking, `<window onBlur>` fires — and the element would be told
|
|
175
|
-
to blur the client it had just focused.
|
|
176
|
-
- A key that reaches a proxy has already gone past every handler in the React
|
|
177
|
-
tree, so an application chord could never be checked first.
|
|
178
|
-
|
|
179
|
-
So the X focus stays on your window, and the rule is:
|
|
138
|
+
X gives the input focus to one window. react-x11 keeps the X focus on your
|
|
139
|
+
window and gives the client a _logical_ focus by XEmbed message — no focus
|
|
140
|
+
proxy, which would make your window read the client's focus as its own blur
|
|
141
|
+
and let keys past every handler in the React tree. So the rule is:
|
|
180
142
|
|
|
181
143
|
> While a `<foreign>` holds focus, the application's handlers see every key
|
|
182
144
|
> first. Anything they do not consume is forwarded to the client.
|
|
@@ -205,32 +167,30 @@ Edit menu's, which is what a user of that terminal expects. An application
|
|
|
205
167
|
chord that must win everywhere goes in an `onKeyDown` like the one above,
|
|
206
168
|
which is checked before either.
|
|
207
169
|
|
|
208
|
-
Everything else about focus is the ordinary focus manager
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
| the client sends `XEMBED_REQUEST_FOCUS` | the node is focused _through the focus manager_, so `:focus`, `:focus-within`, the previous node's `onBlur` and the AT-SPI bridge all see it |
|
|
217
|
-
| the client sends `FOCUS_NEXT` / `FOCUS_PREV` | focus moves to the next/previous react-x11 focusable — Tab crosses the boundary as if it were one application |
|
|
170
|
+
Everything else about focus is the ordinary focus manager. Clicking or
|
|
171
|
+
`focus()`-ing the node activates the client and focuses it; Tab and Shift+Tab
|
|
172
|
+
into it focus its first or last widget; focus leaving, or the window
|
|
173
|
+
deactivating, unfocuses and deactivates it. A client asking for the focus
|
|
174
|
+
(`onRequestFocus`) is focused _through the focus manager_, so `:focus`,
|
|
175
|
+
`:focus-within`, the previous node's `onBlur` and the AT-SPI bridge all see
|
|
176
|
+
it. The XEmbed message behind each step is in the
|
|
177
|
+
[design notes](../design/embedding.md#focus-and-who-gets-the-keys).
|
|
218
178
|
|
|
219
179
|
A `<foreign>` is focusable by default, like a `<textinput>`. `focusable={false}`
|
|
220
180
|
opts out, which is what a video surface wants.
|
|
221
181
|
|
|
222
|
-
Tab is _forwarded_ rather than acted on
|
|
223
|
-
own and
|
|
224
|
-
|
|
225
|
-
for
|
|
182
|
+
Tab is _forwarded_ rather than acted on. An XEmbed client has a tab chain of
|
|
183
|
+
its own, and running off either end of it moves focus to the next or previous
|
|
184
|
+
react-x11 focusable — Tab crosses the boundary as if it were one application.
|
|
185
|
+
A client that speaks no XEmbed — a terminal — keeps Tab for good, which is
|
|
186
|
+
what a terminal is for; click elsewhere to leave.
|
|
226
187
|
|
|
227
188
|
**Dead keys and Compose stay out of it.** react-x11's own composition
|
|
228
189
|
([events.md](events.md#composition)) does not run while a `<foreign>` holds
|
|
229
|
-
focus: the client
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
terminal whatever the toolkit inside it is.
|
|
190
|
+
focus: the client has an input method of its own, and an accent composed on
|
|
191
|
+
this side would swallow the key on its way there. The raw key is forwarded and
|
|
192
|
+
the client composes it, which is what makes `é` work in an embedded terminal
|
|
193
|
+
whatever the toolkit inside it is.
|
|
234
194
|
|
|
235
195
|
### The one gap
|
|
236
196
|
|
|
@@ -243,24 +203,22 @@ would make in the other direction.
|
|
|
243
203
|
## Reparenting window managers
|
|
244
204
|
|
|
245
205
|
A `<foreign>` inside a toplevel that the window manager has reparented into a
|
|
246
|
-
frame is offset by that frame
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
server rather than trusting reported geometry — the same problem
|
|
250
|
-
`src/components/anchor.js` solves for popup placement.
|
|
206
|
+
frame is offset by that frame. react-x11 tracks the toplevel's screen origin
|
|
207
|
+
and tells the client its true root-relative position; nothing is needed from
|
|
208
|
+
the app.
|
|
251
209
|
|
|
252
210
|
## Props
|
|
253
211
|
|
|
254
|
-
| prop |
|
|
255
|
-
| ---------------- |
|
|
256
|
-
| `windowId` | the X window to embed
|
|
257
|
-
| `onReady` | `({ windowId })` — the node's own container id,
|
|
258
|
-
| `onEmbedded` | `({ id, xembed, version })` — a client is in
|
|
259
|
-
| `onClientGone` | destroyed, or reparented away by someone else
|
|
260
|
-
| `onRequestFocus` | the client asked for the focus (
|
|
261
|
-
| `onError` | the embed failed — no such window, or it went away mid-handshake
|
|
262
|
-
| `focusable` | default `true`; takes part in the focus manager and the tab chain
|
|
263
|
-
| `style` | layout as usual; `backgroundColor`
|
|
212
|
+
| prop | |
|
|
213
|
+
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
214
|
+
| `windowId` | the X window to embed; a change hands the old client back first. Omit to adopt whatever is put inside the node |
|
|
215
|
+
| `onReady` | `({ windowId })` — the node's own container id, before anything is embedded, to spawn a program into |
|
|
216
|
+
| `onEmbedded` | `({ id, xembed, version })` — a client is in |
|
|
217
|
+
| `onClientGone` | destroyed, or reparented away by someone else |
|
|
218
|
+
| `onRequestFocus` | the client asked for the focus (then given through the focus manager) |
|
|
219
|
+
| `onError` | the embed failed — no such window, or it went away mid-handshake; without a handler, a console warning |
|
|
220
|
+
| `focusable` | default `true`; takes part in the focus manager and the tab chain |
|
|
221
|
+
| `style` | layout as usual; `backgroundColor` shows with no client in |
|
|
264
222
|
|
|
265
223
|
## Example
|
|
266
224
|
|
|
@@ -275,14 +233,7 @@ FOREIGN_CMD="mpv --wid=%WID% video.mp4" npm run examples:foreign
|
|
|
275
233
|
|
|
276
234
|
## What is not here yet
|
|
277
235
|
|
|
278
|
-
- **`<TrayHost>`** —
|
|
279
|
-
|
|
280
|
-
panel a real desktop shell. The system tray is XEmbed's biggest surviving
|
|
281
|
-
consumer.
|
|
236
|
+
- **`<TrayHost>`** — hosting other applications' tray icons (owning the
|
|
237
|
+
system tray selection, a `<foreign>` per docked icon).
|
|
282
238
|
- **The plug side** — a react-x11 root that renders _into_ someone else's
|
|
283
|
-
socket,
|
|
284
|
-
deliberately last: GTK4 removed `GtkPlug` and Qt dropped `QX11Embed*` after
|
|
285
|
-
Qt4, so the population of hosts willing to embed us is shrinking while the
|
|
286
|
-
population of clients we can host is not.
|
|
287
|
-
|
|
288
|
-
Both are tracked in [issue #269](https://github.com/sidorares/react-x11/issues/269).
|
|
239
|
+
XEmbed socket, as a tray icon or a panel applet.
|