react-x11 2.12.0 → 2.14.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/package.json +12 -8
- package/src/Reconciler.js +38 -35
- package/src/appcontext.js +59 -30
- package/src/cocoa/app.js +11 -0
- package/src/cocoa/glarea.js +4 -2
- package/src/cocoa/overlay.js +159 -0
- package/src/cocoa/promotion.js +13 -0
- package/src/components/Select.js +8 -2
- package/src/embedding.js +31 -0
- package/src/events.js +80 -14
- package/src/foreignnodes.js +56 -3
- package/src/glnodes.js +171 -40
- package/src/gloverlay.js +383 -0
- package/src/host.d.ts +0 -1
- package/src/index.d.ts +19 -1
- package/src/node.d.ts +12 -1
- package/src/nodes/boxpaint.js +9 -0
- package/src/nodes/preedit.js +64 -14
- package/src/nodes/window/flush.js +35 -0
- package/src/nodes/window/window.js +9 -0
- package/src/scale.js +52 -22
- package/src/screencolor.js +104 -17
- package/src/types/elements.d.ts +15 -13
- package/src/wayland/app.js +560 -0
- package/src/wayland/backendwindow.js +1123 -0
- package/src/wayland/clipboard.js +326 -0
- package/src/wayland/connection.js +482 -0
- package/src/wayland/context2d.js +2133 -0
- package/src/wayland/decorations.js +476 -0
- package/src/wayland/dmabuf.js +89 -0
- package/src/wayland/dnd.js +581 -0
- package/src/wayland/fdutil.js +108 -0
- package/src/wayland/framestyle.js +257 -0
- package/src/wayland/glarea.js +371 -0
- package/src/wayland/glcontext.js +415 -0
- package/src/wayland/glyphatlas.js +237 -0
- package/src/wayland/input.js +417 -0
- package/src/wayland/keysymnames.js +35 -0
- package/src/wayland/layershell.js +363 -0
- package/src/wayland/outputs.js +601 -0
- package/src/wayland/protocols/cursor-shape-v1.json +1 -0
- package/src/wayland/protocols/ext-idle-notify-v1.json +1 -0
- package/src/wayland/protocols/ext-image-capture-source-v1.json +1 -0
- package/src/wayland/protocols/ext-image-copy-capture-v1.json +1 -0
- package/src/wayland/protocols/fractional-scale-v1.json +1 -0
- package/src/wayland/protocols/index.json +127 -0
- package/src/wayland/protocols/keyboard-shortcuts-inhibit-unstable-v1.json +1 -0
- package/src/wayland/protocols/linux-dmabuf-v1.json +1 -0
- package/src/wayland/protocols/pointer-constraints-unstable-v1.json +1 -0
- package/src/wayland/protocols/presentation-time.json +1 -0
- package/src/wayland/protocols/primary-selection-unstable-v1.json +1 -0
- package/src/wayland/protocols/relative-pointer-unstable-v1.json +1 -0
- package/src/wayland/protocols/tablet-v2.json +1 -0
- package/src/wayland/protocols/text-input-unstable-v3.json +1 -0
- package/src/wayland/protocols/viewporter.json +1 -0
- package/src/wayland/protocols/wayland.json +1 -0
- package/src/wayland/protocols/wlr-layer-shell-unstable-v1.json +1 -0
- package/src/wayland/protocols/wlr-screencopy-unstable-v1.json +1 -0
- package/src/wayland/protocols/xdg-activation-v1.json +1 -0
- package/src/wayland/protocols/xdg-decoration-unstable-v1.json +1 -0
- package/src/wayland/protocols/xdg-output-unstable-v1.json +1 -0
- package/src/wayland/protocols/xdg-shell.json +1 -0
- package/src/wayland/protocols/xdg-toplevel-icon-v1.json +1 -0
- package/src/wayland/readback.js +99 -0
- package/src/wayland/screencopy.js +584 -0
- package/src/wayland/seat.js +584 -0
- package/src/wayland/shm.js +226 -0
- package/src/wayland/ssd.js +106 -0
- package/src/wayland/surface.js +123 -0
- package/src/wayland/swapchain.js +411 -0
- package/src/wayland/tablet.js +522 -0
- package/src/wayland/target.js +263 -0
- package/src/wayland/text.js +113 -0
- package/src/wayland/textinput.js +671 -0
- package/src/wayland/touch.js +284 -0
- package/src/wayland/window.js +827 -0
- package/src/wayland/xkb.js +425 -0
package/src/scale.js
CHANGED
|
@@ -166,6 +166,18 @@ const VIRTUAL_EDID_VENDORS = new Set([
|
|
|
166
166
|
]);
|
|
167
167
|
const VIRTUAL_MODEL = /qemu|virtual|vbox|vmware|parallels|bochs|bhyve/i;
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Whether an EDID's vendor and model name software — or a compositor's
|
|
171
|
+
* `wl_output` make and model, which are the same two strings read off the
|
|
172
|
+
* same EDID (mutter says 'RHT' / 'QEMU Monitor' for a QEMU guest's screen).
|
|
173
|
+
*/
|
|
174
|
+
export function isVirtualDisplay(vendor, model) {
|
|
175
|
+
return (
|
|
176
|
+
(vendor != null && VIRTUAL_EDID_VENDORS.has(vendor)) ||
|
|
177
|
+
(model != null && VIRTUAL_MODEL.test(model))
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
169
181
|
/**
|
|
170
182
|
* The 128-byte EDID base block → what the scale ladder wants from it:
|
|
171
183
|
* vendor, model name, the physical size, and the one derived judgement —
|
|
@@ -202,9 +214,7 @@ export function parseEdid(buffer) {
|
|
|
202
214
|
break;
|
|
203
215
|
}
|
|
204
216
|
}
|
|
205
|
-
const virtual =
|
|
206
|
-
(vendor !== null && VIRTUAL_EDID_VENDORS.has(vendor)) ||
|
|
207
|
-
(model !== null && VIRTUAL_MODEL.test(model));
|
|
217
|
+
const virtual = isVirtualDisplay(vendor, model);
|
|
208
218
|
return { vendor, model, mmWidth, mmHeight, virtual };
|
|
209
219
|
}
|
|
210
220
|
|
|
@@ -352,13 +362,17 @@ export function monitorScaleFromMetadata(monitor, { perPanel = true } = {}) {
|
|
|
352
362
|
}
|
|
353
363
|
|
|
354
364
|
// No physical truth to reason from. The pixel grid alone still separates
|
|
355
|
-
// "unmistakably a retina panel" from everything else
|
|
356
|
-
//
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
//
|
|
360
|
-
//
|
|
361
|
-
|
|
365
|
+
// "unmistakably a retina panel" from everything else. 2560x1600, a 30"
|
|
366
|
+
// desk monitor, is the tallest grid a 1x panel ships with, and nothing is
|
|
367
|
+
// sold as 1x with a short side between that and 1800 — so a short side
|
|
368
|
+
// past 1600 is a 2x grid: the 2560x1664 and 2880x1800 laptop lids, and a
|
|
369
|
+
// VM *window* over a retina panel, which is all a guest sees of its host
|
|
370
|
+
// (2488x1668 is a UTM window on a 14" MacBook). A long side of 3000 or
|
|
371
|
+
// more catches the wide ones. 2560x1440 and 2560x1600 stay at 1 on
|
|
372
|
+
// purpose — the commonest *1x* desk monitors there are, and only
|
|
373
|
+
// millimetres could tell them from a 13" retina lid, which is exactly the
|
|
374
|
+
// data this branch does not have.
|
|
375
|
+
if (perPanel && (Math.min(pxW, pxH) > 1600 || Math.max(pxW, pxH) >= 3000)) {
|
|
362
376
|
return {
|
|
363
377
|
scale: 2,
|
|
364
378
|
source: 'resolution',
|
|
@@ -379,6 +393,26 @@ export function monitorScaleFromMetadata(monitor, { perPanel = true } = {}) {
|
|
|
379
393
|
// The desktop-configuration rungs
|
|
380
394
|
// --------------------------------------------------------------------------
|
|
381
395
|
|
|
396
|
+
/**
|
|
397
|
+
* The factor a person or the app pinned, or null for `'auto'`:
|
|
398
|
+
* `REACT_X11_SCALE` (0.5–8) first, then a numeric `createRoot({ scale })`
|
|
399
|
+
* clamped to [0.5, 8]. The ladder's first word, and the only one a backend
|
|
400
|
+
* with a scale of its own (a Wayland compositor's) lets outrank that scale.
|
|
401
|
+
*/
|
|
402
|
+
export function pinnedScale(option) {
|
|
403
|
+
const own = Number(process.env.REACT_X11_SCALE);
|
|
404
|
+
if (Number.isFinite(own) && own >= 0.5 && own <= 8) {
|
|
405
|
+
return { scale: own, source: 'REACT_X11_SCALE' };
|
|
406
|
+
}
|
|
407
|
+
if (typeof option === 'number' && Number.isFinite(option)) {
|
|
408
|
+
return { scale: Math.min(8, Math.max(0.5, option)), source: 'option' };
|
|
409
|
+
}
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** `REACT_X11_DEBUG_SCALE`'s line, for the backends that decide their own. */
|
|
414
|
+
export const traceScale = trace;
|
|
415
|
+
|
|
382
416
|
function envScale() {
|
|
383
417
|
const own = Number(process.env.REACT_X11_SCALE);
|
|
384
418
|
// wider bounds than `snapScale` on purpose: an explicit override is a
|
|
@@ -609,18 +643,14 @@ export async function beginScale(app, option) {
|
|
|
609
643
|
session = new ScaleSession();
|
|
610
644
|
sessions.set(app, session);
|
|
611
645
|
|
|
612
|
-
const
|
|
613
|
-
if (
|
|
614
|
-
session.scale =
|
|
615
|
-
session.source =
|
|
616
|
-
trace(
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
if (typeof option === 'number' && Number.isFinite(option)) {
|
|
621
|
-
session.scale = Math.min(8, Math.max(0.5, option));
|
|
622
|
-
session.source = 'option';
|
|
623
|
-
trace(`${session.scale}x from createRoot({ scale })`);
|
|
646
|
+
const pinned = pinnedScale(option);
|
|
647
|
+
if (pinned) {
|
|
648
|
+
session.scale = pinned.scale;
|
|
649
|
+
session.source = pinned.source;
|
|
650
|
+
trace(
|
|
651
|
+
`${pinned.scale}x from ` +
|
|
652
|
+
(pinned.source === 'option' ? 'createRoot({ scale })' : pinned.source),
|
|
653
|
+
);
|
|
624
654
|
return session;
|
|
625
655
|
}
|
|
626
656
|
|
package/src/screencolor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Sample one pixel from the screen — the eyedropper, through whatever this
|
|
2
2
|
// machine actually has.
|
|
3
3
|
//
|
|
4
|
-
// The file dialog's ladder again (docs/filedialog.md),
|
|
4
|
+
// The file dialog's ladder again (docs/filedialog.md), four rungs:
|
|
5
5
|
//
|
|
6
6
|
// 1. **the system sampler** — `NSColorSampler` on the cocoa backend
|
|
7
7
|
// (src/cocoa/screencolor.js). macOS draws the loupe out of process, so
|
|
@@ -11,24 +11,31 @@
|
|
|
11
11
|
// 2. **the portal** — `org.freedesktop.portal.Screenshot.PickColor`. The
|
|
12
12
|
// desktop draws its own magnifier and hands back the colour, which is
|
|
13
13
|
// also the only route that works under a compositor that would refuse a
|
|
14
|
-
// root read, and
|
|
14
|
+
// root read, and GNOME's only route on Wayland. Needs version 2 of
|
|
15
15
|
// the Screenshot interface — XFCE ships none, GNOME and KDE ship 2 —
|
|
16
16
|
// so the gate is the interface's `version` property, not `hasService()`.
|
|
17
|
-
// 3. **
|
|
17
|
+
// 3. **the Wayland backend's own picker** — where the compositor offers a
|
|
18
|
+
// screen capture protocol and layer-shell (wlroots: sway, labwc, …)
|
|
19
|
+
// but no portal, the backend freezes the output into a capture, shows
|
|
20
|
+
// it as an overlay and takes the click on that
|
|
21
|
+
// (src/wayland/screencopy.js). Below the portal because the portal is
|
|
22
|
+
// the desktop's picker and user-consented; guarded by the backend's
|
|
23
|
+
// name because the capability is a Wayland object through and through.
|
|
24
|
+
// 4. **X11** — grab the pointer with a crosshair, wait for the click,
|
|
18
25
|
// `GetImage` a 1×1 at it, decode by the server's own pixel layout.
|
|
19
26
|
// Reached under a bare WM, over ssh, on XQuartz: everywhere there is a
|
|
20
27
|
// display and nothing else, which is the case react-x11 exists for.
|
|
21
28
|
//
|
|
22
|
-
// Rungs 1
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
29
|
+
// Rungs 1 to 3 are the same shape — ask, a picker is drawn, an sRGB triple
|
|
30
|
+
// comes back — which is why the sampler goes on top of the portal rather
|
|
31
|
+
// than under the crosshair: where the OS will do this for us, it does it
|
|
32
|
+
// better, and `hexFromPortalColor()` converts for all three.
|
|
26
33
|
//
|
|
27
34
|
// There is no rung to *draw*, because the thing being read — the whole
|
|
28
35
|
// screen — is precisely what an application cannot draw itself. So unlike
|
|
29
36
|
// `useFileDialog()`, `useEyedropper()` adds no rung; it adds the binding a
|
|
30
37
|
// component wants (`picking`, `supported`, the owner window) over these
|
|
31
|
-
//
|
|
38
|
+
// four.
|
|
32
39
|
//
|
|
33
40
|
// Which means the ladder really can run out, and where it does the floor has
|
|
34
41
|
// to be the typed rejection rather than a crash. A cocoa app on a bridge
|
|
@@ -83,8 +90,9 @@ export class NoScreenColorError extends Error {
|
|
|
83
90
|
message ??
|
|
84
91
|
'no way to sample a colour from the screen — no cocoa app with a ' +
|
|
85
92
|
'system sampler, no Screenshot portal with PickColor (interface ' +
|
|
86
|
-
'version 2) on the session bus,
|
|
87
|
-
'
|
|
93
|
+
'version 2) on the session bus, no Wayland compositor with screen ' +
|
|
94
|
+
'capture and layer-shell, and no X connection was given for the ' +
|
|
95
|
+
'fallback. Pass `app` (from createRoot() or useApp()), or use ' +
|
|
88
96
|
'useEyedropper().'
|
|
89
97
|
}`,
|
|
90
98
|
{ cause },
|
|
@@ -212,7 +220,14 @@ async function portalPick(opts, ref) {
|
|
|
212
220
|
// options)` — no title — which is the whole reason portalRequest takes a
|
|
213
221
|
// signature now.
|
|
214
222
|
signature: 'sa{sv}',
|
|
215
|
-
|
|
223
|
+
// The handle names an X window. A Wayland toplevel has none to name —
|
|
224
|
+
// an xdg-foreign export would be the equivalent — so there the dialog
|
|
225
|
+
// floats, which the portal allows.
|
|
226
|
+
args: [
|
|
227
|
+
appFor(opts)?.backend === 'wayland'
|
|
228
|
+
? ''
|
|
229
|
+
: parentWindowHandle(windowIdOf(opts.parentWindow)),
|
|
230
|
+
],
|
|
216
231
|
options: {},
|
|
217
232
|
signal: opts.signal,
|
|
218
233
|
});
|
|
@@ -237,7 +252,49 @@ async function portalCanPick(ref) {
|
|
|
237
252
|
}
|
|
238
253
|
|
|
239
254
|
// --------------------------------------------------------------------------
|
|
240
|
-
// Rung 3:
|
|
255
|
+
// Rung 3: the Wayland backend's own picker
|
|
256
|
+
// --------------------------------------------------------------------------
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* The Wayland app whose compositor can freeze and show the screen, or null.
|
|
260
|
+
*
|
|
261
|
+
* Guarded by the backend's name, unlike the sampler: `screenCapture` is the
|
|
262
|
+
* capability, but it is a Wayland object through and through — the pick is
|
|
263
|
+
* a layer-shell overlay over a screencopy frame (src/wayland/screencopy.js)
|
|
264
|
+
* — and `canPick` is the compositor's answer, not the app's. GNOME's is no:
|
|
265
|
+
* it advertises neither protocol, and the portal above is its route.
|
|
266
|
+
*/
|
|
267
|
+
function waylandApp(opts) {
|
|
268
|
+
const app = appFor(opts);
|
|
269
|
+
return app?.backend === 'wayland' && app.screenCapture?.canPick ? app : null;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Freeze, show, click — the sampler's contract: `'#rrggbb'`, null on Escape,
|
|
274
|
+
* a rejection on abort. Unlike the sampler the overlay is ours, and it is
|
|
275
|
+
* down before the promise settles either way, so an abort leaves nothing on
|
|
276
|
+
* screen.
|
|
277
|
+
*/
|
|
278
|
+
function waylandPick(opts, app) {
|
|
279
|
+
const signal = opts.signal;
|
|
280
|
+
if (signal?.aborted) {
|
|
281
|
+
return Promise.reject(signal.reason ?? new PortalCancelledError());
|
|
282
|
+
}
|
|
283
|
+
return app.screenCapture.pickColor({ signal }).then((color) => {
|
|
284
|
+
if (color == null) return null;
|
|
285
|
+
const hex = hexFromPortalColor([color.r, color.g, color.b]);
|
|
286
|
+
if (!hex) {
|
|
287
|
+
throw new Error(
|
|
288
|
+
'react-x11: the Wayland screen pick answered without a colour — ' +
|
|
289
|
+
`expected sRGB { r, g, b } in 0–1, got ${JSON.stringify(color)}.`,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
return hex;
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// --------------------------------------------------------------------------
|
|
297
|
+
// Rung 4: X11
|
|
241
298
|
// --------------------------------------------------------------------------
|
|
242
299
|
|
|
243
300
|
// x11.eventMask bits, spelled out the way xsettings.js spells its one. No
|
|
@@ -680,6 +737,16 @@ function canGrabOn(app) {
|
|
|
680
737
|
* fixes, and only one of them is the caller's.
|
|
681
738
|
*/
|
|
682
739
|
function noX11Reason(app, backend) {
|
|
740
|
+
if (app?.backend === 'wayland') {
|
|
741
|
+
return (
|
|
742
|
+
'this tree renders through the Wayland backend, and its compositor ' +
|
|
743
|
+
'offers neither a Screenshot portal with PickColor nor a screen ' +
|
|
744
|
+
'capture protocol (wlr-screencopy, ext-image-copy-capture) together ' +
|
|
745
|
+
'with wlr-layer-shell to draw the picker on. ' +
|
|
746
|
+
'`useEyedropper().supported` is false, which is the signal to leave ' +
|
|
747
|
+
'the eyedropper button undrawn (docs/wayland-backend.md).'
|
|
748
|
+
);
|
|
749
|
+
}
|
|
683
750
|
if (app) {
|
|
684
751
|
return (
|
|
685
752
|
'this tree does not render through an X connection — a cocoa-backend ' +
|
|
@@ -710,15 +777,17 @@ function noX11Reason(app, backend) {
|
|
|
710
777
|
* Screenshot interface at version 2 — the probe reads the interface's
|
|
711
778
|
* `version` property, because `hasService()` cannot see which interfaces a
|
|
712
779
|
* portal's backends actually provide (XFCE's provides no Screenshot at
|
|
713
|
-
* all). `'
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
* answer
|
|
780
|
+
* all). `'wayland'` is a Wayland-backend app (`app`, or a `parentWindow`
|
|
781
|
+
* in one) whose compositor advertises a screen capture protocol and
|
|
782
|
+
* layer-shell — wlroots without a portal. `'x11'` needs a connection to
|
|
783
|
+
* answer with, so pass `app` (or a `parentWindow` that resolves to one) —
|
|
784
|
+
* and one that can actually grab, which a cocoa-backend app cannot. With
|
|
785
|
+
* none of the four the honest answer is `null`.
|
|
717
786
|
*
|
|
718
787
|
* Acquires a bus reference and releases it, so it is cheap but not free —
|
|
719
788
|
* `useEyedropper().supported` caches it for you.
|
|
720
789
|
*
|
|
721
|
-
* @returns {Promise<'cocoa'|'portal'|'x11'|null>}
|
|
790
|
+
* @returns {Promise<'cocoa'|'portal'|'wayland'|'x11'|null>}
|
|
722
791
|
*/
|
|
723
792
|
export async function screenColorBackend(options = {}) {
|
|
724
793
|
const backend = options.backend;
|
|
@@ -737,6 +806,10 @@ export async function screenColorBackend(options = {}) {
|
|
|
737
806
|
}
|
|
738
807
|
if (backend === 'portal') return null;
|
|
739
808
|
}
|
|
809
|
+
if (!backend || backend === 'wayland') {
|
|
810
|
+
if (waylandApp(options)) return 'wayland';
|
|
811
|
+
if (backend === 'wayland') return null;
|
|
812
|
+
}
|
|
740
813
|
return canGrabOn(appFor(options)) ? 'x11' : null;
|
|
741
814
|
}
|
|
742
815
|
|
|
@@ -775,6 +848,20 @@ async function runPick(opts) {
|
|
|
775
848
|
}
|
|
776
849
|
}
|
|
777
850
|
|
|
851
|
+
const wantWayland = !opts.backend || opts.backend === 'wayland';
|
|
852
|
+
if (wantWayland) {
|
|
853
|
+
const app = waylandApp(opts);
|
|
854
|
+
if (app) return await waylandPick(opts, app);
|
|
855
|
+
if (opts.backend === 'wayland') {
|
|
856
|
+
throw new NoScreenColorError(
|
|
857
|
+
"backend: 'wayland' — no screen pick here: this tree does not " +
|
|
858
|
+
'render through the Wayland backend, or its compositor offers ' +
|
|
859
|
+
'neither a screen capture protocol (wlr-screencopy, ' +
|
|
860
|
+
'ext-image-copy-capture) nor wlr-layer-shell.',
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
778
865
|
const app = appFor(opts);
|
|
779
866
|
if (canGrabOn(app)) return x11Pick(opts, app);
|
|
780
867
|
throw new NoScreenColorError(noX11Reason(app, opts.backend));
|
package/src/types/elements.d.ts
CHANGED
|
@@ -915,6 +915,16 @@ export interface SvgProps extends DrawnProps<DrawnNode> {
|
|
|
915
915
|
|
|
916
916
|
export type FrameLoop = 'demand' | 'always';
|
|
917
917
|
|
|
918
|
+
/**
|
|
919
|
+
* `<glarea>`: a GL surface in the layout. Its **children** are 2D content
|
|
920
|
+
* drawn above the surface — laid out in its box like a `<box>`'s and cut to
|
|
921
|
+
* it, painted over the GL frame, hit before it — composited on the Cocoa
|
|
922
|
+
* backend and opaque on X11 (docs/elements.md); `useSupports('glOverlay')`
|
|
923
|
+
* asks whether they will be. The pointer over it is the tree's, as over any
|
|
924
|
+
* node: the handlers it inherits (`onMouseDown`, `onClick`, `onWheel`, …)
|
|
925
|
+
* fire at the child under the pointer or the `<glarea>` and bubble, on both
|
|
926
|
+
* backends, and `GlAreaNode.forwardsPointer` says so at run time.
|
|
927
|
+
*/
|
|
918
928
|
export interface GlAreaProps extends DrawnProps<DrawnNode> {
|
|
919
929
|
/** CSS colour, or `[r, g, b, a]` floats. Default black. */
|
|
920
930
|
clearColor?: Color | [number, number, number, number];
|
|
@@ -937,17 +947,6 @@ export interface GlAreaProps extends DrawnProps<DrawnNode> {
|
|
|
937
947
|
onDraw?: (gl: any, info: DrawInfo) => void;
|
|
938
948
|
/** No GL surface — no GLX, or no matching visual. */
|
|
939
949
|
onError?: (err: Error) => void;
|
|
940
|
-
/**
|
|
941
|
-
* The wheel over the surface. Inherited from `EventHandlers` like every
|
|
942
|
-
* other element's, and listed here because it is the **only** pointer
|
|
943
|
-
* event a `<glarea>` currently reports: the surface owns its own X window,
|
|
944
|
-
* so it selects the wheel there and hands it to the window's event manager
|
|
945
|
-
* (see docs/elements.md). Deltas are pixels, `preventDefault()` takes the
|
|
946
|
-
* default scroll action back, and it bubbles from this node.
|
|
947
|
-
*/
|
|
948
|
-
onWheel?: (ev: WheelEvent<DrawnNode>) => void;
|
|
949
|
-
/** A click inside the surface that hit no mesh. */
|
|
950
|
-
onPointerMissed?: (ev: MouseEvent<DrawnNode>) => void;
|
|
951
950
|
}
|
|
952
951
|
|
|
953
952
|
// --- embedding -------------------------------------------------------------
|
|
@@ -973,7 +972,9 @@ export interface ForeignProps extends DrawnProps<DrawnNode> {
|
|
|
973
972
|
*/
|
|
974
973
|
windowId?: number;
|
|
975
974
|
/** The container window's id, offered as soon as it exists, so a program
|
|
976
|
-
* can be spawned into it. Fires before there is anything embedded
|
|
975
|
+
* can be spawned into it. Fires before there is anything embedded — and
|
|
976
|
+
* never on a backend with no embedding (`useSupports('embedding')`), so the
|
|
977
|
+
* id is always a real window's. */
|
|
977
978
|
onReady?: (info: { windowId: number; node: DrawnNode }) => void;
|
|
978
979
|
/** A client is in. */
|
|
979
980
|
onEmbedded?: (info: EmbeddedInfo) => void;
|
|
@@ -982,7 +983,8 @@ export interface ForeignProps extends DrawnProps<DrawnNode> {
|
|
|
982
983
|
/** `XEMBED_REQUEST_FOCUS`: the client wants the focus. It is given through
|
|
983
984
|
* the focus manager unless a handler prevents it by focusing elsewhere. */
|
|
984
985
|
onRequestFocus?: (info: { node: DrawnNode }) => void;
|
|
985
|
-
/** The embed failed — no such window, or it went away mid-handshake
|
|
986
|
+
/** The embed failed — no such window, or it went away mid-handshake — or
|
|
987
|
+
* this backend cannot embed at all, which is reported once, at mount.
|
|
986
988
|
* Without a handler the failure is a console warning. */
|
|
987
989
|
onError?: (err: Error) => void;
|
|
988
990
|
}
|