@desklink/host 0.5.14 → 0.5.15

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 CHANGED
@@ -84,8 +84,12 @@ See the [changelog](https://github.com/umeranjum17/desklink/blob/main/CHANGELOG.
84
84
  npm install @desklink/host
85
85
  npx desklink-host path # the engine this install will run
86
86
  npx desklink-host capabilities # what this machine can do right now
87
+ npx desklink-host doctor # check every Linux requirement before a session
87
88
  ```
88
89
 
90
+ `doctor` prints one PASS/FAIL line per requirement with the exact free package
91
+ command for each failure, and exits nonzero when one is missing. It starts no session.
92
+
89
93
  On **Linux x64 with glibc 2.36 or newer** — Debian 12, Ubuntu 24.04, Fedora 37
90
94
  or later, Arch — that is the whole install. npm also installs the optional
91
95
  platform package `@desklink/host-linux-x64-gnu`, which carries the prebuilt
@@ -114,7 +118,8 @@ that asks), Quartz pointer/keyboard events, and
114
118
  plain-text NSPasteboard operations. `capabilities` is non-prompting; `session.open`
115
119
  requests Screen Recording and, for input, Accessibility consent when needed.
116
120
  For persistent grants, install the signed `DesklinkHost.app` at one fixed path.
117
- Build the engine on the Mac, then run
121
+ Build the engine on the Mac with `cargo build --release` (the packed release CLI, built with
122
+ `DESKLINK_MACOS_CLI`, has no bundle identity and the installer refuses it), then run
118
123
  `release/install-mac-app.sh <engine> <absolute path to DesklinkHost.app> [existing signing PEM]`
119
124
  from this package. It prefers a usable Developer ID Application or Apple
120
125
  Development identity in the login keychain; otherwise it imports the supplied
@@ -2,14 +2,16 @@
2
2
  /**
3
3
  * CLI for the desktop host engine package.
4
4
  *
5
- * `path` and `capabilities` work without starting a session, so a consumer can
6
- * tell the user what is wrong before a desktop is opened rather than after.
5
+ * `path`, `doctor` and `capabilities` work without starting a session, so a
6
+ * consumer can tell the user what is wrong before a desktop is opened rather
7
+ * than after.
7
8
  * Everything else is forwarded to the engine binary, so the CLI cannot drift
8
9
  * from the process protocol it documents.
9
10
  */
10
11
  import { spawn } from 'node:child_process';
11
12
  import { randomBytes } from 'node:crypto';
12
13
  import { Bridge } from '../dist/bridge.js';
14
+ import { runDoctor } from '../dist/doctor.js';
13
15
  import { EngineClient, windowsEngineStartupError } from '../dist/engineProcess.js';
14
16
  import { explainMissingEngine, resolveEngine } from '../dist/resolveEngine.js';
15
17
 
@@ -21,12 +23,13 @@ async function main() {
21
23
 
22
24
  USAGE:
23
25
  desklink-host path print the engine binary this package would run
26
+ desklink-host doctor check every Linux requirement and print the fix for each failure
24
27
  desklink-host capabilities print what this machine can do right now
25
28
  desklink-host bridge [--listen H:P] [--token T] [--source portal|x11|display] [--display :0] [--display-id ID] [--reattach-ms MS]
26
29
  re-serve the engine's protocol over a WebSocket and
27
30
  print the URL to open; no signaling of your own needed
28
31
  retain detached sessions for 30000 ms; --reattach-ms 0 closes immediately
29
- desklink-host <engine command> ... run the engine directly (serve, keep, capture-probe, setup-input, version)
32
+ desklink-host <engine command> ... run the engine directly (serve, keep, capture-probe, setup-input, diagnose, version)
30
33
 
31
34
  Set DESKLINK_ENGINE to use an engine built somewhere else (MUXR_DESKLINK_ENGINE still works as a deprecated fallback).`);
32
35
  return 0;
@@ -40,6 +43,9 @@ Set DESKLINK_ENGINE to use an engine built somewhere else (MUXR_DESKLINK_ENGINE
40
43
  console.log(resolved.command);
41
44
  return 0;
42
45
  }
