react-x11 2.22.8 → 2.22.10
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 +1 -1
- package/src/a11ypace.js +83 -0
- package/src/atspi.js +76 -18
- package/src/cocoa/app.js +30 -3
- package/src/cocoa/bezels.js +69 -1
- package/src/cocoa/window.js +24 -0
- package/src/components/Button.js +28 -12
- package/src/components/Select.js +3 -3
- package/src/components/native.js +43 -12
- package/src/frames.js +7 -0
- package/src/glnodes.js +26 -0
- package/src/gloverlay.js +772 -79
- package/src/nodes/paint.js +11 -2
- package/src/nodes/window/floors.js +40 -4
- package/src/win32/a11y.js +47 -39
package/src/components/native.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import React, { useCallback, useRef } from 'react';
|
|
21
21
|
import { useAppOrNull } from '../appcontext.js';
|
|
22
|
-
import { useTheme } from './theme.js';
|
|
22
|
+
import { capBand, useTheme } from './theme.js';
|
|
23
23
|
|
|
24
24
|
const h = React.createElement;
|
|
25
25
|
|
|
@@ -101,6 +101,37 @@ export function nativeTitleStyle(controlSize = 'regular') {
|
|
|
101
101
|
return { alignSelf: 'flex-end', fontSize: CONTROL_FONT_SIZE[controlSize] };
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Where a push button's title goes in a control whose padding is only the
|
|
106
|
+
* bezel's shadow — so the box inside it is the body, and an icon beside the
|
|
107
|
+
* title is centred on the body as AppKit centres an image. The title is a
|
|
108
|
+
* margin box inside that: `TITLE_BASELINE` under its last baseline, and over
|
|
109
|
+
* its capitals the room a one-line title leaves there in a body of the
|
|
110
|
+
* bezel's own height. So a title that fits sits exactly where the cell puts
|
|
111
|
+
* it, filling the body to the pixel, and one that wrapped keeps the same
|
|
112
|
+
* margins round the lines it grew by: the control is taller by those lines,
|
|
113
|
+
* and so is the bezel drawn to it (src/cocoa/bezels.js, the flexible push).
|
|
114
|
+
* AppKit's own flexible push starts a wrapped title's capitals within half a
|
|
115
|
+
* point of here (4.5pt under the body's top edge at the regular size, 4 at
|
|
116
|
+
* the small) and ends it 2.5pt nearer the bottom edge at the regular size:
|
|
117
|
+
* the one-line baseline is kept instead, so a title does not move when it
|
|
118
|
+
* wraps, and a wrapped button is that much taller than AppKit's.
|
|
119
|
+
*
|
|
120
|
+
* The capitals are measured the way the title will be, `capBand` of the
|
|
121
|
+
* control font size, so the two cancel: a face whose trimmed caps round to
|
|
122
|
+
* the band — every UI face measured — fills the body exactly and never
|
|
123
|
+
* grows the control by a line it does not have.
|
|
124
|
+
*/
|
|
125
|
+
export function nativeTitleMargins(nat, shadow, controlSize = 'regular') {
|
|
126
|
+
const body = nat.height - shadow.top - shadow.bottom;
|
|
127
|
+
const baseline = TITLE_BASELINE[controlSize];
|
|
128
|
+
const caps = capBand(CONTROL_FONT_SIZE[controlSize]);
|
|
129
|
+
return {
|
|
130
|
+
marginTop: Math.max(0, body - baseline - caps),
|
|
131
|
+
marginBottom: baseline,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
104
135
|
/**
|
|
105
136
|
* The **footprint** a native control sits in: the box the caller's style
|
|
106
137
|
* sizes, with the control — bezel, title and press wash, one unit at
|
|
@@ -108,9 +139,9 @@ export function nativeTitleStyle(controlSize = 'regular') {
|
|
|
108
139
|
*
|
|
109
140
|
* Two boxes rather than one, because the title is *placed* and not centred:
|
|
110
141
|
* it rides `TITLE_BASELINE` above the bezel body's bottom edge, and that is
|
|
111
|
-
* only where the cell puts it while the box is
|
|
112
|
-
*
|
|
113
|
-
*
|
|
142
|
+
* only where the cell puts it while the box is the control's own height. The
|
|
143
|
+
* caller's style is applied last and flex stretches a box regardless, so it
|
|
144
|
+
* was not always: `style={{ height: 44 }}`, a `height: '100%'` in a taller
|
|
114
145
|
* parent and a bare `flexGrow: 1` each made the box taller, and the two
|
|
115
146
|
* halves — the bezel absolutely filling it, the title glued to its bottom —
|
|
116
147
|
* came apart, the label landing below the control it names (issue #510). The
|
|
@@ -118,20 +149,20 @@ export function nativeTitleStyle(controlSize = 'regular') {
|
|
|
118
149
|
* control is merely roomy, where a stretched native one was broken.
|
|
119
150
|
*
|
|
120
151
|
* So the height a caller can move belongs to a box the control sits in, and
|
|
121
|
-
* the control keeps
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* the
|
|
152
|
+
* the control keeps its own. Untouched, the footprint is exactly as tall as
|
|
153
|
+
* the control — AppKit's height, or a button's taller one when its label
|
|
154
|
+
* wrapped — and the caller's style, applied after it, moves the footprint
|
|
155
|
+
* alone. A row's align-stretch moves it too, and the control stays centred
|
|
156
|
+
* in the slot, which is where a control that cannot stretch belongs beside a
|
|
157
|
+
* taller neighbour. The control stretches across it (align-stretch, the
|
|
158
|
+
* default), so a footprint given a width is a bezel that wide.
|
|
126
159
|
*
|
|
127
160
|
* The control, not the footprint, stays the *control*: the role, the
|
|
128
161
|
* handlers, the focus ring and the ref go on it, so a press in the slack
|
|
129
162
|
* above a 22pt popup in a 46pt hole does nothing at all — as it does in
|
|
130
163
|
* AppKit — rather than firing a button with no visible answer to the press.
|
|
131
164
|
*/
|
|
132
|
-
export
|
|
133
|
-
return { height: nat.height, justifyContent: 'center' };
|
|
134
|
-
}
|
|
165
|
+
export const NATIVE_FOOTPRINT = Object.freeze({ justifyContent: 'center' });
|
|
135
166
|
|
|
136
167
|
/**
|
|
137
168
|
* The rest of what a native control's own box says about its size: nothing
|
package/src/frames.js
CHANGED
|
@@ -53,6 +53,12 @@ export function clearPendingFrame(node) {
|
|
|
53
53
|
* - **Every window answers for itself.** The set is app-wide, so a click
|
|
54
54
|
* that dirtied both a menu and the window under it paints both, each
|
|
55
55
|
* gated on its own window's frame clock.
|
|
56
|
+
* - **Nor while a `<glarea>` of it waits on the clock.** A window's frame
|
|
57
|
+
* paints the overlay a surface's children are drawn on, and the clock
|
|
58
|
+
* draws the surface's own frame after it, in the same tick (#641). A
|
|
59
|
+
* window that says it owes one (`surfaceFrameOwed`) keeps its paced
|
|
60
|
+
* frame: painted now, the overlay would go out a refresh or more ahead
|
|
61
|
+
* of the GL frame it was painted for.
|
|
56
62
|
*
|
|
57
63
|
* A window whose scheduled frame this pays off keeps that scheduled
|
|
58
64
|
* callback; it runs and finds `needsPaint` false, which is already a cheap
|
|
@@ -68,6 +74,7 @@ export function flushPendingFrames() {
|
|
|
68
74
|
// Same for a headless mock window that models no frame clock at all.
|
|
69
75
|
if (typeof wnd?.frameInFlight !== 'function') continue;
|
|
70
76
|
if (wnd.frameInFlight()) continue;
|
|
77
|
+
if (wnd.surfaceFrameOwed?.()) continue;
|
|
71
78
|
node.flush();
|
|
72
79
|
}
|
|
73
80
|
}
|
package/src/glnodes.js
CHANGED
|
@@ -38,6 +38,10 @@ function recordGlxFailure(app, err) {
|
|
|
38
38
|
if (app && err && !glxFailures.has(app)) glxFailures.set(app, err);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// ChangeWindowAttributes' backing-store value: the server keeps what the
|
|
42
|
+
// window shows while it is mapped (`_create`)
|
|
43
|
+
const BACKING_STORE_WHEN_MAPPED = 1;
|
|
44
|
+
|
|
41
45
|
// Apps already told that a <glarea>'s children are not drawn on their
|
|
42
46
|
// display. Once per app, as for a <foreign> that cannot embed: the answer
|
|
43
47
|
// belongs to the server, so the next surface to find out carries no news.
|
|
@@ -301,6 +305,19 @@ export class GlAreaNode extends Node {
|
|
|
301
305
|
this.rect = rect;
|
|
302
306
|
this.config = config;
|
|
303
307
|
wnd._reactX11Node = this;
|
|
308
|
+
// The server keeps what the surface shows while it is mapped (X backing
|
|
309
|
+
// store), so a pane over it that moves away — a card dragged across a
|
|
310
|
+
// graph drawn in GL — uncovers the last frame at once. Without it the
|
|
311
|
+
// uncovered pixels were the pane's until the surface drew again: an
|
|
312
|
+
// Expose, a frame requested, and the next vblank, which is a trail of
|
|
313
|
+
// the card behind it on every step. ntk forwards no backing-store
|
|
314
|
+
// attribute (its `backingStore` is its own double buffer), and a
|
|
315
|
+
// backend with no X connection has none to set.
|
|
316
|
+
if (typeof this.app.X?.ChangeWindowAttributes === 'function') {
|
|
317
|
+
this.app.X.ChangeWindowAttributes(wnd.id, {
|
|
318
|
+
backingStore: BACKING_STORE_WHEN_MAPPED,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
304
321
|
// Above everything 2D in the owning window on both backends, and above
|
|
305
322
|
// every surface made before this one: X stacks a new child window over
|
|
306
323
|
// its siblings, and Core Animation a layer added later over one at the
|
|
@@ -328,6 +345,15 @@ export class GlAreaNode extends Node {
|
|
|
328
345
|
this.gl?.ready?.catch((err) => {
|
|
329
346
|
if (!this.destroyed) this._failed(err, { reported: true });
|
|
330
347
|
});
|
|
348
|
+
// …and a context that fails after it was ready — a swap the driver
|
|
349
|
+
// refused mid-life — says so here (ntk >= 8.12.11). Before ntk said so,
|
|
350
|
+
// the surface kept its last frame, or nothing, with no word to anyone:
|
|
351
|
+
// on NVIDIA every resize did that (sidorares/ntk#399).
|
|
352
|
+
if (this.gl && 'onError' in this.gl) {
|
|
353
|
+
this.gl.onError = (err) => {
|
|
354
|
+
if (!this.destroyed) this._failed(err);
|
|
355
|
+
};
|
|
356
|
+
}
|
|
331
357
|
wnd.on?.('expose', () => this.requestFrame());
|
|
332
358
|
wnd.map?.();
|
|
333
359
|
// made on top of its siblings — over the panes of children that were
|