@zenbu-labs/pixel 0.0.0 → 0.0.12

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.
Files changed (153) hide show
  1. package/dist/bin.d.ts +2 -0
  2. package/dist/bin.js +166 -0
  3. package/dist/bootstrap.d.ts +1 -0
  4. package/dist/bootstrap.js +75 -0
  5. package/dist/context-menu.d.ts +20 -0
  6. package/dist/context-menu.js +57 -0
  7. package/dist/debug.d.ts +1 -0
  8. package/dist/debug.js +9 -0
  9. package/dist/devtools-layout.d.ts +21 -0
  10. package/dist/devtools-layout.js +45 -0
  11. package/dist/devtools.d.ts +33 -0
  12. package/dist/devtools.js +125 -0
  13. package/dist/electron/index.d.ts +3 -0
  14. package/dist/electron/index.js +4 -0
  15. package/dist/host/guest.d.ts +5 -0
  16. package/dist/host/guest.js +178 -0
  17. package/dist/host/server.d.ts +91 -0
  18. package/dist/host/server.js +296 -0
  19. package/dist/host/shell.d.ts +35 -0
  20. package/dist/host/shell.js +113 -0
  21. package/dist/host/strip.d.ts +6 -0
  22. package/dist/host/strip.js +63 -0
  23. package/dist/icons.d.ts +30 -0
  24. package/dist/icons.js +58 -0
  25. package/dist/index.d.ts +17 -0
  26. package/dist/index.js +39 -0
  27. package/dist/instances.d.ts +30 -0
  28. package/dist/instances.js +177 -0
  29. package/dist/layout.d.ts +5 -0
  30. package/dist/layout.js +34 -0
  31. package/dist/popup.d.ts +21 -0
  32. package/dist/popup.js +47 -0
  33. package/dist/preload/index.d.ts +15 -0
  34. package/dist/preload/index.js +3 -0
  35. package/dist/react/colors.d.ts +3 -0
  36. package/dist/react/colors.js +25 -0
  37. package/dist/react/components.d.ts +21 -0
  38. package/dist/react/components.js +45 -0
  39. package/dist/react/devtools/app.d.ts +3 -0
  40. package/dist/react/devtools/app.js +89 -0
  41. package/dist/react/devtools/console-capture.d.ts +1 -0
  42. package/dist/react/devtools/console-capture.js +41 -0
  43. package/dist/react/devtools/controller.d.ts +45 -0
  44. package/dist/react/devtools/controller.js +252 -0
  45. package/dist/react/devtools/elements.d.ts +4 -0
  46. package/dist/react/devtools/elements.js +152 -0
  47. package/dist/react/devtools/export-profile.d.ts +2 -0
  48. package/dist/react/devtools/export-profile.js +225 -0
  49. package/dist/react/devtools/fiber-hook.d.ts +1 -0
  50. package/dist/react/devtools/fiber-hook.js +89 -0
  51. package/dist/react/devtools/log-panel.d.ts +4 -0
  52. package/dist/react/devtools/log-panel.js +113 -0
  53. package/dist/react/devtools/profiler.d.ts +11 -0
  54. package/dist/react/devtools/profiler.js +374 -0
  55. package/dist/react/devtools/store.d.ts +27 -0
  56. package/dist/react/devtools/store.js +61 -0
  57. package/dist/react/devtools/stores.d.ts +92 -0
  58. package/dist/react/devtools/stores.js +41 -0
  59. package/dist/react/devtools/theme.d.ts +35 -0
  60. package/dist/react/devtools/theme.js +77 -0
  61. package/dist/react/devtools/ui.d.ts +24 -0
  62. package/dist/react/devtools/ui.js +59 -0
  63. package/dist/react/index.d.ts +110 -0
  64. package/dist/react/index.js +538 -0
  65. package/dist/react/markdown.d.ts +25 -0
  66. package/dist/react/markdown.js +270 -0
  67. package/dist/react/native.d.ts +116 -0
  68. package/dist/react/native.js +56 -0
  69. package/dist/react/reconciler-config.d.ts +241 -0
  70. package/dist/react/reconciler-config.js +412 -0
  71. package/dist/react/styles.d.ts +88 -0
  72. package/dist/react/styles.js +85 -0
  73. package/dist/react/surface.d.ts +55 -0
  74. package/dist/react/surface.js +74 -0
  75. package/dist/registry.d.ts +53 -0
  76. package/dist/registry.js +193 -0
  77. package/dist/root.d.ts +19 -0
  78. package/dist/root.js +342 -0
  79. package/dist/sandbox.d.ts +4 -0
  80. package/dist/sandbox.js +84 -0
  81. package/dist/scale.d.ts +7 -0
  82. package/dist/scale.js +31 -0
  83. package/dist/ssh/index.d.ts +58 -0
  84. package/dist/ssh/index.js +445 -0
  85. package/dist/terminal/applescript.d.ts +2 -0
  86. package/dist/terminal/applescript.js +20 -0
  87. package/dist/terminal/detect.d.ts +10 -0
  88. package/dist/terminal/detect.js +34 -0
  89. package/dist/terminal/graphics.d.ts +9 -0
  90. package/dist/terminal/graphics.js +142 -0
  91. package/dist/terminal/index.d.ts +12 -0
  92. package/dist/terminal/index.js +23 -0
  93. package/dist/terminal/run.d.ts +2 -0
  94. package/dist/terminal/run.js +15 -0
  95. package/dist/terminal/shared.d.ts +20 -0
  96. package/dist/terminal/shared.js +88 -0
  97. package/dist/terminal/terminal.d.ts +66 -0
  98. package/dist/terminal/terminal.js +6 -0
  99. package/dist/terminal/terminals/cmux.d.ts +2 -0
  100. package/dist/terminal/terminals/cmux.js +98 -0
  101. package/dist/terminal/terminals/ghostty-script.d.ts +1 -0
  102. package/dist/terminal/terminals/ghostty-script.js +179 -0
  103. package/dist/terminal/terminals/ghostty.d.ts +2 -0
  104. package/dist/terminal/terminals/ghostty.js +336 -0
  105. package/dist/terminal/terminals/herdr.d.ts +2 -0
  106. package/dist/terminal/terminals/herdr.js +141 -0
  107. package/dist/terminal/terminals/index.d.ts +5 -0
  108. package/dist/terminal/terminals/index.js +26 -0
  109. package/dist/terminal/terminals/kitty.d.ts +2 -0
  110. package/dist/terminal/terminals/kitty.js +209 -0
  111. package/dist/terminal/terminals/supacode.d.ts +2 -0
  112. package/dist/terminal/terminals/supacode.js +79 -0
  113. package/dist/terminal/terminals/tmux.d.ts +2 -0
  114. package/dist/terminal/terminals/tmux.js +132 -0
  115. package/dist/terminal/terminals/tty7.d.ts +2 -0
  116. package/dist/terminal/terminals/tty7.js +58 -0
  117. package/dist/terminal/terminals/vscode.d.ts +2 -0
  118. package/dist/terminal/terminals/vscode.js +13 -0
  119. package/dist/terminal/terminals/wezterm.d.ts +2 -0
  120. package/dist/terminal/terminals/wezterm.js +59 -0
  121. package/dist/theme.d.ts +22 -0
  122. package/dist/theme.js +40 -0
  123. package/dist/web/browser-session.d.ts +13 -0
  124. package/dist/web/browser-session.js +186 -0
  125. package/dist/web/cursor.d.ts +1 -0
  126. package/dist/web/cursor.js +24 -0
  127. package/dist/web/devtools.d.ts +39 -0
  128. package/dist/web/devtools.js +300 -0
  129. package/dist/web/favicon.d.ts +7 -0
  130. package/dist/web/favicon.js +73 -0
  131. package/dist/web/frame-rate.d.ts +1 -0
  132. package/dist/web/frame-rate.js +12 -0
  133. package/dist/web/host.d.ts +123 -0
  134. package/dist/web/host.js +573 -0
  135. package/dist/web/input.d.ts +49 -0
  136. package/dist/web/input.js +468 -0
  137. package/dist/web/offscreen.d.ts +2 -0
  138. package/dist/web/offscreen.js +23 -0
  139. package/dist/web/paint.d.ts +11 -0
  140. package/dist/web/paint.js +128 -0
  141. package/dist/web/popup.d.ts +40 -0
  142. package/dist/web/popup.js +144 -0
  143. package/dist/web/session.d.ts +20 -0
  144. package/dist/web/session.js +110 -0
  145. package/dist/web/types.d.ts +38 -0
  146. package/dist/web/types.js +39 -0
  147. package/dist/web/zoom.d.ts +5 -0
  148. package/dist/web/zoom.js +36 -0
  149. package/dist/webview.d.ts +55 -0
  150. package/dist/webview.js +481 -0
  151. package/package.json +69 -3
  152. package/scripts/apparmor.sh +71 -0
  153. package/scripts/postinstall.mjs +150 -0
