@domicile-desktop/sdk 0.0.0-alpha-e040773499e5 → 0.0.0-alpha-019dff1d8582
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 +1 -1
- package/dist/portal.d.ts +109 -3
- package/dist/portal.js +130 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ See [docs/ELEMENTS.md](docs/ELEMENTS.md) for `<app>` input and focus, and the
|
|
|
57
57
|
| `./bind-keys` | `bindKeys`: grab a shell's own chords by name and handle them by mode. `./key-action` and `./own-keybindings` are its parts. |
|
|
58
58
|
| `./fake-host` | `FakeDomicileHost`: a desktop for a shell's tests. |
|
|
59
59
|
| `./system` | `system(domicile)`: files, watches, processes and D-Bus. Calls resolve a `Result`; the compositor refuses most while the desktop is locked. See [SHELL-SYSTEM-ACCESS.md](/docs/SHELL-SYSTEM-ACCESS.md). |
|
|
60
|
-
| `./portal` | `watchPortalRequests` and `answerPortalRequest`: application dialogs from `xdg-desktop-portal`, parsed by kind. `<PortalDialogs />` in component-library draws them. See [PORTALS.md](/docs/architecture/PORTALS.md). |
|
|
60
|
+
| `./portal` | `watchPortalRequests` and `answerPortalRequest`: application dialogs from `xdg-desktop-portal`, parsed by kind. `watchCapturing` and `stopCapturing`: running sessions that control or capture input. `<PortalDialogs />` in component-library draws them. See [PORTALS.md](/docs/architecture/PORTALS.md). |
|
|
61
61
|
| `./extension`, `./tray`, `./notification`, `./theme`, `./file-preview`, `./display-transform` | Data types and Zod schemas for what the desktop holds. |
|
|
62
62
|
|
|
63
63
|
Internal, not needed by shells: `./cursor-shape`.
|
package/dist/portal.d.ts
CHANGED
|
@@ -11,8 +11,12 @@ export declare enum PortalKind {
|
|
|
11
11
|
* lets go. Not a question: the compositor refuses answers to it.
|
|
12
12
|
*/
|
|
13
13
|
Inhibit = 3,
|
|
14
|
+
/** Which input devices, and the clipboard, an application may control. */
|
|
15
|
+
RemoteDesktop = 4,
|
|
16
|
+
/** Whether an application may take input that crosses a screen edge. */
|
|
17
|
+
InputCapture = 5,
|
|
14
18
|
/** A kind this SDK cannot parse. Answer it with {@link PortalAnswer.Refused}. */
|
|
15
|
-
Unknown =
|
|
19
|
+
Unknown = 6
|
|
16
20
|
}
|
|
17
21
|
/** What every request carries. */
|
|
18
22
|
export type PortalRequestBase = {
|
|
@@ -115,6 +119,21 @@ export type InhibitBody = {
|
|
|
115
119
|
what: readonly Inhibited[];
|
|
116
120
|
reason: string | undefined;
|
|
117
121
|
};
|
|
122
|
+
/** Input devices a session asks for or holds. */
|
|
123
|
+
export type Devices = {
|
|
124
|
+
keyboard: boolean;
|
|
125
|
+
pointer: boolean;
|
|
126
|
+
touchscreen: boolean;
|
|
127
|
+
};
|
|
128
|
+
/** What a remote desktop session asks to control. */
|
|
129
|
+
export type RemoteDesktopBody = {
|
|
130
|
+
devices: Devices;
|
|
131
|
+
clipboard: boolean;
|
|
132
|
+
};
|
|
133
|
+
/** What an input capture session asks to take. */
|
|
134
|
+
export type InputCaptureBody = {
|
|
135
|
+
devices: Devices;
|
|
136
|
+
};
|
|
118
137
|
export declare const PortalRequest: {
|
|
119
138
|
Access: (base: PortalRequestBase, body: AccessBody) => {
|
|
120
139
|
/** The id {@link answerPortalRequest} takes. */
|
|
@@ -156,6 +175,26 @@ export declare const PortalRequest: {
|
|
|
156
175
|
body: InhibitBody;
|
|
157
176
|
kind: PortalKind.Inhibit;
|
|
158
177
|
};
|
|
178
|
+
InputCapture: (base: PortalRequestBase, body: InputCaptureBody) => {
|
|
179
|
+
/** The id {@link answerPortalRequest} takes. */
|
|
180
|
+
id: number;
|
|
181
|
+
/** The asking application's desktop file id. Empty when unknown. */
|
|
182
|
+
appId: string;
|
|
183
|
+
/** The `<app>` to show the dialog over, or the focused screen when absent. */
|
|
184
|
+
parentAppId: string | undefined;
|
|
185
|
+
body: InputCaptureBody;
|
|
186
|
+
kind: PortalKind.InputCapture;
|
|
187
|
+
};
|
|
188
|
+
RemoteDesktop: (base: PortalRequestBase, body: RemoteDesktopBody) => {
|
|
189
|
+
/** The id {@link answerPortalRequest} takes. */
|
|
190
|
+
id: number;
|
|
191
|
+
/** The asking application's desktop file id. Empty when unknown. */
|
|
192
|
+
appId: string;
|
|
193
|
+
/** The `<app>` to show the dialog over, or the focused screen when absent. */
|
|
194
|
+
parentAppId: string | undefined;
|
|
195
|
+
body: RemoteDesktopBody;
|
|
196
|
+
kind: PortalKind.RemoteDesktop;
|
|
197
|
+
};
|
|
159
198
|
Unknown: (base: PortalRequestBase, wireKind: string) => {
|
|
160
199
|
/** The id {@link answerPortalRequest} takes. */
|
|
161
200
|
id: number;
|
|
@@ -175,10 +214,16 @@ export declare enum PortalAnswerKind {
|
|
|
175
214
|
AppChooser = 1,
|
|
176
215
|
/** The user chose in a {@link PortalKind.FileChooser}. */
|
|
177
216
|
FileChooser = 2,
|
|
217
|
+
/** The user granted a {@link PortalKind.RemoteDesktop} no more than it asked. */
|
|
218
|
+
RemoteDesktop = 3,
|
|
219
|
+
/** The user allowed a {@link PortalKind.InputCapture} request. */
|
|
220
|
+
InputCapture = 4,
|
|
221
|
+
/** The user stopped a {@link Capturing} session. */
|
|
222
|
+
Stop = 5,
|
|
178
223
|
/** The user dismissed or denied the dialog. */
|
|
179
|
-
Canceled =
|
|
224
|
+
Canceled = 6,
|
|
180
225
|
/** The shell has no dialog for this kind. */
|
|
181
|
-
Refused =
|
|
226
|
+
Refused = 7
|
|
182
227
|
}
|
|
183
228
|
export declare const PortalAnswer: {
|
|
184
229
|
Access: () => {
|
|
@@ -196,11 +241,65 @@ export declare const PortalAnswer: {
|
|
|
196
241
|
chosen: FileChosen;
|
|
197
242
|
kind: PortalAnswerKind.FileChooser;
|
|
198
243
|
};
|
|
244
|
+
InputCapture: () => {
|
|
245
|
+
kind: PortalAnswerKind.InputCapture;
|
|
246
|
+
};
|
|
199
247
|
Refused: () => {
|
|
200
248
|
kind: PortalAnswerKind.Refused;
|
|
201
249
|
};
|
|
250
|
+
RemoteDesktop: (devices: Devices, clipboard: boolean) => {
|
|
251
|
+
clipboard: boolean;
|
|
252
|
+
devices: Devices;
|
|
253
|
+
kind: PortalAnswerKind.RemoteDesktop;
|
|
254
|
+
};
|
|
255
|
+
Stop: () => {
|
|
256
|
+
kind: PortalAnswerKind.Stop;
|
|
257
|
+
};
|
|
202
258
|
};
|
|
203
259
|
export type PortalAnswer = ReturnType<(typeof PortalAnswer)[keyof typeof PortalAnswer]>;
|
|
260
|
+
export declare enum CapturingKind {
|
|
261
|
+
/** An application controls input, and the clipboard when `clipboard` is set. */
|
|
262
|
+
RemoteDesktop = 0,
|
|
263
|
+
/** An application takes the user's input once it crosses a screen edge. */
|
|
264
|
+
InputCapture = 1,
|
|
265
|
+
/** A kind this SDK cannot parse. It can still be stopped. */
|
|
266
|
+
Unknown = 2
|
|
267
|
+
}
|
|
268
|
+
/** What every capturing session carries. */
|
|
269
|
+
export type CapturingBase = {
|
|
270
|
+
/** The id {@link stopCapturing} takes. */
|
|
271
|
+
id: number;
|
|
272
|
+
/** The application's desktop file id. Empty when unknown. */
|
|
273
|
+
appId: string;
|
|
274
|
+
};
|
|
275
|
+
export declare const Capturing: {
|
|
276
|
+
InputCapture: (base: CapturingBase, body: InputCaptureBody) => {
|
|
277
|
+
devices: Devices;
|
|
278
|
+
/** The id {@link stopCapturing} takes. */
|
|
279
|
+
id: number;
|
|
280
|
+
/** The application's desktop file id. Empty when unknown. */
|
|
281
|
+
appId: string;
|
|
282
|
+
kind: CapturingKind.InputCapture;
|
|
283
|
+
};
|
|
284
|
+
RemoteDesktop: (base: CapturingBase, body: RemoteDesktopBody) => {
|
|
285
|
+
devices: Devices;
|
|
286
|
+
clipboard: boolean;
|
|
287
|
+
/** The id {@link stopCapturing} takes. */
|
|
288
|
+
id: number;
|
|
289
|
+
/** The application's desktop file id. Empty when unknown. */
|
|
290
|
+
appId: string;
|
|
291
|
+
kind: CapturingKind.RemoteDesktop;
|
|
292
|
+
};
|
|
293
|
+
Unknown: (base: CapturingBase, wireKind: string) => {
|
|
294
|
+
/** The id {@link stopCapturing} takes. */
|
|
295
|
+
id: number;
|
|
296
|
+
/** The application's desktop file id. Empty when unknown. */
|
|
297
|
+
appId: string;
|
|
298
|
+
kind: CapturingKind.Unknown;
|
|
299
|
+
wireKind: string;
|
|
300
|
+
};
|
|
301
|
+
};
|
|
302
|
+
export type Capturing = ReturnType<(typeof Capturing)[keyof typeof Capturing]>;
|
|
204
303
|
/** What the portal functions need of the desktop `Shell` is handed. */
|
|
205
304
|
export type PortalHost = Pick<DomicileHost, "answerPortalRequest"> & {
|
|
206
305
|
addEventListener: (type: "portalrequests", listener: (event: MessageEvent<string>) => void) => void;
|
|
@@ -212,5 +311,12 @@ export type PortalHost = Pick<DomicileHost, "answerPortalRequest"> & {
|
|
|
212
311
|
* whose body does not parse: the compositor and this SDK disagree.
|
|
213
312
|
*/
|
|
214
313
|
export declare const watchPortalRequests: (host: PortalHost, listener: (requests: readonly PortalRequest[]) => void) => (() => void);
|
|
314
|
+
/**
|
|
315
|
+
* Call `listener` with every session that controls or captures input, on each
|
|
316
|
+
* change. Returns a function that stops listening.
|
|
317
|
+
*/
|
|
318
|
+
export declare const watchCapturing: (host: PortalHost, listener: (sessions: readonly Capturing[]) => void) => (() => void);
|
|
215
319
|
/** Answer request `id`. The first answer to reach the compositor wins. */
|
|
216
320
|
export declare const answerPortalRequest: (host: PortalHost, id: number, answer: PortalAnswer) => void;
|
|
321
|
+
/** End capturing session `id`. */
|
|
322
|
+
export declare const stopCapturing: (host: PortalHost, id: number) => void;
|
package/dist/portal.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
//
|
|
5
5
|
// The engine relays each request's body untyped; it is parsed here, by kind.
|
|
6
6
|
// A new kind is one schema in `KINDS`, one `PortalKind` and one constructor.
|
|
7
|
+
// The same push lists the sessions that control or capture input.
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
export var PortalKind;
|
|
9
10
|
(function (PortalKind) {
|
|
@@ -18,8 +19,12 @@ export var PortalKind;
|
|
|
18
19
|
* lets go. Not a question: the compositor refuses answers to it.
|
|
19
20
|
*/
|
|
20
21
|
PortalKind[PortalKind["Inhibit"] = 3] = "Inhibit";
|
|
22
|
+
/** Which input devices, and the clipboard, an application may control. */
|
|
23
|
+
PortalKind[PortalKind["RemoteDesktop"] = 4] = "RemoteDesktop";
|
|
24
|
+
/** Whether an application may take input that crosses a screen edge. */
|
|
25
|
+
PortalKind[PortalKind["InputCapture"] = 5] = "InputCapture";
|
|
21
26
|
/** A kind this SDK cannot parse. Answer it with {@link PortalAnswer.Refused}. */
|
|
22
|
-
PortalKind[PortalKind["Unknown"] =
|
|
27
|
+
PortalKind[PortalKind["Unknown"] = 6] = "Unknown";
|
|
23
28
|
})(PortalKind || (PortalKind = {}));
|
|
24
29
|
/** Which `FileChooser` method asked. */
|
|
25
30
|
export var FileChooserMode;
|
|
@@ -59,6 +64,16 @@ export const PortalRequest = {
|
|
|
59
64
|
body,
|
|
60
65
|
kind: PortalKind.Inhibit,
|
|
61
66
|
}),
|
|
67
|
+
InputCapture: (base, body) => ({
|
|
68
|
+
...base,
|
|
69
|
+
body,
|
|
70
|
+
kind: PortalKind.InputCapture,
|
|
71
|
+
}),
|
|
72
|
+
RemoteDesktop: (base, body) => ({
|
|
73
|
+
...base,
|
|
74
|
+
body,
|
|
75
|
+
kind: PortalKind.RemoteDesktop,
|
|
76
|
+
}),
|
|
62
77
|
Unknown: (base, wireKind) => ({
|
|
63
78
|
...base,
|
|
64
79
|
kind: PortalKind.Unknown,
|
|
@@ -73,10 +88,16 @@ export var PortalAnswerKind;
|
|
|
73
88
|
PortalAnswerKind[PortalAnswerKind["AppChooser"] = 1] = "AppChooser";
|
|
74
89
|
/** The user chose in a {@link PortalKind.FileChooser}. */
|
|
75
90
|
PortalAnswerKind[PortalAnswerKind["FileChooser"] = 2] = "FileChooser";
|
|
91
|
+
/** The user granted a {@link PortalKind.RemoteDesktop} no more than it asked. */
|
|
92
|
+
PortalAnswerKind[PortalAnswerKind["RemoteDesktop"] = 3] = "RemoteDesktop";
|
|
93
|
+
/** The user allowed a {@link PortalKind.InputCapture} request. */
|
|
94
|
+
PortalAnswerKind[PortalAnswerKind["InputCapture"] = 4] = "InputCapture";
|
|
95
|
+
/** The user stopped a {@link Capturing} session. */
|
|
96
|
+
PortalAnswerKind[PortalAnswerKind["Stop"] = 5] = "Stop";
|
|
76
97
|
/** The user dismissed or denied the dialog. */
|
|
77
|
-
PortalAnswerKind[PortalAnswerKind["Canceled"] =
|
|
98
|
+
PortalAnswerKind[PortalAnswerKind["Canceled"] = 6] = "Canceled";
|
|
78
99
|
/** The shell has no dialog for this kind. */
|
|
79
|
-
PortalAnswerKind[PortalAnswerKind["Refused"] =
|
|
100
|
+
PortalAnswerKind[PortalAnswerKind["Refused"] = 7] = "Refused";
|
|
80
101
|
})(PortalAnswerKind || (PortalAnswerKind = {}));
|
|
81
102
|
export const PortalAnswer = {
|
|
82
103
|
Access: () => ({ kind: PortalAnswerKind.Access }),
|
|
@@ -90,7 +111,40 @@ export const PortalAnswer = {
|
|
|
90
111
|
chosen,
|
|
91
112
|
kind: PortalAnswerKind.FileChooser,
|
|
92
113
|
}),
|
|
114
|
+
InputCapture: () => ({ kind: PortalAnswerKind.InputCapture }),
|
|
93
115
|
Refused: () => ({ kind: PortalAnswerKind.Refused }),
|
|
116
|
+
RemoteDesktop: (devices, clipboard) => ({
|
|
117
|
+
clipboard,
|
|
118
|
+
devices,
|
|
119
|
+
kind: PortalAnswerKind.RemoteDesktop,
|
|
120
|
+
}),
|
|
121
|
+
Stop: () => ({ kind: PortalAnswerKind.Stop }),
|
|
122
|
+
};
|
|
123
|
+
export var CapturingKind;
|
|
124
|
+
(function (CapturingKind) {
|
|
125
|
+
/** An application controls input, and the clipboard when `clipboard` is set. */
|
|
126
|
+
CapturingKind[CapturingKind["RemoteDesktop"] = 0] = "RemoteDesktop";
|
|
127
|
+
/** An application takes the user's input once it crosses a screen edge. */
|
|
128
|
+
CapturingKind[CapturingKind["InputCapture"] = 1] = "InputCapture";
|
|
129
|
+
/** A kind this SDK cannot parse. It can still be stopped. */
|
|
130
|
+
CapturingKind[CapturingKind["Unknown"] = 2] = "Unknown";
|
|
131
|
+
})(CapturingKind || (CapturingKind = {}));
|
|
132
|
+
export const Capturing = {
|
|
133
|
+
InputCapture: (base, body) => ({
|
|
134
|
+
...base,
|
|
135
|
+
...body,
|
|
136
|
+
kind: CapturingKind.InputCapture,
|
|
137
|
+
}),
|
|
138
|
+
RemoteDesktop: (base, body) => ({
|
|
139
|
+
...base,
|
|
140
|
+
...body,
|
|
141
|
+
kind: CapturingKind.RemoteDesktop,
|
|
142
|
+
}),
|
|
143
|
+
Unknown: (base, wireKind) => ({
|
|
144
|
+
...base,
|
|
145
|
+
kind: CapturingKind.Unknown,
|
|
146
|
+
wireKind,
|
|
147
|
+
}),
|
|
94
148
|
};
|
|
95
149
|
/**
|
|
96
150
|
* Call `listener` with every unanswered request, oldest first, on each change.
|
|
@@ -108,10 +162,29 @@ export const watchPortalRequests = (host, listener) => {
|
|
|
108
162
|
host.removeEventListener("portalrequests", heard);
|
|
109
163
|
};
|
|
110
164
|
};
|
|
165
|
+
/**
|
|
166
|
+
* Call `listener` with every session that controls or captures input, on each
|
|
167
|
+
* change. Returns a function that stops listening.
|
|
168
|
+
*/
|
|
169
|
+
export const watchCapturing = (host, listener) => {
|
|
170
|
+
const heard = (event) => {
|
|
171
|
+
listener(requestsSchema
|
|
172
|
+
.parse(JSON.parse(event.data))
|
|
173
|
+
.capturing.map((item) => parseCapturing(item)));
|
|
174
|
+
};
|
|
175
|
+
host.addEventListener("portalrequests", heard);
|
|
176
|
+
return () => {
|
|
177
|
+
host.removeEventListener("portalrequests", heard);
|
|
178
|
+
};
|
|
179
|
+
};
|
|
111
180
|
/** Answer request `id`. The first answer to reach the compositor wins. */
|
|
112
181
|
export const answerPortalRequest = (host, id, answer) => {
|
|
113
182
|
host.answerPortalRequest(id, JSON.stringify(wireAnswer(answer)));
|
|
114
183
|
};
|
|
184
|
+
/** End capturing session `id`. */
|
|
185
|
+
export const stopCapturing = (host, id) => {
|
|
186
|
+
answerPortalRequest(host, id, PortalAnswer.Stop());
|
|
187
|
+
};
|
|
115
188
|
const accessSchema = z
|
|
116
189
|
.object({
|
|
117
190
|
body: z.string(),
|
|
@@ -190,6 +263,16 @@ const inhibitSchema = z
|
|
|
190
263
|
reason: body.reason,
|
|
191
264
|
what: body.what.map((inhibited) => INHIBITED[inhibited]),
|
|
192
265
|
}));
|
|
266
|
+
const devicesSchema = z.object({
|
|
267
|
+
keyboard: z.boolean(),
|
|
268
|
+
pointer: z.boolean(),
|
|
269
|
+
touchscreen: z.boolean(),
|
|
270
|
+
});
|
|
271
|
+
const remoteDesktopSchema = z.object({
|
|
272
|
+
clipboard: z.boolean(),
|
|
273
|
+
devices: devicesSchema,
|
|
274
|
+
});
|
|
275
|
+
const inputCaptureSchema = z.object({ devices: devicesSchema });
|
|
193
276
|
/** Each kind's wire name, and how to read its body into a request. */
|
|
194
277
|
const KINDS = new Map([
|
|
195
278
|
[
|
|
@@ -208,6 +291,25 @@ const KINDS = new Map([
|
|
|
208
291
|
"inhibit",
|
|
209
292
|
(base, body) => PortalRequest.Inhibit(base, inhibitSchema.parse(body)),
|
|
210
293
|
],
|
|
294
|
+
[
|
|
295
|
+
"remote_desktop",
|
|
296
|
+
(base, body) => PortalRequest.RemoteDesktop(base, remoteDesktopSchema.parse(body)),
|
|
297
|
+
],
|
|
298
|
+
[
|
|
299
|
+
"input_capture",
|
|
300
|
+
(base, body) => PortalRequest.InputCapture(base, inputCaptureSchema.parse(body)),
|
|
301
|
+
],
|
|
302
|
+
]);
|
|
303
|
+
/** Each capturing kind's wire name, and how to read its body into a session. */
|
|
304
|
+
const CAPTURING_KINDS = new Map([
|
|
305
|
+
[
|
|
306
|
+
"remote_desktop",
|
|
307
|
+
(base, body) => Capturing.RemoteDesktop(base, remoteDesktopSchema.parse(body)),
|
|
308
|
+
],
|
|
309
|
+
[
|
|
310
|
+
"input_capture",
|
|
311
|
+
(base, body) => Capturing.InputCapture(base, inputCaptureSchema.parse(body)),
|
|
312
|
+
],
|
|
211
313
|
]);
|
|
212
314
|
const itemSchema = z.object({
|
|
213
315
|
app_id: z.string(),
|
|
@@ -216,7 +318,15 @@ const itemSchema = z.object({
|
|
|
216
318
|
kind: z.string(),
|
|
217
319
|
parent_app_id: z.string().optional(),
|
|
218
320
|
});
|
|
321
|
+
const capturingSchema = z.object({
|
|
322
|
+
app_id: z.string(),
|
|
323
|
+
body: z.unknown(),
|
|
324
|
+
id: z.number(),
|
|
325
|
+
kind: z.string(),
|
|
326
|
+
});
|
|
219
327
|
const requestsSchema = z.object({
|
|
328
|
+
// Optional on the wire, so a line without it parses.
|
|
329
|
+
capturing: z.array(capturingSchema).default([]),
|
|
220
330
|
items: z.array(itemSchema),
|
|
221
331
|
type: z.literal("portal_requests"),
|
|
222
332
|
});
|
|
@@ -241,6 +351,13 @@ const chooserMode = (mode) => {
|
|
|
241
351
|
return FileChooserMode.SaveFiles;
|
|
242
352
|
}
|
|
243
353
|
};
|
|
354
|
+
const parseCapturing = (item) => {
|
|
355
|
+
const base = { appId: item.app_id, id: item.id };
|
|
356
|
+
const parse = CAPTURING_KINDS.get(item.kind);
|
|
357
|
+
return parse === undefined
|
|
358
|
+
? Capturing.Unknown(base, item.kind)
|
|
359
|
+
: parse(base, item.body);
|
|
360
|
+
};
|
|
244
361
|
/** `answer` as the compositor reads it. */
|
|
245
362
|
const wireAnswer = (answer) => {
|
|
246
363
|
switch (answer.kind) {
|
|
@@ -248,6 +365,16 @@ const wireAnswer = (answer) => {
|
|
|
248
365
|
return { kind: "access" };
|
|
249
366
|
case PortalAnswerKind.AppChooser:
|
|
250
367
|
return { choice: answer.choice, kind: "app_chooser" };
|
|
368
|
+
case PortalAnswerKind.RemoteDesktop:
|
|
369
|
+
return {
|
|
370
|
+
clipboard: answer.clipboard,
|
|
371
|
+
devices: answer.devices,
|
|
372
|
+
kind: "remote_desktop",
|
|
373
|
+
};
|
|
374
|
+
case PortalAnswerKind.InputCapture:
|
|
375
|
+
return { kind: "input_capture" };
|
|
376
|
+
case PortalAnswerKind.Stop:
|
|
377
|
+
return { kind: "stop" };
|
|
251
378
|
case PortalAnswerKind.Canceled:
|
|
252
379
|
return { kind: "canceled" };
|
|
253
380
|
case PortalAnswerKind.FileChooser:
|
package/package.json
CHANGED