@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 +6 -1
- package/bin/desklink-host.mjs +9 -3
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +220 -0
- package/dist/doctor.js.map +1 -0
- package/dist/engineProcess.d.ts +5 -0
- package/dist/engineProcess.d.ts.map +1 -1
- package/dist/engineProcess.js +15 -5
- package/dist/engineProcess.js.map +1 -1
- package/docs/PROTOCOL.md +1 -1
- package/engine/Cargo.lock +1 -1
- package/engine/Cargo.toml +1 -1
- package/engine/native/mac_stream.mm +4 -1
- package/engine/src/diagnose.rs +99 -0
- package/engine/src/mac.rs +229 -6
- package/engine/src/main.rs +5 -0
- package/engine/src/session.rs +60 -22
- package/examples/reference-client.html +13 -0
- package/package.json +3 -3
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,
|
|
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
|
package/bin/desklink-host.mjs
CHANGED
|
@@ -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
|
|
6
|
-
* tell the user what is wrong before a desktop is opened rather
|
|
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) {
|
package/dist/doctor.d.ts
ADDED
|
@@ -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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"}
|
package/dist/engineProcess.d.ts
CHANGED
|
@@ -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":"AAIA,OAAO,EACH,aAAa,EAEb,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACtB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"engineProcess.d.ts","sourceRoot":"","sources":["../src/engineProcess.ts"],"names":[],"mappings":"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"}
|
package/dist/engineProcess.js
CHANGED
|
@@ -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 =
|
|
68
|
-
if (missing !==
|
|
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":"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"}
|
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 |
|
|
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
package/engine/Cargo.toml
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
684
|
-
output_path = args.next()
|
|
685
|
-
|
|
686
|
-
|
|
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
|
-
|
|
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
|
}
|
package/engine/src/main.rs
CHANGED
|
@@ -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
|
package/engine/src/session.rs
CHANGED
|
@@ -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
|
-
///
|
|
212
|
-
///
|
|
213
|
-
///
|
|
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
|
-
/// `
|
|
234
|
-
///
|
|
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
|
|
240
|
+
mut announced: Vec<crate::indicator::Cue>,
|
|
241
241
|
) {
|
|
242
|
-
|
|
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
|
|
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
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
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
|
|
378
|
-
|
|
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.
|
|
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.
|
|
57
|
-
"@desklink/host-darwin-arm64": "0.5.
|
|
56
|
+
"@desklink/host-linux-x64-gnu": "0.5.15",
|
|
57
|
+
"@desklink/host-darwin-arm64": "0.5.15"
|
|
58
58
|
}
|
|
59
59
|
}
|