@@ -0,0 +1,49 @@
1
+ import type { WebContents } from "electron";
2
+ import type { EngineKeyEvent, PastedImage, PointerEvent, WheelEvent } from "../react";
3
+ export interface InputTarget {
4
+ contents(): WebContents;
5
+ scale(): number;
6
+ focus(): Promise<void> | void;
7
+ cdp(method: string, params?: Record<string, unknown>): Promise<unknown>;
8
+ }
9
+ export declare class PageInput {
10
+ private readonly target;
11
+ private lastX;
12
+ private lastY;
13
+ private lastSentX;
14
+ private lastSentY;
15
+ private pressed;
16
+ private click;
17
+ private activeClickCount;
18
+ private wheelRemainderX;
19
+ private wheelRemainderY;
20
+ private sentKeys;
21
+ private superHeld;
22
+ private focusGate;
23
+ constructor(target: InputTarget);
24
+ private syncFocus;
25
+ private send;
26
+ releaseModifiers(): void;
27
+ private rememberModifiers;
28
+ private pointerModifiers;
29
+ pointer(event: PointerEvent): void;
30
+ wheel(event: WheelEvent): void;
31
+ private wheelTick;
32
+ private pinch;
33
+ key(event: EngineKeyEvent): void;
34
+ paste(text: string): void;
35
+ selectionText(): Promise<string>;
36
+ pasteImage(image: PastedImage): Promise<void>;
37
+ releaseKeys(): void;
38
+ /**
39
+ *
40
+ * why are we hard coding huerestics for vscode web??
41
+ *
42
+ */
43
+ private dispatchEnter;
44
+ private dispatchPaste;
45
+ private dispatchEditing;
46
+ private nextClickCount;
47
+ private modifiers;
48
+ }
49
+ export declare function electronKey(key: string): string | null;
@@ -0,0 +1,468 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageInput = void 0;
4
+ exports.electronKey = electronKey;
5
+ const electron_1 = require("electron");
6
+ class PageInput {
7
+ target;
8
+ lastX = 0;
9
+ lastY = 0;
10
+ lastSentX = 0;
11
+ lastSentY = 0;
12
+ pressed = new Set();
13
+ click = { button: "none", at: 0, x: 0, y: 0, count: 0 };
14
+ activeClickCount = 1;
15
+ wheelRemainderX = 0;
16
+ wheelRemainderY = 0;
17
+ sentKeys = new Set();
18
+ superHeld = false;
19
+ focusGate = null;
20
+ constructor(target) {
21
+ this.target = target;
22
+ }
23
+ syncFocus() {
24
+ const pending = this.target.focus();
25
+ if (!pending)
26
+ return this.focusGate;
27
+ const gate = this.focusGate ? this.focusGate.then(() => pending) : pending;
28
+ this.focusGate = gate;
29
+ void gate.then(() => {
30
+ if (this.focusGate === gate)
31
+ this.focusGate = null;
32
+ });
33
+ return gate;
34
+ }
35
+ send(event) {
36
+ const contents = this.target.contents();
37
+ if (this.focusGate)
38
+ void this.focusGate.then(() => contents.sendInputEvent(event));
39
+ else
40
+ contents.sendInputEvent(event);
41
+ }
42
+ releaseModifiers() {
43
+ this.superHeld = false;
44
+ }
45
+ rememberModifiers(event) {
46
+ this.superHeld =
47
+ event.key === "leftsuper" || event.key === "rightsuper"
48
+ ? event.kind !== "release"
49
+ : !!event.mods.super;
50
+ }
51
+ pointerModifiers(mods) {
52
+ return this.modifiers(this.superHeld && !mods.super ? { ...mods, super: true } : mods);
53
+ }
54
+ pointer(event) {
55
+ this.syncFocus();
56
+ const scale = this.target.scale();
57
+ const x = Math.max(0, Math.round(event.x / scale));
58
+ const y = Math.max(0, Math.round(event.y / scale));
59
+ this.lastX = x;
60
+ this.lastY = y;
61
+ const button = event.button === "none" ? undefined : event.button;
62
+ if (event.kind === "down" && button) {
63
+ this.pressed.add(button);
64
+ this.activeClickCount = this.nextClickCount(button, x, y);
65
+ }
66
+ if (event.kind === "up" && button)
67
+ this.pressed.delete(button);
68
+ const modifiers = this.pointerModifiers(event.mods);
69
+ for (const pressed of this.pressed)
70
+ modifiers.push(`${pressed}buttondown`);
71
+ this.send({
72
+ type: event.kind === "down"
73
+ ? "mouseDown"
74
+ : event.kind === "up"
75
+ ? "mouseUp"
76
+ : "mouseMove",
77
+ x,
78
+ y,
79
+ movementX: x - this.lastSentX,
80
+ movementY: y - this.lastSentY,
81
+ button,
82
+ clickCount: event.kind === "move" ? 0 : this.activeClickCount,
83
+ modifiers,
84
+ });
85
+ this.lastSentX = x;
86
+ this.lastSentY = y;
87
+ }
88
+ wheel(event) {
89
+ this.syncFocus();
90
+ if (event.mods.ctrl && event.precise) {
91
+ this.pinch(event);
92
+ return;
93
+ }
94
+ if (!event.precise) {
95
+ this.wheelTick(event);
96
+ return;
97
+ }
98
+ const scale = this.target.scale();
99
+ this.wheelRemainderX += -event.deltaX / scale;
100
+ this.wheelRemainderY += -event.deltaY / scale;
101
+ const deltaX = wholeDelta(this.wheelRemainderX);
102
+ const deltaY = wholeDelta(this.wheelRemainderY);
103
+ this.wheelRemainderX -= deltaX;
104
+ this.wheelRemainderY -= deltaY;
105
+ if (deltaX === 0 && deltaY === 0)
106
+ return;
107
+ this.send({
108
+ type: "mouseWheel",
109
+ x: this.lastX,
110
+ y: this.lastY,
111
+ deltaX,
112
+ deltaY,
113
+ wheelTicksX: deltaX / 40,
114
+ wheelTicksY: deltaY / 40,
115
+ hasPreciseScrollingDeltas: true,
116
+ canScroll: true,
117
+ modifiers: this.pointerModifiers(event.mods),
118
+ });
119
+ }
120
+ wheelTick(event) {
121
+ const ticksX = -Math.sign(event.deltaX);
122
+ const ticksY = -Math.sign(event.deltaY);
123
+ if (ticksX === 0 && ticksY === 0)
124
+ return;
125
+ const step = WHEEL_DETENT_PX;
126
+ this.send({
127
+ type: "mouseWheel",
128
+ x: this.lastX,
129
+ y: this.lastY,
130
+ deltaX: ticksX * step,
131
+ deltaY: ticksY * step,
132
+ wheelTicksX: ticksX,
133
+ wheelTicksY: ticksY,
134
+ hasPreciseScrollingDeltas: false,
135
+ canScroll: true,
136
+ modifiers: this.pointerModifiers(event.mods),
137
+ });
138
+ }
139
+ pinch(event) {
140
+ const pinchScale = 1 - event.deltaY / 100;
141
+ if (pinchScale <= 0)
142
+ return;
143
+ this.send({
144
+ type: "mouseWheel",
145
+ x: this.lastX,
146
+ y: this.lastY,
147
+ deltaX: 0,
148
+ deltaY: 100 * Math.log(pinchScale),
149
+ wheelTicksX: 0,
150
+ wheelTicksY: pinchScale > 1 ? 1 : -1,
151
+ hasPreciseScrollingDeltas: true,
152
+ canScroll: true,
153
+ modifiers: ["ctrl"],
154
+ });
155
+ }
156
+ key(event) {
157
+ this.rememberModifiers(event);
158
+ if (event.key === "enter") {
159
+ void this.dispatchEnter(event).catch(() => { });
160
+ return;
161
+ }
162
+ const commands = process.platform === "darwin" ? editingCommands(event) : null;
163
+ if (commands) {
164
+ void this.dispatchEditing(event, commands).catch(() => { });
165
+ return;
166
+ }
167
+ const keyCode = electronKey(event.key);
168
+ if (event.kind === "release") {
169
+ if (!keyCode || !this.sentKeys.delete(event.key))
170
+ return;
171
+ const modifiers = this.modifiers(event.mods);
172
+ if (event.key.startsWith("left"))
173
+ modifiers.push("left");
174
+ if (event.key.startsWith("right"))
175
+ modifiers.push("right");
176
+ this.send({ type: "keyUp", keyCode, modifiers });
177
+ return;
178
+ }
179
+ this.syncFocus();
180
+ if (!keyCode) {
181
+ if (event.text) {
182
+ this.target.contents().insertText(event.text);
183
+ }
184
+ return;
185
+ }
186
+ const modifiers = this.modifiers(event.mods);
187
+ if (event.key.startsWith("left"))
188
+ modifiers.push("left");
189
+ if (event.key.startsWith("right"))
190
+ modifiers.push("right");
191
+ if (event.kind === "repeat")
192
+ modifiers.push("isautorepeat");
193
+ this.sentKeys.add(event.key);
194
+ this.send({ type: "rawKeyDown", keyCode, modifiers });
195
+ const printable = !!event.text && !event.mods.ctrl && !event.mods.super && !event.mods.alt;
196
+ if (printable) {
197
+ this.send({ type: "char", keyCode: event.text, modifiers });
198
+ }
199
+ }
200
+ paste(text) {
201
+ electron_1.clipboard.writeText(text);
202
+ if (process.platform === "darwin") {
203
+ void this.dispatchPaste().catch(() => { });
204
+ return;
205
+ }
206
+ this.syncFocus();
207
+ this.target.contents().paste();
208
+ }
209
+ async selectionText() {
210
+ for (const frame of this.target.contents().mainFrame.framesInSubtree) {
211
+ const text = await frame.executeJavaScript(SELECTION_SNIPPET).catch(() => "");
212
+ if (typeof text === "string" && text)
213
+ return text;
214
+ }
215
+ return "";
216
+ }
217
+ async pasteImage(image) {
218
+ this.syncFocus();
219
+ switch (image.source) {
220
+ case "clipboard":
221
+ this.target.contents().paste();
222
+ return;
223
+ case "osc":
224
+ case "file": {
225
+ const staged = electron_1.nativeImage.createFromPath(image.path);
226
+ if (staged.isEmpty())
227
+ return;
228
+ const png = new Blob([new Uint8Array(staged.toPNG())], { type: "image/png" });
229
+ await electron_1.clipboard.write([new electron_1.ClipboardItem({ "image/png": png })]);
230
+ this.target.contents().paste();
231
+ return;
232
+ }
233
+ }
234
+ }
235
+ releaseKeys() {
236
+ for (const key of this.sentKeys) {
237
+ const keyCode = electronKey(key);
238
+ if (!keyCode)
239
+ continue;
240
+ const modifiers = [];
241
+ if (key.startsWith("left"))
242
+ modifiers.push("left");
243
+ if (key.startsWith("right"))
244
+ modifiers.push("right");
245
+ this.send({ type: "keyUp", keyCode, modifiers });
246
+ }
247
+ this.sentKeys.clear();
248
+ }
249
+ /**
250
+ *
251
+ * why are we hard coding huerestics for vscode web??
252
+ *
253
+ */
254
+ async dispatchEnter(event) {
255
+ const base = {
256
+ key: "Enter",
257
+ code: "Enter",
258
+ windowsVirtualKeyCode: 13,
259
+ nativeVirtualKeyCode: 13,
260
+ modifiers: cdpModifiers(event.mods),
261
+ };
262
+ if (event.kind === "release") {
263
+ await this.target.cdp("Input.dispatchKeyEvent", { type: "keyUp", ...base });
264
+ return;
265
+ }
266
+ await this.syncFocus();
267
+ await this.target.cdp("Input.dispatchKeyEvent", {
268
+ type: "rawKeyDown",
269
+ ...base,
270
+ autoRepeat: event.kind === "repeat",
271
+ });
272
+ if (!event.mods.ctrl && !event.mods.super && !event.mods.alt) {
273
+ await this.target.cdp("Input.dispatchKeyEvent", { type: "char", text: "\r", ...base });
274
+ }
275
+ }
276
+ async dispatchPaste() {
277
+ const base = {
278
+ key: "v",
279
+ code: "KeyV",
280
+ windowsVirtualKeyCode: 86,
281
+ nativeVirtualKeyCode: 86,
282
+ modifiers: 4,
283
+ };
284
+ await this.syncFocus();
285
+ await this.target.cdp("Input.dispatchKeyEvent", {
286
+ type: "rawKeyDown",
287
+ ...base,
288
+ commands: ["Paste"],
289
+ });
290
+ await this.target.cdp("Input.dispatchKeyEvent", { type: "keyUp", ...base });
291
+ }
292
+ async dispatchEditing(event, commands) {
293
+ const info = EDITING_KEY_INFO[event.key];
294
+ if (!info)
295
+ return;
296
+ const base = {
297
+ key: info.key,
298
+ code: info.code,
299
+ windowsVirtualKeyCode: info.keyCode,
300
+ nativeVirtualKeyCode: info.keyCode,
301
+ modifiers: cdpModifiers(event.mods),
302
+ };
303
+ if (event.kind === "release") {
304
+ await this.target.cdp("Input.dispatchKeyEvent", { type: "keyUp", ...base });
305
+ return;
306
+ }
307
+ await this.syncFocus();
308
+ await this.target.cdp("Input.dispatchKeyEvent", {
309
+ type: "rawKeyDown",
310
+ ...base,
311
+ autoRepeat: event.kind === "repeat",
312
+ commands,
313
+ });
314
+ }
315
+ nextClickCount(button, x, y) {
316
+ const now = Date.now();
317
+ const close = Math.abs(x - this.click.x) <= 4 && Math.abs(y - this.click.y) <= 4;
318
+ const count = this.click.button === button && now - this.click.at <= 500 && close
319
+ ? Math.min(this.click.count + 1, 3)
320
+ : 1;
321
+ this.click = { button, at: now, x, y, count };
322
+ return count;
323
+ }
324
+ modifiers(mods) {
325
+ const result = [];
326
+ if (mods.shift)
327
+ result.push("shift");
328
+ if (mods.alt)
329
+ result.push("alt");
330
+ if (mods.ctrl)
331
+ result.push("ctrl");
332
+ if (mods.super)
333
+ result.push("meta");
334
+ return result;
335
+ }
336
+ }
337
+ exports.PageInput = PageInput;
338
+ const SELECTION_SNIPPET = `(() => {
339
+ const el = document.activeElement;
340
+ try {
341
+ if (el && "selectionStart" in el && el.selectionStart !== el.selectionEnd) {
342
+ return el.value.slice(el.selectionStart, el.selectionEnd);
343
+ }
344
+ } catch {}
345
+ return String(getSelection() ?? "");
346
+ })()`;
347
+ const WHEEL_DETENT_PX = process.platform === "darwin" ? 40 : 120;
348
+ function wholeDelta(value) {
349
+ return value < 0 ? Math.ceil(value) : Math.floor(value);
350
+ }
351
+ function cdpModifiers(mods) {
352
+ return ((mods.alt ? 1 : 0) | (mods.ctrl ? 2 : 0) | (mods.super ? 4 : 0) | (mods.shift ? 8 : 0));
353
+ }
354
+ const EDITING_KEY_INFO = {
355
+ backspace: { key: "Backspace", code: "Backspace", keyCode: 8 },
356
+ left: { key: "ArrowLeft", code: "ArrowLeft", keyCode: 37 },
357
+ right: { key: "ArrowRight", code: "ArrowRight", keyCode: 39 },
358
+ up: { key: "ArrowUp", code: "ArrowUp", keyCode: 38 },
359
+ down: { key: "ArrowDown", code: "ArrowDown", keyCode: 40 },
360
+ a: { key: "a", code: "KeyA", keyCode: 65 },
361
+ b: { key: "b", code: "KeyB", keyCode: 66 },
362
+ c: { key: "c", code: "KeyC", keyCode: 67 },
363
+ d: { key: "d", code: "KeyD", keyCode: 68 },
364
+ e: { key: "e", code: "KeyE", keyCode: 69 },
365
+ f: { key: "f", code: "KeyF", keyCode: 70 },
366
+ k: { key: "k", code: "KeyK", keyCode: 75 },
367
+ u: { key: "u", code: "KeyU", keyCode: 85 },
368
+ w: { key: "w", code: "KeyW", keyCode: 87 },
369
+ x: { key: "x", code: "KeyX", keyCode: 88 },
370
+ z: { key: "z", code: "KeyZ", keyCode: 90 },
371
+ };
372
+ function editingCommands(event) {
373
+ const { key, mods } = event;
374
+ if (mods.ctrl)
375
+ return controlEditingCommands(event);
376
+ const select = mods.shift ? "AndModifySelection" : "";
377
+ if (key === "backspace") {
378
+ if (mods.super)
379
+ return ["deleteToBeginningOfLine"];
380
+ if (mods.alt)
381
+ return ["deleteWordBackward"];
382
+ return null;
383
+ }
384
+ if (key === "b" && mods.alt && !mods.super)
385
+ return [`moveWordLeft${select}`];
386
+ if (key === "f" && mods.alt && !mods.super)
387
+ return [`moveWordRight${select}`];
388
+ if (key === "left" || key === "right") {
389
+ const end = key === "left" ? "moveToLeftEndOfLine" : "moveToRightEndOfLine";
390
+ const word = key === "left" ? "moveWordLeft" : "moveWordRight";
391
+ if (mods.super)
392
+ return [`${end}${select}`];
393
+ if (mods.alt)
394
+ return [`${word}${select}`];
395
+ return null;
396
+ }
397
+ if (key === "up" || key === "down") {
398
+ const edge = key === "up" ? "moveToBeginningOfDocument" : "moveToEndOfDocument";
399
+ if (mods.super && !mods.alt)
400
+ return [`${edge}${select}`];
401
+ return null;
402
+ }
403
+ if (mods.super && !mods.alt && !mods.shift && key === "a")
404
+ return ["selectAll"];
405
+ if (mods.super && !mods.alt && key === "z")
406
+ return [mods.shift ? "redo" : "undo"];
407
+ if (mods.super && !mods.alt && !mods.shift && key === "c")
408
+ return ["Copy"];
409
+ if (mods.super && !mods.alt && !mods.shift && key === "x")
410
+ return ["Cut"];
411
+ return null;
412
+ }
413
+ // fixme this is left over and shouldn't exist
414
+ function controlEditingCommands(event) {
415
+ const { key, mods } = event;
416
+ if (mods.super || mods.alt)
417
+ return null;
418
+ const select = mods.shift ? "AndModifySelection" : "";
419
+ switch (key) {
420
+ case "a":
421
+ return [`moveToLeftEndOfLine${select}`];
422
+ case "e":
423
+ return [`moveToRightEndOfLine${select}`];
424
+ case "b":
425
+ return [`moveLeft${select}`];
426
+ case "f":
427
+ return [`moveRight${select}`];
428
+ case "d":
429
+ return ["deleteForward"];
430
+ case "k":
431
+ return ["deleteToEndOfLine"];
432
+ case "w":
433
+ return ["deleteWordBackward"];
434
+ case "u":
435
+ return ["deleteToBeginningOfLine"];
436
+ default:
437
+ return null;
438
+ }
439
+ }
440
+ function electronKey(key) {
441
+ const special = {
442
+ enter: "return",
443
+ backspace: "backspace",
444
+ delete: "delete",
445
+ escape: "escape",
446
+ tab: "tab",
447
+ up: "up",
448
+ down: "down",
449
+ left: "left",
450
+ right: "right",
451
+ home: "home",
452
+ end: "end",
453
+ insert: "insert",
454
+ pageup: "pageup",
455
+ pagedown: "pagedown",
456
+ leftshift: "shift",
457
+ leftcontrol: "control",
458
+ leftalt: "alt",
459
+ leftsuper: "meta",
460
+ rightshift: "shift",
461
+ rightcontrol: "control",
462
+ rightalt: "alt",
463
+ rightsuper: "meta",
464
+ };
465
+ if (key === "unknown")
466
+ return null;
467
+ return special[key] ?? key;
468
+ }
@@ -0,0 +1,2 @@
1
+ export declare function offscreenPreferences(deviceScaleFactor: number): Electron.WebPreferences["offscreen"];
2
+ export declare function initOffscreenMode(sharedTextures: boolean): void;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.offscreenPreferences = offscreenPreferences;
4
+ exports.initOffscreenMode = initOffscreenMode;
5
+ const react_1 = require("../react");
6
+ const SHM_FRAMES = process.platform === "linux" && process.env.PIXEL_SHM !== "0";
7
+ function offscreenPreferences(deviceScaleFactor) {
8
+ if (process.platform === "darwin") {
9
+ return { useSharedTexture: true, sharedTexturePixelFormat: "argb", deviceScaleFactor };
10
+ }
11
+ return {
12
+ useSharedTexture: false,
13
+ useSharedMemory: SHM_FRAMES,
14
+ deviceScaleFactor,
15
+ };
16
+ }
17
+ function initOffscreenMode(sharedTextures) {
18
+ if (process.platform === "darwin" && !sharedTextures) {
19
+ throw new Error("wrong electron build installed");
20
+ }
21
+ const mode = process.platform === "darwin" ? "shared-texture" : SHM_FRAMES ? "shm" : "bitmap";
22
+ (0, react_1.appLog)("info", "texture", `offscreen mode: ${mode}`);
23
+ }
@@ -0,0 +1,11 @@
1
+ import type { NativeImage, OffscreenSharedTexture, OffscreenSoftwareFrame, Rectangle } from "electron";
2
+ import type { Surface } from "../react";
3
+ export declare function presentPaint(surface: Surface, texture: OffscreenSharedTexture | undefined, shmFrame: OffscreenSoftwareFrame | undefined, image: NativeImage, dirtyRect: Rectangle, wholeSurface: boolean): boolean;
4
+ export declare class BitmapPresenter {
5
+ private readonly surface;
6
+ private pending;
7
+ private scheduled;
8
+ constructor(surface: Surface);
9
+ push(image: NativeImage, dirtyRect: Rectangle, wholeSurface: boolean): boolean;
10
+ private drain;
11
+ }
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BitmapPresenter = void 0;
4
+ exports.presentPaint = presentPaint;
5
+ const types_1 = require("./types");
6
+ function presentPaint(surface, texture, shmFrame, image, dirtyRect, wholeSurface) {
7
+ if (texture)
8
+ return presentTexture(surface, texture, wholeSurface);
9
+ if (shmFrame)
10
+ return presentShmFrame(surface, shmFrame, dirtyRect, wholeSurface);
11
+ return presentBitmap(surface, image, wholeSurface ? undefined : dirtyRect);
12
+ }
13
+ function presentTexture(surface, texture, wholeSurface) {
14
+ try {
15
+ const info = texture.textureInfo;
16
+ if (info.widgetType !== "frame" || info.pixelFormat !== "bgra")
17
+ return false;
18
+ const { ioSurface } = info.handle;
19
+ if (!ioSurface)
20
+ return false;
21
+ if ((0, types_1.paintedNothing)(info) && !wholeSurface)
22
+ return false;
23
+ surface.present({ ioSurface, damage: wholeSurface ? undefined : (0, types_1.damageOf)(info) });
24
+ return true;
25
+ }
26
+ finally {
27
+ texture.release();
28
+ }
29
+ }
30
+ function presentShmFrame(surface, frame, dirtyRect, wholeSurface) {
31
+ let handedOff = false;
32
+ try {
33
+ const info = frame.frameInfo;
34
+ if (info.widgetType !== "frame")
35
+ return false;
36
+ if (info.pixelFormat !== "bgra")
37
+ return false;
38
+ if (info.contentRect.x !== 0 || info.contentRect.y !== 0)
39
+ return false;
40
+ const update = info.metadata.captureUpdateRect;
41
+ if (update && update.width <= 0 && update.height <= 0 && !wholeSurface)
42
+ return false;
43
+ const damage = wholeSurface || dirtyRect.width <= 0 || dirtyRect.height <= 0 ? undefined : dirtyRect;
44
+ try {
45
+ surface.present({
46
+ shm: {
47
+ fd: info.fd,
48
+ width: info.contentRect.width,
49
+ height: info.contentRect.height,
50
+ stride: info.stride,
51
+ size: info.dataSize,
52
+ },
53
+ damage,
54
+ released: () => frame.release(),
55
+ });
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ handedOff = true;
61
+ return true;
62
+ }
63
+ finally {
64
+ if (!handedOff)
65
+ frame.release();
66
+ }
67
+ }
68
+ function presentBitmap(surface, image, dirtyRect) {
69
+ const size = image.getSize();
70
+ if (size.width <= 0 || size.height <= 0)
71
+ return false;
72
+ const damage = dirtyRect && dirtyRect.width > 0 && dirtyRect.height > 0 ? dirtyRect : undefined;
73
+ surface.present({ bgra: image.toBitmap(), width: size.width, height: size.height, damage });
74
+ return true;
75
+ }
76
+ function unionRect(a, b) {
77
+ const x = Math.min(a.x, b.x);
78
+ const y = Math.min(a.y, b.y);
79
+ return {
80
+ x,
81
+ y,
82
+ width: Math.max(a.x + a.width, b.x + b.width) - x,
83
+ height: Math.max(a.y + a.height, b.y + b.height) - y,
84
+ };
85
+ }
86
+ class BitmapPresenter {
87
+ surface;
88
+ pending = null;
89
+ scheduled = false;
90
+ constructor(surface) {
91
+ this.surface = surface;
92
+ }
93
+ push(image, dirtyRect, wholeSurface) {
94
+ const size = image.getSize();
95
+ if (size.width <= 0 || size.height <= 0)
96
+ return false;
97
+ const fresh = dirtyRect.width > 0 && dirtyRect.height > 0 ? dirtyRect : undefined;
98
+ const stale = this.pending;
99
+ const carried = stale && stale.width === size.width && stale.height === size.height ? stale : null;
100
+ const damage = carried?.damage && fresh ? unionRect(carried.damage, fresh) : fresh;
101
+ this.pending = {
102
+ bgra: image.toBitmap(),
103
+ width: size.width,
104
+ height: size.height,
105
+ damage,
106
+ whole: wholeSurface || (carried?.whole ?? false) || (stale != null && !carried),
107
+ };
108
+ if (!this.scheduled) {
109
+ this.scheduled = true;
110
+ setImmediate(() => this.drain());
111
+ }
112
+ return true;
113
+ }
114
+ drain() {
115
+ this.scheduled = false;
116
+ const pending = this.pending;
117
+ this.pending = null;
118
+ if (!pending)
119
+ return;
120
+ this.surface.present({
121
+ bgra: pending.bgra,
122
+ width: pending.width,
123
+ height: pending.height,
124
+ damage: pending.whole ? undefined : pending.damage,
125
+ });
126
+ }
127
+ }
128
+ exports.BitmapPresenter = BitmapPresenter;