@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 +9 -9
- package/src/keyboard/command.ts +4 -1
- package/src/keyboard/commands.ts +3 -0
- package/src/window-management/AppWindow.tsx +0 -2
- package/src/window-management/BrowserWindow.tsx +0 -2
- package/src/window-management/floating/FloatShadow.tsx +3 -6
- package/src/window-management/useWindows.ts +27 -1
- package/src/window-management/window-state.ts +15 -0
- package/src/window-management/window-styles.ts +1 -8
- package/styled-system/styles.css +0 -4
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-
|
|
5
|
-
"@domicile-desktop/sdk": "0.0.0-alpha-
|
|
6
|
-
"@domicile-desktop/system-apps": "0.0.0-alpha-
|
|
7
|
-
"@domicile-desktop/system-audio": "0.0.0-alpha-
|
|
8
|
-
"@domicile-desktop/system-backlight": "0.0.0-alpha-
|
|
9
|
-
"@domicile-desktop/system-battery": "0.0.0-alpha-
|
|
10
|
-
"@domicile-desktop/system-bluetooth": "0.0.0-alpha-
|
|
11
|
-
"@domicile-desktop/system-network": "0.0.0-alpha-
|
|
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-
|
|
80
|
+
"version": "0.0.0-alpha-e2ddcb67524d"
|
|
81
81
|
}
|
package/src/keyboard/command.ts
CHANGED
|
@@ -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
|
|
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
|
),
|
package/src/keyboard/commands.ts
CHANGED
|
@@ -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
|
|
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
|
|
61
|
-
*
|
|
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
|
|
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.
|
package/styled-system/styles.css
CHANGED
|
@@ -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
|
}
|