react-x11 2.14.0 → 2.15.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 +1 -1
- package/src/glnodes.js +15 -3
- package/src/ntk.js +10 -1
- package/src/types/system.d.ts +14 -1
- package/src/wayland/app.js +14 -0
- package/src/wayland/backendwindow.js +86 -10
- package/src/wayland/connection.js +3 -0
- package/src/wayland/context2d.js +176 -19
- package/src/wayland/device.js +55 -0
- package/src/wayland/framewatch.js +190 -0
- package/src/wayland/glarea.js +1 -0
- package/src/wayland/protocols/index.json +4 -0
- package/src/wayland/protocols/kde-server-decoration.json +1 -0
- package/src/wayland/ssd.js +154 -26
- package/src/wayland/surface.js +18 -0
- package/src/wayland/target.js +6 -0
- package/src/wayland/window.js +36 -9
- package/src/windowstate.js +41 -1
package/src/windowstate.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
// | `minimized` `maximized` `fullscreen` `states` | `_NET_WM_STATE`, as ntk's `statechange` event |
|
|
17
17
|
// | `obscured` | VisibilityNotify |
|
|
18
18
|
// | `desktop` | `_NET_WM_DESKTOP` |
|
|
19
|
+
// | `presenting` | the Wayland frame clock, where the backend has one |
|
|
19
20
|
//
|
|
20
21
|
// Nothing here is asked for until something subscribes. `_NET_WM_STATE`
|
|
21
22
|
// costs a PropertyChange selection and a round trip per change,
|
|
@@ -35,6 +36,18 @@
|
|
|
35
36
|
// is the field to branch on. An animation paused on `visible` stops when the
|
|
36
37
|
// window is minimized everywhere, and additionally when it is buried on a
|
|
37
38
|
// desktop with no compositor.
|
|
39
|
+
//
|
|
40
|
+
// ## Wayland answers the same question from the other end
|
|
41
|
+
//
|
|
42
|
+
// A Wayland compositor never says a surface is covered either — but it stops
|
|
43
|
+
// sending it frame callbacks, and the backend's frame loop notices the
|
|
44
|
+
// silence (`src/wayland/framewatch.js`, #567). That arrives here as
|
|
45
|
+
// `presenting`, which folds into `visible` the way `minimized` does: a
|
|
46
|
+
// surface the compositor has stopped scheduling frames for is one nobody is
|
|
47
|
+
// looking at, and an animation paused on `visible` is right to stop. It
|
|
48
|
+
// costs a couple of seconds of silence to be sure, so it is a signal to stop
|
|
49
|
+
// work on, not a frame-accurate one — and it is `true` on every backend
|
|
50
|
+
// whose windows have no such signal, X11 and Cocoa among them.
|
|
38
51
|
|
|
39
52
|
import { useCallback, useSyncExternalStore } from 'react';
|
|
40
53
|
|
|
@@ -62,6 +75,7 @@ const UNKNOWN = Object.freeze({
|
|
|
62
75
|
focused: true,
|
|
63
76
|
visible: true,
|
|
64
77
|
obscured: false,
|
|
78
|
+
presenting: true,
|
|
65
79
|
minimized: false,
|
|
66
80
|
maximized: false,
|
|
67
81
|
fullscreen: false,
|
|
@@ -75,6 +89,7 @@ const SAME = (a, b) =>
|
|
|
75
89
|
a.focused === b.focused &&
|
|
76
90
|
a.visible === b.visible &&
|
|
77
91
|
a.obscured === b.obscured &&
|
|
92
|
+
a.presenting === b.presenting &&
|
|
78
93
|
a.minimized === b.minimized &&
|
|
79
94
|
a.maximized === b.maximized &&
|
|
80
95
|
a.fullscreen === b.fullscreen &&
|
|
@@ -119,7 +134,7 @@ class WindowStateSession {
|
|
|
119
134
|
});
|
|
120
135
|
const settled = Object.freeze({
|
|
121
136
|
...next,
|
|
122
|
-
visible: !next.minimized && !next.obscured,
|
|
137
|
+
visible: !next.minimized && !next.obscured && next.presenting,
|
|
123
138
|
});
|
|
124
139
|
if (SAME(settled, this.snapshot)) return;
|
|
125
140
|
this.snapshot = settled;
|
|
@@ -262,9 +277,33 @@ function arm(session) {
|
|
|
262
277
|
);
|
|
263
278
|
}
|
|
264
279
|
|
|
280
|
+
watchPresenting(session);
|
|
265
281
|
watchVisibility(session);
|
|
266
282
|
}
|
|
267
283
|
|
|
284
|
+
/**
|
|
285
|
+
* The Wayland backend's frame-loop liveness, where the window has it — the
|
|
286
|
+
* X11 and Cocoa windows do not, and the absence of the method is the answer
|
|
287
|
+
* (`presenting` stays true, as it does on a backend whose frames are paced
|
|
288
|
+
* by anything but the compositor's goodwill).
|
|
289
|
+
*
|
|
290
|
+
* Nothing is selected and nothing is asked: the window is already watching
|
|
291
|
+
* its own frame callbacks, so this is a listener on a signal that exists
|
|
292
|
+
* whether or not a component ever reads it.
|
|
293
|
+
*/
|
|
294
|
+
function watchPresenting(session) {
|
|
295
|
+
const wnd = session.node.window;
|
|
296
|
+
if (typeof wnd?.onPresentingChange !== 'function') return;
|
|
297
|
+
session._offs.push(
|
|
298
|
+
wnd.onPresentingChange((presenting) => {
|
|
299
|
+
if (!session.stopped) session.publish({ presenting });
|
|
300
|
+
}),
|
|
301
|
+
);
|
|
302
|
+
// Whatever it is now: a window can have parked before anything subscribed.
|
|
303
|
+
if (typeof wnd.presenting === 'boolean')
|
|
304
|
+
session.publish({ presenting: wnd.presenting });
|
|
305
|
+
}
|
|
306
|
+
|
|
268
307
|
function readDesktop(session) {
|
|
269
308
|
Promise.resolve(
|
|
270
309
|
session.node.window?.getProperty?.(DESKTOP_PROPERTY, { as: 'numbers' }),
|
|
@@ -370,6 +409,7 @@ export function endWindowState(node) {
|
|
|
370
409
|
* | `maximized` | both axes; one axis alone shows up in `states` |
|
|
371
410
|
* | `fullscreen` | what the WM actually did, not what `<window fullscreen>` asked for |
|
|
372
411
|
* | `obscured` | fully covered by other windows — **always false under a compositor** |
|
|
412
|
+
* | `presenting` | the display is still scheduling frames for this window — Wayland; always true elsewhere |
|
|
373
413
|
* | `states` | the raw `_NET_WM_STATE` names, e.g. `['maximized_vert', 'focused']` |
|
|
374
414
|
* | `desktop` | the workspace index, or null (a sticky window shows up in `states`) |
|
|
375
415
|
*
|