46
+ if (command === 'doctor') {
47
+ return await runDoctor();
48
+ }
43
49
  if (command === 'bridge') {
44
50
  const resolved = resolveEngine();
45
51
  if (resolved === null) {
@@ -0,0 +1,2 @@
1
+ export declare function runDoctor(): Promise<number>;
2
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AA0LA,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAyEjD"}
package/dist/doctor.js ADDED
@@ -0,0 +1,220 @@
1
+ /**
2
+ * `desklink-host doctor`: one PASS/FAIL line per requirement a Linux session
3
+ * needs, and the free package command that fixes a failure.
4
+ *
5
+ * The engine answers the machine questions (`diagnose`); this file adds the
6
+ * package facts and the words a person can act on. It starts no session and
7
+ * opens no portal, so it is safe to run before choosing a capture source.
8
+ */
9
+ import { execFile } from 'node:child_process';
10
+ import { readFileSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { missingSystemLibrary } from './engineProcess.js';
13
+ import { enginePackageRoot, explainMissingEngine, resolveEngine } from './resolveEngine.js';
14
+ const ENGINE_FIX = 'Debian/Ubuntu: `npm install @desklink/host-linux-x64-gnu` (keep optional dependencies); Fedora: the same command.';
15
+ const NODE_FIX = 'Debian/Ubuntu: `curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt install -y nodejs`; Fedora: `sudo dnf install nodejs`.';
16
+ const X11_FIX = 'Debian/Ubuntu: `sudo apt install xserver-xorg-core`; Fedora: `sudo dnf install xorg-x11-server-Xorg` (run inside the logged-in desktop session).';
17
+ const WAYLAND_FIX = 'Debian/Ubuntu: `sudo apt install pipewire xdg-desktop-portal xdg-desktop-portal-gnome` (KDE: xdg-desktop-portal-kde); Fedora: `sudo dnf install pipewire xdg-desktop-portal xdg-desktop-portal-gnome`.';
18
+ const INPUT_FIX = 'Wayland Debian/Ubuntu: `sudo apt install xdg-desktop-portal xdg-desktop-portal-gnome`; Fedora: `sudo dnf install xdg-desktop-portal xdg-desktop-portal-gnome`; then run `desklink-host setup-input` once for /dev/uinput.';
19
+ const ENCODER_FIX = 'Debian/Ubuntu: `sudo apt install mesa-va-drivers intel-media-va-driver`; Fedora: `sudo dnf install mesa-va-drivers intel-media-driver` (the engine also fetches Cisco openh264 once on first use when online).';
20
+ const LIBRARY_FIX = 'Debian/Ubuntu: `sudo apt install libpipewire-0.3-0 libxkbcommon0 libevdev2 libstdc++6 libxcursor1 libx11-6 libxext6 libwayland-client0 libfontconfig1 libfreetype6`; Fedora: `sudo dnf install pipewire-libs libxkbcommon libevdev libstdc++ libXcursor libX11 libXext libwayland-client fontconfig freetype`. A complete desktop install usually has these already.';
21
+ const UPDATE_FIX = 'Debian/Ubuntu: `npm install @desklink/host@latest`; Fedora: the same command.';
22
+ const PROBE_FIX = `install the engine first — ${ENGINE_FIX}`;
23
+ function pass(name, detail) {
24
+ return { status: 'PASS', name, detail };
25
+ }
26
+ function na(name, detail) {
27
+ return { status: 'N/A', name, detail };
28
+ }
29
+ function fail(name, detail, fix) {
30
+ return { status: 'FAIL', name, detail, fix };
31
+ }
32
+ function firstLine(text) {
33
+ return text.split('\n').find((line) => line.trim() !== '')?.trim() ?? '';
34
+ }
35
+ function runEngine(command, args) {
36
+ return new Promise((done) => {
37
+ execFile(command, args, { timeout: 40_000, maxBuffer: 8 << 20, windowsHide: true }, (error, stdout, stderr) => {
38
+ const code = error === null ? 0 : typeof error.code === 'number' ? error.code : null;
39
+ done({ code, stdout: String(stdout), stderr: String(stderr) });
40
+ });
41
+ });
42
+ }
43
+ function readPackage() {
44
+ try {
45
+ return JSON.parse(readFileSync(join(enginePackageRoot(), 'package.json'), 'utf8'));
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ }
51
+ /** The package asks for a minimum Node version; only `>=` needs to be read. */
52
+ function nodeMeets(current, requirement) {
53
+ const have = current.split('.').map(Number);
54
+ for (const clause of requirement.trim().split(/\s+/)) {
55
+ const match = /^>=\s*v?(\d+)(?:\.(\d+))?(?:\.(\d+))?$/.exec(clause);
56
+ if (match === null)
57
+ return false;
58
+ const want = [Number(match[1]), Number(match[2] ?? 0), Number(match[3] ?? 0)];
59
+ for (let index = 0; index < 3; index++) {
60
+ const left = have[index] ?? 0;
61
+ const right = want[index] ?? 0;
62
+ if (left !== right) {
63
+ if (left < right)
64
+ return false;
65
+ break;
66
+ }
67
+ }
68
+ }
69
+ return true;
70
+ }
71
+ function librariesCheck(resolved, version) {
72
+ if (resolved === null)
73
+ return na('libraries', 'needs an engine binary; see the engine line');
74
+ const missing = missingSystemLibrary(version.stderr);
75
+ if (missing !== null)
76
+ return fail('libraries', `cannot load ${missing}`, LIBRARY_FIX);
77
+ if (version.code === 0)
78
+ return pass('libraries', "the engine starts with this machine's system libraries");
79
+ return fail('libraries', `the engine did not run: ${firstLine(version.stderr) || `exit ${version.code ?? 'unexpectedly'}`}`, UPDATE_FIX);
80
+ }
81
+ function x11Check(x11, session, probeError, probeFix) {
82
+ if (session === 'wayland')
83
+ return na('x11', 'Wayland session; the portal is the capture path');
84
+ if (session === 'none')
85
+ return fail('x11', 'no X11 or Wayland session (DISPLAY and WAYLAND_DISPLAY are unset)', X11_FIX);
86
+ if (x11 === undefined)
87
+ return fail('x11', `not checked: ${probeError ?? 'the engine reported no X11 result'}`, probeFix);
88
+ if (!x11.connected)
89
+ return fail('x11', `cannot open ${x11.display ?? process.env.DISPLAY ?? 'the display'}: ${x11.error ?? 'unknown error'}`, X11_FIX);
90
+ const missing = [!x11.shm && 'XShm', !x11.damage && 'XDamage'].filter((value) => value !== false);
91
+ const size = `${x11.width ?? '?'}x${x11.height ?? '?'}`;
92
+ if (missing.length > 0) {
93
+ return fail('x11', `${x11.display ?? 'the display'} ${size} cannot use ${missing.join(' or ')}`, X11_FIX);
94
+ }
95
+ return pass('x11', `${x11.display ?? 'the display'} ${size}, XShm + XDamage`);
96
+ }
97
+ function waylandCheck(wayland, session, probeError, probeFix) {
98
+ if (session !== 'wayland')
99
+ return na('wayland', session === 'x11' ? 'X11 session; no portal is needed' : 'no Wayland session');
100
+ if (wayland === undefined)
101
+ return fail('wayland', `not checked: ${probeError ?? 'the engine reported no Wayland result'}`, probeFix);
102
+ const missing = [];
103
+ if (!wayland.screencast)
104
+ missing.push(`xdg-desktop-portal ScreenCast (${wayland.screencast_error ?? 'not reachable'})`);
105
+ if (!wayland.pipewire)
106
+ missing.push('PipeWire socket');
107
+ if (missing.length > 0)
108
+ return fail('wayland', `missing ${missing.join(', ')}`, WAYLAND_FIX);
109
+ return pass('wayland', 'xdg-desktop-portal ScreenCast + PipeWire');
110
+ }
111
+ function inputCheck(report, session, probeError, probeFix) {
112
+ if (report === null)
113
+ return fail('input', `not checked: ${probeError ?? 'the engine did not answer'}`, probeFix);
114
+ if (session === 'x11') {
115
+ const x11 = report.x11;
116
+ if (x11?.connected !== true)
117
+ return fail('input', 'XTest cannot be checked without an X display', X11_FIX);
118
+ if (x11.xtest !== true)
119
+ return fail('input', `XTest is missing from ${x11.display ?? 'the display'}`, X11_FIX);
120
+ return pass('input', `XTest on ${x11.display ?? 'the display'}`);
121
+ }
122
+ if (session === 'wayland') {
123
+ const wayland = report.wayland;
124
+ const missing = [];
125
+ if (wayland?.remote_desktop !== true)
126
+ missing.push(`portal RemoteDesktop (${wayland?.remote_desktop_error ?? 'not reachable'})`);
127
+ if (report.uinput !== true)
128
+ missing.push('/dev/uinput is not writable');
129
+ if (missing.length > 0)
130
+ return fail('input', `missing ${missing.join(', ')}`, INPUT_FIX);
131
+ return pass('input', 'portal RemoteDesktop + /dev/uinput');
132
+ }
133
+ return fail('input', 'no X11 or Wayland session to inject into', X11_FIX);
134
+ }
135
+ function encoderCheck(report, probeError, probeFix) {
136
+ if (report === null)
137
+ return fail('encoder', `not checked: ${probeError ?? 'the engine did not answer'}`, probeFix);
138
+ if (report.encoder === null || report.encoder === undefined)
139
+ return fail('encoder', 'no working H.264 encoder', ENCODER_FIX);
140
+ return pass('encoder', `${report.encoder.name}${report.encoder.hardware ? ' (hardware)' : ''}; VP9 software is always available`);
141
+ }
142
+ function versionCheck(packageVersion, engineVersion, reason, fix) {
143
+ if (packageVersion === null)
144
+ return fail('versions', 'cannot read @desklink/host package.json', UPDATE_FIX);
145
+ if (engineVersion === null)
146
+ return fail('versions', `@desklink/host ${packageVersion}; engine version unavailable (${reason ?? 'no answer'})`, fix);
147
+ return pass('versions', `@desklink/host ${packageVersion} · engine ${engineVersion}`);
148
+ }
149
+ export async function runDoctor() {
150
+ // Linux first: the engine has no `diagnose` on other platforms yet, and a
151
+ // report built from failed probes there would describe the wrong machine.
152
+ if (process.platform !== 'linux') {
153
+ console.log(`FAIL platform desklink-host doctor checks Linux only; ${process.platform} was not checked`);
154
+ return 1;
155
+ }
156
+ const checks = [];
157
+ const packageFacts = readPackage();
158
+ const packageVersion = typeof packageFacts?.version === 'string' ? packageFacts.version : null;
159
+ const resolved = resolveEngine();
160
+ checks.push(resolved === null
161
+ ? fail('engine', explainMissingEngine() ?? 'the engine binary is not resolvable', ENGINE_FIX)
162
+ : pass('engine', `${resolved.command} (${resolved.origin})`));
163
+ const nodeVersion = process.versions.node;
164
+ const requirement = typeof packageFacts?.engines?.node === 'string' ? packageFacts.engines.node : null;
165
+ checks.push(requirement !== null && !nodeMeets(nodeVersion, requirement)
166
+ ? fail('node', `v${nodeVersion} does not meet the package requirement ${requirement}`, NODE_FIX)
167
+ : pass('node', `v${nodeVersion}${requirement === null ? '' : ` (package needs ${requirement})`}`));
168
+ let diagnose = null;
169
+ let engineVersion = null;
170
+ let probeError = null;
171
+ let versionResult = { code: null, stdout: '', stderr: '' };
172
+ if (resolved !== null) {
173
+ const [version, diagnoseResult] = await Promise.all([
174
+ runEngine(resolved.command, ['version']),
175
+ runEngine(resolved.command, ['diagnose']),
176
+ ]);
177
+ versionResult = version;
178
+ if (versionResult.code === 0)
179
+ engineVersion = versionResult.stdout.trim() || null;
180
+ if (diagnoseResult.code === 0) {
181
+ try {
182
+ diagnose = JSON.parse(diagnoseResult.stdout);
183
+ }
184
+ catch {
185
+ probeError = 'the engine returned unreadable diagnose output';
186
+ }
187
+ }
188
+ else {
189
+ probeError = firstLine(diagnoseResult.stderr) || `engine diagnose exited ${diagnoseResult.code ?? 'unexpectedly'}`;
190
+ }
191
+ if (engineVersion === null && typeof diagnose?.version === 'string')
192
+ engineVersion = diagnose.version;
193
+ }
194
+ checks.push(librariesCheck(resolved, versionResult));
195
+ const session = diagnose?.session
196
+ ?? (process.env.WAYLAND_DISPLAY !== undefined && process.env.WAYLAND_DISPLAY !== ''
197
+ ? 'wayland'
198
+ : process.env.DISPLAY !== undefined && process.env.DISPLAY !== ''
199
+ ? 'x11'
200
+ : 'none');
201
+ const missingLibrary = missingSystemLibrary(versionResult.stderr);
202
+ const probeFix = resolved === null ? PROBE_FIX : missingLibrary !== null ? LIBRARY_FIX : UPDATE_FIX;
203
+ checks.push(x11Check(diagnose?.x11 ?? undefined, session, probeError, probeFix));
204
+ checks.push(waylandCheck(diagnose?.wayland ?? undefined, session, probeError, probeFix));
205
+ checks.push(inputCheck(diagnose, session, probeError, probeFix));
206
+ checks.push(encoderCheck(diagnose, probeError, probeFix));
207
+ checks.push(versionCheck(packageVersion, engineVersion, resolved === null ? 'no engine binary' : probeError, probeFix));
208
+ for (const check of checks) {
209
+ console.log(`${check.status.padEnd(4)} ${check.name.padEnd(8)} ${check.detail}`);
210
+ if (check.fix !== undefined)
211
+ console.log(` fix ${check.fix}`);
212
+ }
213
+ const failed = checks.filter((check) => check.status === 'FAIL').length;
214
+ const passed = checks.filter((check) => check.status === 'PASS').length;
215
+ const skipped = checks.length - failed - passed;
216
+ console.log('');
217
+ console.log(`${checks.length} checks: ${passed} passed, ${failed} failed, ${skipped} not applicable`);
218
+ return failed === 0 ? 0 : 1;
219
+ }
220
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,9 @@
1
1
  import { EngineRefused, type EngineCapabilities, type EngineEvent, type OpenedSession, type PointRequest, type OpenSessionRequest, type SessionMetrics } from './protocol.js';
2
+ /**
3
+ * The library a Linux engine could not load, from the linker's own message, or
4
+ * null when the engine started or stopped for another reason.
5
+ */
6
+ export declare function missingSystemLibrary(stderr: string): string | null;
2
7
  export declare function windowsEngineStartupError(code: number | null, error?: Error): EngineRefused | null;
3
8
  export interface EngineClientOptions {
4
9
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"engineProcess.d.ts","sourceRoot":"","sources":["../src/engineProcess.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engineProcess.d.ts","sourceRoot":"","sources":["../src/engineProcess.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,19 @@ import { spawn, spawnSync } from 'node:child_process';
2
2
  import { appendFileSync } from 'node:fs';
3
3
  import { createInterface } from 'node:readline';
4
4
  import { EngineRefused, PROTOCOL_VERSION, } from './protocol.js';
5
+ /** The system libraries the prebuilt Linux engine loads at start. */
6
+ const LINUX_SYSTEM_LIBRARIES = [
7
+ 'libpipewire-0.3.so.0', 'libxkbcommon.so.0', 'libevdev.so.2', 'libstdc++.so.6',
8
+ 'libXcursor.so.1', 'libX11.so.6', 'libXext.so.6', 'libwayland-client.so.0', 'libfontconfig.so.1', 'libfreetype.so.6',
9
+ ];
10
+ /**
11
+ * The library a Linux engine could not load, from the linker's own message, or
12
+ * null when the engine started or stopped for another reason.
13
+ */
14
+ export function missingSystemLibrary(stderr) {
15
+ const missing = /error while loading shared libraries: ([^:\s]+): cannot open shared object file/.exec(stderr)?.[1];
16
+ return missing !== undefined && LINUX_SYSTEM_LIBRARIES.includes(missing) ? missing : null;
17
+ }
5
18
  export function windowsEngineStartupError(code, error) {
6
19
  if (process.platform !== 'win32')
7
20
  return null;
@@ -64,11 +77,8 @@ export class EngineClient {
64
77
  static async start(command, args, options = {}, env = process.env) {
65
78
  if (process.platform === 'linux' && args[0] === 'serve') {
66
79
  const probe = spawnSync(command, ['version'], { env, encoding: 'utf8', timeout: 3000 });
67
- const missing = /error while loading shared libraries: ([^:\s]+): cannot open shared object file/.exec(probe.stderr ?? '')?.[1];
68
- if (missing !== undefined && [
69
- 'libpipewire-0.3.so.0', 'libxkbcommon.so.0', 'libevdev.so.2', 'libstdc++.so.6',
70
- 'libXcursor.so.1', 'libX11.so.6', 'libXext.so.6', 'libwayland-client.so.0', 'libfontconfig.so.1', 'libfreetype.so.6',
71
- ].includes(missing)) {
80
+ const missing = missingSystemLibrary(probe.stderr ?? '');
81
+ if (missing !== null) {
72
82
  throw new EngineRefused('missing-system-library', `missing system library: ${missing}`);
73
83
  }
74
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"engineProcess.js","sourceRoot":"","sources":["../src/engineProcess.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engineProcess.js","sourceRoot":"","sources":["../src/engineProcess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAuC,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EACH,aAAa,EACb,gBAAgB,GAOnB,MAAM,eAAe,CAAC;AAEvB,qEAAqE;AACrE,MAAM,sBAAsB,GAAG;IAC3B,sBAAsB,EAAE,mBAAmB,EAAE,eAAe,EAAE,gBAAgB;IAC9E,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,kBAAkB;CACvH,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IAC/C,MAAM,OAAO,GAAG,iFAAiF,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACpH,OAAO,OAAO,KAAK,SAAS,IAAI,sBAAsB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,IAAmB,EAAE,KAAa;IACxE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;QAC/C,OAAO,IAAI,aAAa,CAAC,wBAAwB,EAAE,iJAAiJ,CAAC,CAAC;IAC1M,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,IAAI,aAAa,CAAC,qBAAqB,EAAE,+CAA+C,KAAK,CAAC,OAAO,iEAAiE,CAAC,CAAC;IACnL,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AA0BD;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IACJ,KAAK,CAAiC;IACtC,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;IACrC,KAAK,GAAkB,EAAE,CAAC;IACnC,MAAM,GAAG,CAAC,CAAC;IACX,MAAM,GAAG,KAAK,CAAC;IACf,QAAQ,GAAG,KAAK,CAAC;IACR,SAAS,CAAS;IAEnC,YAAoB,KAAqC,EAAE,OAA4B;QACnF,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,gBAAgB,IAAI,MAAM,CAAC;QAEpD,mEAAmE;QACnE,mEAAmE;QACnE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACvC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxB,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC5B,OAAO,CAAC,MAAM,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;YAC9F,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,QAAQ;gBAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,OAAO,CAAC,YAAY,EAAE,CAAC,yBAAyB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACjE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;gBAAE,OAAO;YACzC,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACvC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxB,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC5B,OAAO,CAAC,MAAM,CAAC,yBAAyB,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;YACpE,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAED,mEAAmE;IACnE,MAAM,CAAC,KAAK,CAAC,KAAK,CACd,OAAe,EACf,IAAc,EACd,UAA+B,EAAE,EACjC,MAAyB,OAAO,CAAC,GAAG;QAEpC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACxF,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YACzD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACnB,MAAM,IAAI,aAAa,CAAC,wBAAwB,EAAE,2BAA2B,OAAO,EAAE,CAAC,CAAC;YAC5F,CAAC;QACL,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAChG,IAAI,GAAG,CAAC,4BAA4B,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YAChD,IAAI,CAAC;gBAAC,cAAc,CAAC,GAAG,CAAC,4BAA4B,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YAAC,CAAC;YAC3E,OAAO,KAAK,EAAE,CAAC;gBAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAAC,MAAM,KAAK,CAAC;YAAC,CAAC;QACzD,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC;YACD,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,kEAAkE;YAClE,mDAAmD;YACnD,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC3C,MAAM,KAAK,CAAC;QAChB,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,UAAU,CAAC,IAAY,EAAE,OAA4B;QACzD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,KAAK,EAAE;YAAE,OAAO;QAC3B,IAAI,MAA+B,CAAC;QACpC,IAAI,CAAC;YACD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,CAAC,YAAY,EAAE,CAAC,wCAAwC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACxF,OAAO;QACX,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,MAAgC,CAAC;YAC/C,oEAAoE;YACpE,kEAAkE;YAClE,gEAAgE;YAChE,iDAAiD;YACjD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1D,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YACzB,OAAO;QACX,CAAC;QACD,MAAM,EAAE,GAAG,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACjE,IAAI,EAAE,KAAK,SAAS;YAAE,OAAO;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO;QAClC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAwD,CAAC;QAC9E,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,IAAI,QAAQ,EAAE,KAAK,CAAC,OAAO,IAAI,gCAAgC,CAAC,CAAC,CAAC;YAC7G,OAAO;QACX,CAAC;QACD,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAI,MAAc,EAAE,MAAgC,EAAE,SAAS,GAAG,IAAI,CAAC,SAAS;QACnF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAC7F,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,OAAmC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YACtF,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC1F,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBACxC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;gBACpC,CAAC;YACL,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED,YAAY;QACR,OAAO,IAAI,CAAC,OAAO,CAAqB,cAAc,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,OAA2B,EAAE,SAAkB;QACvD,OAAO,IAAI,CAAC,OAAO,CAAgB,cAAc,EAAE;YAC/C,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;YACnE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;YACnE,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC1E,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;YAC7E,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;YACnF,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;YACpE,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;YAChF,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;YACtF,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;YAChF,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,GAAG,CAAC,OAAO,CAAC,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpE,EAAE,SAAS,CAAC,CAAC;IAClB,CAAC;IAED,YAAY,CAAC,SAAiB,EAAE,UAAkB,EAAE,GAAW;QAC3D,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;YACvC,UAAU,EAAE,SAAS;YACrB,UAAU;YACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE;SACvC,CAAC,CAAC;IACP,CAAC;IAED,YAAY,CACR,SAAiB,EACjB,UAAkB,EAClB,SAAiB,EACjB,MAAqB,EACrB,aAA4B;QAE5B,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE;YACrC,UAAU,EAAE,SAAS;YACrB,UAAU;YACV,SAAS;YACT,OAAO,EAAE,MAAM;YACf,gBAAgB,EAAE,aAAa;SAClC,CAAC,CAAC;IACP,CAAC;IAED,OAAO;QACH,OAAO,IAAI,CAAC,OAAO,CAAiB,iBAAiB,CAAC,CAAC;IAC3D,CAAC;IAED,aAAa,CAAC,SAAiB;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,cAAc,CAAC,SAAiB,EAAE,IAAY;QAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,SAAiB,EAAE,OAAqB;QAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE;YACjC,UAAU,EAAE,SAAS;YACrB,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC3C,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC1B,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChE,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;aAChF,CAAC;SACL,CAAC,CAAC;IACP,CAAC;IAED,YAAY,CAAC,SAAiB;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,qDAAqD;IACrD,WAAW,CAAC,SAAkB;QAC1B,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAkB,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,IAAI,KAAK,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS;gBAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;gBAC1D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,QAAQ,CAAC;IACpB,CAAC;IAEO,mBAAmB,CAAC,KAA4B;QACpD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,IAAI,uBAAuB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACvF,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAED;;;;;;;;;OASG;IACK,OAAO,CAAC,MAAa;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACxB,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,IAAI;QACN,yEAAyE;QACzE,kDAAkD;QAClD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS;YAAE,OAAO;QACxD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,oEAAoE;YACpE,yDAAyD;YACzD,KAAK,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACrD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC3B,CAAC;QACD,uEAAuE;QACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAChC,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;gBAAE,OAAO,OAAO,EAAE,CAAC;YAC3E,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;YAC5D,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;gBACpB,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,OAAO,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;CACJ;AAED;;;;GAIG;AACH,SAAS,QAAQ,CAAC,MAAc,EAAE,MAA2C,EAAE,SAAiB;IAC5F,MAAM,OAAO,GAAG,qCAAqC,MAAM,OAAO,SAAS,IAAI,CAAC;IAChF,MAAM,MAAM,GAAG,MAAM,EAAE,MAAwC,CAAC;IAChE,IAAI,MAAM,KAAK,cAAc,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;QAClF,OAAO,IAAI,aAAa,CAAC,iBAAiB,EAAE,GAAG,OAAO,mDAAmD,CAAC,CAAC;IAC/G,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC"}
package/docs/PROTOCOL.md CHANGED
@@ -480,7 +480,7 @@ The session ended on the engine's side; there is nothing further to drain.
480
480
  | `code` | Meaning | A client should |
481
481
  |---|---|---|
482
482
  | `transport` | The path to the client's peer was lost (ICE `failed`, or the track refused a frame) | open a new session with fresh authority; the desktop is still available |
483
- | `lease` | The session's `ttl_seconds` ran out | end; the grant is spent |
483
+ | `lease` | The session's `ttl_seconds` ran out | open a new session with fresh authority at once; this grant is spent but the desktop is still available (`@desklink/react-native`'s hook does; a client that ignores the event just goes dead) |
484
484
  | `error` | The engine could not keep serving it, such as an encoder refusing a frame | end and report |
485
485
 
486
486
  A session the consumer closes or replaces (`session.close`, a new
package/engine/Cargo.lock CHANGED
@@ -536,7 +536,7 @@ checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
536
536
 
537
537
  [[package]]
538
538
  name = "desklink-host"
539
- version = "0.5.14"
539
+ version = "0.5.15"
540
540
  dependencies = [
541
541
  "anyhow",
542
542
  "ashpd",
package/engine/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "desklink-host"
3
- version = "0.5.14"
3
+ version = "0.5.15"
4
4
  edition = "2021"
5
5
  rust-version = "1.97.1"
6
6
  license = "Apache-2.0"
@@ -118,7 +118,10 @@ extern "C" void *dl_mac_stream_start(uint32_t display_id, size_t width, size_t h
118
118
  config.width = width;
119
119
  config.height = height;
120
120
  config.pixelFormat = kCVPixelFormatType_32BGRA;
121
- config.minimumFrameInterval = CMTimeMake(1, fps ? fps : 30);
121
+ // Asking for exactly 1/fps makes ScreenCaptureKit drop any refresh that lands a hair early and hold the rest to its
122
+ // own timer, a few ms late (a 60 Hz display delivered 52-58 fps). 90% of the interval lets every refresh through;
123
+ // the encoder cadence still caps the stream at `fps`.
124
+ config.minimumFrameInterval = CMTimeMake(9, (fps ? fps : 30) * 10);
122
125
  config.queueDepth = 3;
123
126
  config.showsCursor = YES;
124
127
  config.capturesAudio = NO;
@@ -0,0 +1,99 @@
1
+ //! `desklink-host diagnose`: the machine facts behind `desklink-host doctor`.
2
+ //!
3
+ //! Every check here is a question, not an action: the X server is connected to
4
+ //! and read, the portal's version properties are fetched, and an encoder codes
5
+ //! one blank 320x240 frame. Nothing opens a portal session, asks for consent,
6
+ //! captures a desktop or creates an input device. `doctor` in the Node CLI adds
7
+ //! the package facts and decides which answer a person needs to act on.
8
+
9
+ use anyhow::Result;
10
+ use serde_json::{json, Value};
11
+
12
+ pub async fn run() -> Result<()> {
13
+ let session = if std::env::var_os("WAYLAND_DISPLAY").is_some() {
14
+ "wayland"
15
+ } else if std::env::var_os("DISPLAY").is_some() {
16
+ "x11"
17
+ } else {
18
+ "none"
19
+ };
20
+ let x11 = if session == "x11" { probe_x11() } else { Value::Null };
21
+ let wayland = if session == "wayland" {
22
+ probe_wayland().await
23
+ } else {
24
+ Value::Null
25
+ };
26
+ // `prepare` rather than `probe`: on a machine with no hardware encoder the
27
+ // engine fetches Cisco's openh264 once at first need, so that is the answer
28
+ // a session would get. It is a bounded download, not a session or a prompt.
29
+ let encoder = crate::h264::prepare().map(|info| {
30
+ json!({ "name": info.encoder, "hardware": info.hardware })
31
+ });
32
+ println!(
33
+ "{}",
34
+ serde_json::to_string(&json!({
35
+ "version": env!("CARGO_PKG_VERSION"),
36
+ "session": session,
37
+ "x11": x11,
38
+ "wayland": wayland,
39
+ "encoder": encoder,
40
+ "uinput": crate::input::probe().is_ok(),
41
+ }))?
42
+ );
43
+ Ok(())
44
+ }
45
+
46
+ /// Connect exactly as the capture backend would, then report the two
47
+ /// extensions it wants and XTest for input.
48
+ fn probe_x11() -> Value {
49
+ match crate::x11::X11Desktop::connect(None) {
50
+ Ok(desktop) => json!({
51
+ "connected": true,
52
+ "display": std::env::var("DISPLAY").ok(),
53
+ "width": desktop.width,
54
+ "height": desktop.height,
55
+ "shm": desktop.capture_path() == "shm",
56
+ "damage": desktop.damage_armed(),
57
+ "xtest": desktop.input_available(),
58
+ }),
59
+ Err(error) => json!({ "connected": false, "error": format!("{error:#}") }),
60
+ }
61
+ }
62
+
63
+ /// Ask the session portal whether its ScreenCast and RemoteDesktop interfaces
64
+ /// are there. Building these proxies reads the interface's `version` property;
65
+ /// it creates no session and cannot prompt. The PipeWire socket is the capture
66
+ /// backend's own half of a screen share.
67
+ async fn probe_wayland() -> Value {
68
+ let screencast = ashpd::desktop::screencast::Screencast::new().await;
69
+ let remote_desktop = ashpd::desktop::remote_desktop::RemoteDesktop::new().await;
70
+ json!({
71
+ "screencast": screencast.is_ok(),
72
+ "screencast_error": screencast.err().map(|error| error.to_string()),
73
+ "remote_desktop": remote_desktop.is_ok(),
74
+ "remote_desktop_error": remote_desktop.err().map(|error| error.to_string()),
75
+ "pipewire": pipewire_socket(),
76
+ })
77
+ }
78
+
79
+ /// Whether the session PipeWire socket is present. A portal screencast hands
80
+ /// back a remote on this socket, so a portal without one cannot deliver frames.
81
+ fn pipewire_socket() -> bool {
82
+ let runtime = std::env::var_os("PIPEWIRE_RUNTIME_DIR")
83
+ .filter(|path| !path.is_empty())
84
+ .or_else(|| std::env::var_os("XDG_RUNTIME_DIR"))
85
+ .map(std::path::PathBuf::from);
86
+ let Some(directory) = runtime else {
87
+ return false;
88
+ };
89
+ let remote = std::env::var("PIPEWIRE_REMOTE")
90
+ .ok()
91
+ .filter(|remote| !remote.is_empty())
92
+ .unwrap_or_else(|| String::from("pipewire-0"));
93
+ let remote = std::path::Path::new(&remote);
94
+ if remote.is_absolute() {
95
+ remote.exists()
96
+ } else {
97
+ directory.join(remote).exists()
98
+ }
99
+ }
package/engine/src/mac.rs CHANGED
@@ -592,6 +592,152 @@ fn capture_probe(seconds: u64) -> Result<Value, String> {
592
592
  )
593
593
  }
594
594
 
595
+ /// One real ScreenCaptureKit screenshot of a screen-point rectangle, converted
596
+ /// to packed BGRA with its row stride. `capture-probe --frame/--record` uses it
597
+ /// to keep a real desktop view for proof; it is not a render.
598
+ fn capture_rect_bgra(area: CGRect) -> Result<(Vec<u8>, usize, usize, usize), String> {
599
+ use block2::RcBlock;
600
+ use objc2_core_foundation::{
601
+ CGPoint as NativePoint, CGRect as NativeRect, CGSize as NativeSize,
602
+ };
603
+ use objc2_screen_capture_kit::SCScreenshotManager;
604
+
605
+ let rect = NativeRect {
606
+ origin: NativePoint {
607
+ x: area.origin.x,
608
+ y: area.origin.y,
609
+ },
610
+ size: NativeSize {
611
+ width: area.size.width,
612
+ height: area.size.height,
613
+ },
614
+ };
615
+ let ready = Arc::new((
616
+ Mutex::new(None::<Result<(Vec<u8>, usize, usize, usize), String>>),
617
+ Condvar::new(),
618
+ ));
619
+ let callback_state = ready.clone();
620
+ let callback = RcBlock::new(
621
+ move |image: *mut objc2_core_graphics::CGImage, error: *mut objc2_foundation::NSError| {
622
+ let frame = if !error.is_null() || image.is_null() {
623
+ Err(String::from(
624
+ "ScreenCaptureKit returned an error or no image",
625
+ ))
626
+ } else {
627
+ let image = unsafe { &*image };
628
+ let width = objc2_core_graphics::CGImage::width(Some(image));
629
+ let height = objc2_core_graphics::CGImage::height(Some(image));
630
+ let mut length = 0usize;
631
+ let mut stride = 0usize;
632
+ let pointer = unsafe {
633
+ desklink_image_bgra(
634
+ image as *const _ as *const c_void,
635
+ &mut length,
636
+ &mut stride,
637
+ )
638
+ };
639
+ if pointer.is_null() || width == 0 || height == 0 {
640
+ Err(String::from(
641
+ "ScreenCaptureKit image could not be converted to BGRA",
642
+ ))
643
+ } else {
644
+ let pixels = unsafe { std::slice::from_raw_parts(pointer, length) }.to_vec();
645
+ unsafe { libc::free(pointer.cast()) };
646
+ Ok((pixels, width, height, stride))
647
+ }
648
+ };
649
+ let (lock, wake) = &*callback_state;
650
+ if let Ok(mut result) = lock.lock() {
651
+ *result = Some(frame);
652
+ wake.notify_one();
653
+ }
654
+ },
655
+ );
656
+ unsafe {
657
+ SCScreenshotManager::captureImageInRect_completionHandler(rect, Some(&callback));
658
+ }
659
+ let deadline = Instant::now() + Duration::from_secs(5);
660
+ let (lock, wake) = &*ready;
661
+ let mut result = lock
662
+ .lock()
663
+ .map_err(|_| String::from("capture lock poisoned"))?;
664
+ while result.is_none() && Instant::now() < deadline {
665
+ let (next, _) = wake
666
+ .wait_timeout(result, deadline.saturating_duration_since(Instant::now()))
667
+ .map_err(|_| String::from("capture wait failed"))?;
668
+ result = next;
669
+ }
670
+ result
671
+ .take()
672
+ .unwrap_or_else(|| Err(String::from("ScreenCaptureKit timed out")))
673
+ }
674
+
675
+ /// Write one real desktop frame, or a short real desktop sequence, to raw BGRA
676
+ /// files. The proof harness turns these into stills and recordings; no pixels
677
+ /// are ever rendered by the engine itself.
678
+ fn capture_rects(
679
+ seconds: u64,
680
+ frame_path: Option<String>,
681
+ record_dir: Option<String>,
682
+ fps: u64,
683
+ area: Option<CGRect>,
684
+ ) -> Result<Value, String> {
685
+ let area = area.unwrap_or_else(|| unsafe { CGDisplayBounds(CGMainDisplayID()) });
686
+ let rect = serde_json::json!({
687
+ "x": area.origin.x, "y": area.origin.y,
688
+ "width": area.size.width, "height": area.size.height
689
+ });
690
+ let mut written = Vec::new();
691
+ let mut dimensions = None;
692
+ if let Some(path) = frame_path {
693
+ let (pixels, width, height, stride) = capture_rect_bgra(area)?;
694
+ std::fs::write(&path, &pixels)
695
+ .map_err(|error| format!("could not write {path}: {error}"))?;
696
+ dimensions = Some((width, height));
697
+ written.push(serde_json::json!({
698
+ "kind": "frame", "path": path, "width": width, "height": height,
699
+ "stride": stride, "format": "bgra"
700
+ }));
701
+ }
702
+ if let Some(dir) = record_dir {
703
+ std::fs::create_dir_all(&dir)
704
+ .map_err(|error| format!("could not create {dir}: {error}"))?;
705
+ let fps = fps.clamp(1, 30);
706
+ let count = seconds.saturating_mul(fps).max(1);
707
+ for index in 0..count {
708
+ let (pixels, width, height, stride) = capture_rect_bgra(area)?;
709
+ dimensions = Some((width, height));
710
+ let path = std::path::Path::new(&dir).join(format!("frame-{index:04}.bgra"));
711
+ std::fs::write(&path, &pixels)
712
+ .map_err(|error| format!("could not write {}: {error}", path.display()))?;
713
+ if index == 0 {
714
+ written.push(serde_json::json!({
715
+ "kind": "record", "dir": dir, "width": width, "height": height,
716
+ "stride": stride, "format": "bgra", "fps": fps, "frames": count
717
+ }));
718
+ }
719
+ std::thread::sleep(Duration::from_millis(1000 / fps));
720
+ }
721
+ let manifest = serde_json::json!({
722
+ "format": "bgra", "fps": fps, "frames": count,
723
+ "width": dimensions.map(|d| d.0), "height": dimensions.map(|d| d.1),
724
+ "rect": rect
725
+ });
726
+ std::fs::write(
727
+ std::path::Path::new(&dir).join("manifest.json"),
728
+ serde_json::to_vec_pretty(&manifest).unwrap(),
729
+ )
730
+ .map_err(|error| format!("could not write manifest: {error}"))?;
731
+ }
732
+ Ok(serde_json::json!({
733
+ "source": {
734
+ "kind": "screencapturekit", "rect": rect.clone(),
735
+ "width": dimensions.map(|d| d.0), "height": dimensions.map(|d| d.1)
736
+ },
737
+ "written": written
738
+ }))
739
+ }
740
+
595
741
  pub fn run() -> i32 {
596
742
  let mut args = std::env::args().skip(1);
597
743
  let command = args.next().unwrap_or_else(|| "help".into());
@@ -600,6 +746,7 @@ pub fn run() -> i32 {
600
746
  "serve"
601
747
  | "capabilities"
602
748
  | "capture-probe"
749
+ | "warp-pointer"
603
750
  | "indicator-demo"
604
751
  | "axi-record"
605
752
  | "setup-input"
@@ -668,6 +815,46 @@ pub fn run() -> i32 {
668
815
  let Some(path) = args.next() else { eprintln!("axi-record requires an output path"); return 2; };
669
816
  if let Err(error) = record_agent_overlay(&path) { eprintln!("axi-record: {error}"); return 1; }
670
817
  }
818
+ "warp-pointer" => {
819
+ let x = args.next().and_then(|value| value.parse::<i64>().ok());
820
+ let y = args.next().and_then(|value| value.parse::<i64>().ok());
821
+ let display = args
822
+ .next()
823
+ .and_then(|value| value.parse::<u32>().ok())
824
+ .unwrap_or_else(|| unsafe { CGMainDisplayID() });
825
+ let (Some(x), Some(y)) = (x, y) else {
826
+ eprintln!("usage: desklink-host warp-pointer <source x> <source y> [display]");
827
+ return 2;
828
+ };
829
+ let mode = unsafe { CGDisplayCopyDisplayMode(display) };
830
+ let (width, height) = if mode.is_null() {
831
+ (
832
+ unsafe { CGDisplayPixelsWide(display) },
833
+ unsafe { CGDisplayPixelsHigh(display) },
834
+ )
835
+ } else {
836
+ let pixels = unsafe {
837
+ (
838
+ CGDisplayModeGetPixelWidth(mode),
839
+ CGDisplayModeGetPixelHeight(mode),
840
+ )
841
+ };
842
+ unsafe { CGDisplayModeRelease(mode) };
843
+ pixels
844
+ };
845
+ let (width, height) = (width as i32, height as i32);
846
+ match crate::input::InputDevices::create_for_display(width, height, display) {
847
+ Ok(mut devices) => {
848
+ devices.move_absolute(x, y);
849
+ std::thread::sleep(Duration::from_millis(200));
850
+ println!("{}", json!({"warped": true, "x": x, "y": y, "display": display}));
851
+ }
852
+ Err(error) => {
853
+ eprintln!("warp-pointer: {error}");
854
+ return 1;
855
+ }
856
+ }
857
+ }
671
858
  #[cfg(all(desklink_vpx, not(desklink_macos_cli)))]
672
859
  "indicator-demo" => {
673
860
  let display = args.next().and_then(|value| value.parse().ok()).unwrap_or(0);
@@ -679,15 +866,51 @@ pub fn run() -> i32 {
679
866
  "capture-probe" => {
680
867
  let mut seconds = 3;
681
868
  let mut output_path = None;
869
+ let mut frame_path = None;
870
+ let mut record_dir = None;
871
+ let mut fps = 10;
872
+ let mut area = None;
682
873
  while let Some(argument) = args.next() {
683
- if argument == "--out" {
684
- output_path = args.next();
685
- } else if let Ok(value) = argument.parse() {
686
- seconds = value;
874
+ match argument.as_str() {
875
+ "--out" => output_path = args.next(),
876
+ "--frame" => frame_path = args.next(),
877
+ "--record" => record_dir = args.next(),
878
+ "--fps" => {
879
+ fps = args.next().and_then(|value| value.parse().ok()).unwrap_or(10);
880
+ }
881
+ "--rect" => {
882
+ let parts: Vec<f64> = args
883
+ .next()
884
+ .unwrap_or_default()
885
+ .split(',')
886
+ .filter_map(|value| value.trim().parse().ok())
887
+ .collect();
888
+ if parts.len() == 4 {
889
+ area = Some(CGRect {
890
+ origin: CGPoint {
891
+ x: parts[0],
892
+ y: parts[1],
893
+ },
894
+ size: CGSize {
895
+ width: parts[2],
896
+ height: parts[3],
897
+ },
898
+ });
899
+ }
900
+ }
901
+ other => {
902
+ if let Ok(value) = other.parse() {
903
+ seconds = value;
904
+ }
905
+ }
687
906
  }
688
907
  }
689
908
  let result = if unsafe { CGPreflightScreenCaptureAccess() } {
690
- capture_probe(seconds)
909
+ if frame_path.is_some() || record_dir.is_some() {
910
+ capture_rects(seconds, frame_path, record_dir, fps, area)
911
+ } else {
912
+ capture_probe(seconds)
913
+ }
691
914
  } else {
692
915
  request_screen_capture_content().and_then(|_| Err(format!("capture-permission: allow {} in System Settings › Privacy & Security › Screen & System Audio Recording, then reconnect", tcc_responsible_app_name())))
693
916
  };
@@ -722,7 +945,7 @@ pub fn run() -> i32 {
722
945
  println!("If the Input Monitoring alert did not open, allow {} in System Settings › Privacy & Security › Input Monitoring.", tcc_responsible_app_name());
723
946
  }
724
947
  }
725
- _ => println!("desklink-host {}\nUSAGE: desklink-host [serve|capabilities|capture-probe|encode-probe|setup-input|version]", env!("CARGO_PKG_VERSION")),
948
+ _ => println!("desklink-host {}\nUSAGE: desklink-host [serve|capabilities|capture-probe|warp-pointer|encode-probe|setup-input|version]", env!("CARGO_PKG_VERSION")),
726
949
  }
727
950
  0
728
951
  }
@@ -26,6 +26,8 @@ mod clipboard;
26
26
  mod clipboard;
27
27
  #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
28
28
  mod convert;
29
+ #[cfg(target_os = "linux")]
30
+ mod diagnose;
29
31
  #[cfg(any(target_os = "linux", all(target_os = "macos", desklink_vpx)))]
30
32
  mod cursor;
31
33
  #[cfg(target_os = "linux")]
@@ -245,6 +247,8 @@ fn main() {
245
247
  );
246
248
  0
247
249
  }
250
+ #[cfg(target_os = "linux")]
251
+ "diagnose" => report(runtime.block_on(diagnose::run())),
248
252
  "serve" => report(runtime.block_on(serve())),
249
253
  "keep" => keeper::command(&args[1..]),
250
254
  "capture-probe" => report(runtime.block_on(probe(
@@ -293,6 +297,7 @@ USAGE:
293
297
  keep one private X screen: kiosk geometry, focus,
294
298
  and a JSON-lines window report on stdout
295
299
  desklink-host capabilities print what this machine can do right now
300
+ desklink-host diagnose print the non-prompting checks behind `desklink-host doctor`
296
301
  desklink-host capture-probe [seconds] [display]
297
302
  capture frames and report the stream; with a
298
303
  display argument it reads that X display's root
@@ -208,9 +208,9 @@ unsafe extern "C" {
208
208
  }
209
209
 
210
210
  /// The X11 agent cue is a real window, so root grabs contain it. Restore
211
- /// exactly the pixels the announced cues cover (one pixel wider for edge
212
- /// rounding) from the last clean frame; everything else, including what lies
213
- /// inside the halo, stays live.
211
+ /// the pixels the announced cues cover (with a small margin for edge rounding)
212
+ /// from the last clean frame; everything else, including what lies inside the
213
+ /// halo, stays live.
214
214
  #[cfg(target_os = "linux")]
215
215
  struct CueMask {
216
216
  cues: crate::indicator::Cues,
@@ -230,18 +230,18 @@ impl CueMask {
230
230
  .unwrap_or_default()
231
231
  }
232
232
 
233
- /// `before` is the snapshot taken when the grab started: with the states
234
- /// announced by the time it returned, it covers whatever the grab saw.
233
+ /// `announced` is the snapshot taken after the grab: the helper announces
234
+ /// every state before drawing it, so this covers whatever the grab saw.
235
235
  fn apply(
236
236
  &mut self,
237
237
  raw: &mut [u8],
238
238
  width: usize,
239
239
  height: usize,
240
- mut cues: Vec<crate::indicator::Cue>,
240
+ mut announced: Vec<crate::indicator::Cue>,
241
241
  ) {
242
- cues.extend(self.snapshot());
242
+ announced.extend(self.snapshot());
243
243
  if let Some(clean) = self.clean.as_ref().filter(|clean| clean.len() == raw.len()) {
244
- for cue in cues {
244
+ for cue in &announced {
245
245
  let side = cue.size as usize + 2;
246
246
  let mut covered = vec![false; side * side];
247
247
  for row in 0..cue.size as usize {
@@ -260,16 +260,26 @@ impl CueMask {
260
260
  } != 0;
261
261
  }
262
262
  }
263
- for row in 0..side {
264
- for col in 0..side {
265
- let near =
266
- |r: usize, c: usize| r < side && c < side && covered[r * side + c];
267
- if !(near(row, col)
268
- || near(row.wrapping_sub(1), col)
269
- || near(row + 1, col)
270
- || near(row, col.wrapping_sub(1))
271
- || near(row, col + 1))
272
- {
263
+ // Restore the cue's pixels and one pixel around them. The
264
+ // shaped window's edge rounds differently from the coverage
265
+ // test; the margin keeps its anti-aliased edge out of the
266
+ // picture without covering live pixels inside the halo.
267
+ let margin = 1isize;
268
+ for row in -margin..side as isize + margin {
269
+ for col in -margin..side as isize + margin {
270
+ let near = |r: isize, c: isize| {
271
+ (-margin..=margin).any(|dr| {
272
+ (-margin..=margin).any(|dc| {
273
+ let (rr, cc) = (r + dr, c + dc);
274
+ rr >= 0
275
+ && cc >= 0
276
+ && rr < side as isize
277
+ && cc < side as isize
278
+ && covered[rr as usize * side + cc as usize]
279
+ })
280
+ })
281
+ };
282
+ if !near(row, col) {
273
283
  continue;
274
284
  }
275
285
  let (x, y) = (cue.x - 1 + col as i64, cue.y - 1 + row as i64);
@@ -282,7 +292,29 @@ impl CueMask {
282
292
  }
283
293
  }
284
294
  }
285
- self.clean = Some(raw.to_vec());
295
+ // Keep the pre-cue baseline inside each cue's bounding box. Restoring
296
+ // only the announced shape can leave an anti-aliased edge pixel in the
297
+ // frame; if that pixel became the baseline, every later cue over it
298
+ // would restore the old cue instead of the desktop. Outside the boxes
299
+ // the grab is live and becomes the next baseline.
300
+ self.clean = Some(match self.clean.take() {
301
+ Some(old) if old.len() == raw.len() && !announced.is_empty() => {
302
+ let mut next = raw.to_vec();
303
+ for cue in &announced {
304
+ let x0 = (cue.x - 4).max(0) as usize;
305
+ let y0 = (cue.y - 4).max(0) as usize;
306
+ let x1 = ((cue.x + cue.size + 4).max(0) as usize).min(width);
307
+ let y1 = ((cue.y + cue.size + 4).max(0) as usize).min(height);
308
+ for y in y0..y1 {
309
+ let start = (y * width + x0) * 4;
310
+ let end = (y * width + x1) * 4;
311
+ next[start..end].copy_from_slice(&old[start..end]);
312
+ }
313
+ }
314
+ next
315
+ }
316
+ _ => raw.to_vec(),
317
+ });
286
318
  }
287
319
  }
288
320
 
@@ -371,11 +403,17 @@ fn select_x11(
371
403
  let grabbed = Instant::now();
372
404
  #[cfg(target_os = "linux")]
373
405
  let frame = {
374
- let before = mask.as_ref().map(CueMask::snapshot);
375
406
  let mut desktop = lock(&desktop);
376
407
  desktop.capture_raw().and_then(|mut raw| {
377
- if let (Some(mask), Some(before)) = (mask.as_mut(), before) {
378
- mask.apply(&mut raw, width as usize, height as usize, before);
408
+ if let Some(mask) = mask.as_mut() {
409
+ // The helper announces each cue before it draws
410
+ // it, so reading the feed after the grab covers
411
+ // every state the grab could have seen. Reading
412
+ // it before the grab would miss a cue drawn
413
+ // during the grab and bake it into the clean
414
+ // baseline.
415
+ let after = mask.snapshot();
416
+ mask.apply(&mut raw, width as usize, height as usize, after);
379
417
  }
380
418
  Ok((desktop.convert(&raw, max_width, max_height)?, raw))
381
419
  })
@@ -223,13 +223,26 @@ const named = {
223
223
  Delete: 'Delete', Home: 'Home', End: 'End', PageUp: 'PageUp', PageDown: 'PageDown',
224
224
  Control: 'Control', Shift: 'Shift', Alt: 'Alt', Meta: 'Meta',
225
225
  };
226
+ // A shortcut (Control or Meta plus one character) is a key with its modifiers,
227
+ // not text: typed text is applied without them, so select-all, copy and paste
228
+ // would otherwise arrive as plain letters.
229
+ function chord(event, down) {
230
+ if (composing || !(event.ctrlKey || event.metaKey) || event.key.length !== 1) return false;
231
+ event.preventDefault();
232
+ const modifiers = [['ctrlKey', 'Control'], ['altKey', 'Alt'], ['shiftKey', 'Shift'], ['metaKey', 'Meta']]
233
+ .filter(([flag]) => event[flag]).map(([, name]) => name);
234
+ control({ kind: 'key', character: event.key, down, modifiers });
235
+ return true;
236
+ }
226
237
  keyboard.addEventListener('keydown', (event) => {
238
+ if (chord(event, true)) return;
227
239
  const name = named[event.key];
228
240
  if (composing || name === undefined) return;
229
241
  event.preventDefault();
230
242
  control({ kind: 'key', name, down: true });
231
243
  });
232
244
  keyboard.addEventListener('keyup', (event) => {
245
+ if (chord(event, false)) return;
233
246
  const name = named[event.key];
234
247
  if (composing || name === undefined) return;
235
248
  event.preventDefault();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@desklink/host",
3
- "version": "0.5.14",
3
+ "version": "0.5.15",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -53,7 +53,7 @@
53
53
  "desklink"
54
54
  ],
55
55
  "optionalDependencies": {
56
- "@desklink/host-linux-x64-gnu": "0.5.14",
57
- "@desklink/host-darwin-arm64": "0.5.14"
56
+ "@desklink/host-linux-x64-gnu": "0.5.15",
57
+ "@desklink/host-darwin-arm64": "0.5.15"
58
58
  }
59
59
  }