@domicile-desktop/manganese 0.0.0-alpha-e1457b57e6b2 → 0.0.0-alpha-e2ddcb67524d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "dependencies": {
3
3
  "@cprussin/option-result": "^2.0.1",
4
- "@domicile-desktop/component-library": "0.0.0-alpha-e1457b57e6b2",
5
- "@domicile-desktop/sdk": "0.0.0-alpha-e1457b57e6b2",
6
- "@domicile-desktop/system-apps": "0.0.0-alpha-e1457b57e6b2",
7
- "@domicile-desktop/system-audio": "0.0.0-alpha-e1457b57e6b2",
8
- "@domicile-desktop/system-backlight": "0.0.0-alpha-e1457b57e6b2",
9
- "@domicile-desktop/system-battery": "0.0.0-alpha-e1457b57e6b2",
10
- "@domicile-desktop/system-bluetooth": "0.0.0-alpha-e1457b57e6b2",
11
- "@domicile-desktop/system-network": "0.0.0-alpha-e1457b57e6b2",
4
+ "@domicile-desktop/component-library": "0.0.0-alpha-e2ddcb67524d",
5
+ "@domicile-desktop/sdk": "0.0.0-alpha-e2ddcb67524d",
6
+ "@domicile-desktop/system-apps": "0.0.0-alpha-e2ddcb67524d",
7
+ "@domicile-desktop/system-audio": "0.0.0-alpha-e2ddcb67524d",
8
+ "@domicile-desktop/system-backlight": "0.0.0-alpha-e2ddcb67524d",
9
+ "@domicile-desktop/system-battery": "0.0.0-alpha-e2ddcb67524d",
10
+ "@domicile-desktop/system-bluetooth": "0.0.0-alpha-e2ddcb67524d",
11
+ "@domicile-desktop/system-network": "0.0.0-alpha-e2ddcb67524d",
12
12
  "@phosphor-icons/react": "^2.1.10",
13
13
  "lowlight": "^3.3.0",
14
14
  "react": "^19.2.8",
@@ -77,5 +77,5 @@
77
77
  "test:unit": "bun test"
78
78
  },
79
79
  "type": "module",
80
- "version": "0.0.0-alpha-e1457b57e6b2"
80
+ "version": "0.0.0-alpha-e2ddcb67524d"
81
81
  }
@@ -2,7 +2,8 @@
2
2
  //
3
3
  // - Commands use sway's syntax where sway has one (`focus left`, `layout
4
4
  // tabbed`), so sway bindings can be copied over. `lock`, `launcher`,
5
- // `clipboard` and `resize grow <direction>` are manganese's own.
5
+ // `clipboard`, `screenshot` and `resize grow <direction>` are manganese's
6
+ // own.
6
7
  // - `exec <argv…>` runs the argv directly, not through `sh -c` as sway does.
7
8
  // - An unknown command is a config error, so it returns an `Err`, not a throw.
8
9
  //
@@ -37,6 +38,8 @@ const COMMANDS: ReadonlyMap<string, Action> = new Map<string, Action>([
37
38
  ["launcher", WindowAction.LauncherToggled()],
38
39
  // Clipboard history; a toggle, like the launcher.
39
40
  ["clipboard", WindowAction.ClipboardToggled()],
41
+ // The area is picked in the screenshot dialog.
42
+ ["screenshot", WindowAction.ScreenshotTaken()],
40
43
  ...DIRECTIONS.map(
41
44
  ([word, way]): Command => [`focus ${word}`, WindowAction.FocusStepped(way)],
42
45
  ),
@@ -25,6 +25,8 @@ export const lock = () => command("lock");
25
25
  export const launcher = () => command("launcher");
26
26
  /** Toggle the clipboard history. */
27
27
  export const clipboard = () => command("clipboard");
28
+ /** Take a screenshot, picking the area in a dialog. */
29
+ export const screenshot = () => command("screenshot");
28
30
  /** Move the focus, or focus the parent or child container. */
29
31
  export const focus = (to: Way | "parent" | "child" | "mode_toggle") =>
30
32
  command("focus", to);
@@ -109,6 +111,7 @@ export const DEFAULT_KEYBINDINGS: ModeKeybindings = {
109
111
  "Meta+Tab": focus("mode_toggle"),
110
112
  "Meta+v": split("v"),
111
113
  "Meta+w": layout("tabbed"),
114
+ Print: screenshot(),
112
115
  ...everyWay("", focus),
113
116
  ...everyWay("Shift+", move),
114
117
  ...everyWorkspace("", workspace),
@@ -16,7 +16,6 @@ import { isLeaving } from "./window-motion";
16
16
  import {
17
17
  bottomCornerStyles,
18
18
  clickThroughStyles,
19
- draggingStyles,
20
19
  edgeStyles,
21
20
  movingStyles,
22
21
  placedAt,
@@ -218,7 +217,6 @@ export const AppWindow = ({
218
217
  (clickThrough || leaving) && clickThroughStyles,
219
218
  // A dragged window gets a new box on every pointer move, so it skips
220
219
  // easing. Colors still ease; see `settlingStyles`.
221
- dragging && draggingStyles,
222
220
  settlingStyles({ dragging }),
223
221
  )}
224
222
  // Exposes the motion on the element for tests and debugging.
@@ -34,7 +34,6 @@ import { isLeaving } from "./window-motion";
34
34
  import {
35
35
  bottomCornerStyles,
36
36
  clickThroughStyles,
37
- draggingStyles,
38
37
  edgeStyles,
39
38
  movingStyles,
40
39
  placedAt,
@@ -415,7 +414,6 @@ export const BrowserWindow = ({
415
414
  (clickThrough || leaving) && clickThroughStyles,
416
415
  // A dragged window gets a new box on every pointer move, so it skips
417
416
  // easing. Colors still ease; see `settlingStyles`.
418
- dragging && draggingStyles,
419
417
  settlingStyles({ dragging }),
420
418
  )}
421
419
  // Exposes the motion on the element for tests and debugging.
@@ -3,7 +3,6 @@ import type { Rect } from "../rect";
3
3
  import type { Restack } from "../restacking";
4
4
  import type { WindowMotion } from "../window-motion";
5
5
  import {
6
- draggingStyles,
7
6
  movingStyles,
8
7
  placedAt,
9
8
  scaledAbout,
@@ -14,7 +13,7 @@ import {
14
13
  type Props = {
15
14
  /** The stacking depth of the window casting it. */
16
15
  depth: number;
17
- /** Whether the window is being dragged, which makes it translucent. */
16
+ /** Whether the window is being dragged, which stops its box easing. */
18
17
  dragging: boolean;
19
18
  /** The window's whole box, bar included. */
20
19
  frame: Rect;
@@ -44,7 +43,6 @@ export const FloatShadow = ({
44
43
  className={cx(
45
44
  shadowStyles,
46
45
  movingStyles({ motion }),
47
- dragging && draggingStyles,
48
46
  settlingStyles({ dragging }),
49
47
  )}
50
48
  data-shadow
@@ -57,9 +55,8 @@ export const FloatShadow = ({
57
55
  );
58
56
 
59
57
  /**
60
- * An outer `box-shadow` only, which is never drawn under its own box, so a
61
- * translucent dragged window shows the desktop, not its shadow. Rounded like
62
- * the frame, and ignores the pointer.
58
+ * An outer `box-shadow` only, which is never drawn under its own box. Rounded
59
+ * like the frame, and ignores the pointer.
63
60
  */
64
61
  const shadowStyles = css({
65
62
  borderRadius: "lg",
@@ -3,7 +3,7 @@ import type {
3
3
  DomicileHost,
4
4
  DomicileWindow,
5
5
  } from "@domicile-desktop/sdk/domicile-host";
6
- import { system } from "@domicile-desktop/sdk/system";
6
+ import { SystemErrorKind, system } from "@domicile-desktop/sdk/system";
7
7
  import { useCallback, useEffect, useMemo, useReducer, useRef } from "react";
8
8
  import { openFileCommand } from "../launcher/open-file";
9
9
  import type { PlacedScreen } from "../screens/screen-toward";
@@ -64,6 +64,9 @@ export const useWindows = (
64
64
  if (action.kind === WindowActionKind.DeskLocked) {
65
65
  domicile.lock();
66
66
  }
67
+ if (action.kind === WindowActionKind.ScreenshotTaken) {
68
+ takeScreenshot(domicile);
69
+ }
67
70
  if (action.kind === WindowActionKind.FileOpened) {
68
71
  openFile(files, action.path)
69
72
  .then((argv) => {
@@ -172,3 +175,26 @@ const placedOf = (displays: readonly Display[]): readonly PlacedScreen[] =>
172
175
  box: { height: size[1], width: size[0], x: position[0], y: position[1] },
173
176
  name,
174
177
  }));
178
+
179
+ /** Takes a screenshot, logging any failure but a dismissed dialog. */
180
+ const takeScreenshot = (domicile: DomicileHost) => {
181
+ system(domicile)
182
+ .screenshot()
183
+ .then((taken) => {
184
+ taken.match({
185
+ Err: (error) => {
186
+ if (error.kind !== SystemErrorKind.Canceled) {
187
+ // biome-ignore lint/suspicious/noConsole: surfacing a failed screenshot
188
+ console.error("The screenshot was not saved", error);
189
+ }
190
+ },
191
+ // The PNG is under `$XDG_PICTURES_DIR/Screenshots/`, as a portal
192
+ // screenshot's is, which says nothing either.
193
+ Ok: () => undefined,
194
+ });
195
+ })
196
+ .catch((error: unknown) => {
197
+ // biome-ignore lint/suspicious/noConsole: surfacing a broken system call
198
+ console.error("The screenshot was not taken", error);
199
+ });
200
+ };
@@ -311,6 +311,7 @@ export enum WindowActionKind {
311
311
  PopupPlaced,
312
312
  ScratchpadShown,
313
313
  ScreenHovered,
314
+ ScreenshotTaken,
314
315
  ScreensDescribed,
315
316
  SplitToggled,
316
317
  WindowClosed,
@@ -567,6 +568,16 @@ export const WindowAction = {
567
568
  screens,
568
569
  }),
569
570
 
571
+ /**
572
+ * The user asked for a screenshot.
573
+ *
574
+ * Changes no state; the compositor freezes the desk and `<PortalDialogs />`
575
+ * draws the dialog.
576
+ */
577
+ ScreenshotTaken: () => ({
578
+ kind: WindowActionKind.ScreenshotTaken as const,
579
+ }),
580
+
570
581
  /** `layout toggle split`. */
571
582
  SplitToggled: () => ({ kind: WindowActionKind.SplitToggled as const }),
572
583
 
@@ -851,6 +862,10 @@ const reduceAction = (
851
862
  // The compositor locks it and the host says so.
852
863
  return state;
853
864
  }
865
+ case WindowActionKind.ScreenshotTaken: {
866
+ // The compositor takes it, through the portal dialog.
867
+ return state;
868
+ }
854
869
  case WindowActionKind.CommandExecuted: {
855
870
  // The compositor spawns it and the host announces the window it opens.
856
871
  return state;
@@ -36,12 +36,6 @@ export const placedAt = (rect: Rect, depth: number): CSSProperties => ({
36
36
  zIndex: depth,
37
37
  });
38
38
 
39
- /**
40
- * A window being dragged. The window is a compositor layer, so the opacity
41
- * applies to the client's buffer too.
42
- */
43
- export const draggingStyles = css({ opacity: 0.6 });
44
-
45
39
  /**
46
40
  * The border that makes a window's edge visible. Focus is shown by `FocusGlow`,
47
41
  * not by this border's color.
@@ -208,8 +202,7 @@ export const movingStyles = cva({
208
202
  * `placement.ts`).
209
203
  * - Colors: always eased; focus follows the pointer, so snapping would
210
204
  * flicker.
211
- * - Opacity: always eased, so the drag fade does not blink at either end of
212
- * a drag.
205
+ * - Opacity: always eased, so `FocusGlow` fades rather than blinks.
213
206
  *
214
207
  * One recipe because two rules setting `transition` on one element race on
215
208
  * Panda's emit order.
@@ -11752,10 +11752,6 @@
11752
11752
  cursor: nwse-resize;
11753
11753
  }
11754
11754
 
11755
- .jLqGsf {
11756
- opacity: 0.6;
11757
- }
11758
-
11759
11755
  .hZnhGo {
11760
11756
  border-end-start-radius: var(--dxfumK);
11761
11757
  }