buninu-browser 0.3.0 → 0.5.0
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/LICENSES/jsmdcui.txt +22 -0
- package/README.md +40 -4
- package/frontends/wayland/LICENSE-land +21 -0
- package/frontends/wayland/README.md +152 -0
- package/frontends/wayland/casty/LICENSE +21 -0
- package/frontends/wayland/casty/bookmarks.js +32 -0
- package/frontends/wayland/casty/click.js +96 -0
- package/frontends/wayland/casty/commands.js +61 -0
- package/frontends/wayland/casty/config.js +45 -0
- package/frontends/wayland/casty/download-directory.js +28 -0
- package/frontends/wayland/casty/download.js +49 -0
- package/frontends/wayland/casty/hints.js +334 -0
- package/frontends/wayland/casty/keys.js +56 -0
- package/frontends/wayland/casty/page-commands.js +80 -0
- package/frontends/wayland/casty/prompt-width.js +148 -0
- package/frontends/wayland/casty/urlbar.js +606 -0
- package/frontends/wayland/client.js +88 -0
- package/frontends/wayland/clipboard.js +80 -0
- package/frontends/wayland/index.js +130 -0
- package/frontends/wayland/input.js +75 -0
- package/frontends/wayland/protocol.js +55 -0
- package/frontends/wayland/protocols/wayland.xml +3248 -0
- package/frontends/wayland/protocols/xdg-shell.xml +1415 -0
- package/frontends/wayland/transport.js +120 -0
- package/frontends/wayland/urlbar.js +162 -0
- package/index.js +28 -1
- package/lib/audio/shared-connection.js +31 -0
- package/lib/cdp-server.js +15 -2
- package/lib/clipboard-command.js +10 -0
- package/lib/clipboard-powershell.js +22 -0
- package/lib/clipboard.js +37 -2
- package/lib/document-types.js +11 -0
- package/lib/headless-shell.js +54 -12
- package/lib/layout/text-layout.js +17 -9
- package/lib/paint/display-list.js +6 -1
- package/lib/qml/README.md +1427 -0
- package/lib/qml/builtins.js +771 -0
- package/lib/qml/canvas-dom.js +115 -0
- package/lib/qml/canvas.js +76 -0
- package/lib/qml/document.js +1199 -0
- package/lib/qml/fonts.js +69 -0
- package/lib/qml/format.js +9 -0
- package/lib/qml/host.js +352 -0
- package/lib/qml/images.js +199 -0
- package/lib/qml/launcher.js +132 -0
- package/lib/qml/loader.js +521 -0
- package/lib/qml/media-renderer.js +49 -0
- package/lib/qml/media.js +86 -0
- package/lib/qml/models.js +622 -0
- package/lib/qml/parser.js +381 -0
- package/lib/qml/qs +5 -0
- package/lib/qml/qscasty +3 -0
- package/lib/qml/qsheadless +3 -0
- package/lib/qml/qswayland +3 -0
- package/lib/qml/reactive.js +182 -0
- package/lib/qml/runtime.js +3603 -0
- package/lib/qml/shader/fragment.js +83 -0
- package/lib/qml/shader/qsb.js +27 -0
- package/lib/qml/shader/renderer.js +39 -0
- package/lib/qml/shader/runtime.js +61 -0
- package/lib/qml/shapes.js +251 -0
- package/lib/qml/shortcuts.js +65 -0
- package/lib/qml/text.js +109 -0
- package/lib/qml/textures.js +126 -0
- package/lib/qml/wayland-clipboard.js +32 -0
- package/lib/qml/window-constraints.js +16 -0
- package/lib/qml/worker-thread.js +70 -0
- package/lib/render-tree/index.js +16 -1
- package/lib/renderer/bindings.js +16 -1
- package/lib/renderer/canvas-2d.js +29 -0
- package/lib/renderer/document-selection.js +19 -0
- package/lib/renderer/host.js +45 -17
- package/lib/renderer/main.js +21 -6
- package/lib/renderer/page-realm.js +20 -10
- package/lib/renderer/page-renderer.js +497 -42
- package/lib/renderer/pointer-move.js +5 -3
- package/lib/renderer/render-interval.js +9 -0
- package/lib/renderer/text-input-paint.js +54 -0
- package/lib/renderer/text-input.js +57 -0
- package/lib/style/computed-style.js +10 -4
- package/package.json +1 -1
- package/test/audio-connection-lifetime.test.js +46 -0
- package/test/canvas-paint.test.js +8 -0
- package/test/clipboard.test.js +19 -0
- package/test/computed-style.test.js +12 -0
- package/test/document-selection.test.js +27 -0
- package/test/double-click.test.js +85 -0
- package/test/fixtures/canvas-damage.js +40 -0
- package/test/fixtures/fake-renderer.js +1 -0
- package/test/fixtures/flea-helpers/Dockerfile +36 -0
- package/test/fixtures/flea-helpers/bat.mjs +43 -0
- package/test/fixtures/flea-helpers/bin/bat +3 -0
- package/test/fixtures/flea-helpers/bin/bwrap +10 -0
- package/test/fixtures/flea-helpers/bin/bwrap-real-filter +9 -0
- package/test/fixtures/flea-helpers/bin/glow +3 -0
- package/test/fixtures/flea-helpers/bin/qs +3 -0
- package/test/fixtures/flea-helpers/bin/unsupported +3 -0
- package/test/fixtures/flea-helpers/check-highlighting.mjs +47 -0
- package/test/fixtures/flea-helpers/check-media.mjs +29 -0
- package/test/fixtures/flea-helpers/check-preview.mjs +27 -0
- package/test/fixtures/flea-helpers/check.mjs +36 -0
- package/test/fixtures/flea-helpers/highlight-cases.json +227 -0
- package/test/fixtures/flea-helpers/source-mime.xml +28 -0
- package/test/fixtures/flea-helpers/syntax-compat.mjs +23 -0
- package/test/fixtures/flea-thumbnail-stub/flea-placeholder.thumbnailer +4 -0
- package/test/fixtures/flea-thumbnail-stub/flea-thumbnail-stub +3 -0
- package/test/fixtures/omastorm-helpers/Dockerfile +35 -0
- package/test/fixtures/omastorm-helpers/check.mjs +56 -0
- package/test/fixtures/omastorm-helpers/launch.mjs +24 -0
- package/test/fixtures/omastorm-helpers/prepare.mjs +17 -0
- package/test/fixtures/omastorm-helpers/runtime.mjs +32 -0
- package/test/fixtures/pointer-paint-batching.js +23 -0
- package/test/fixtures/qml/flea/EscapeHint.qml +11 -0
- package/test/fixtures/qml/flea/LICENSE +21 -0
- package/test/fixtures/qml/flea/README.md +25 -0
- package/test/fixtures/qml/flea/Theme.qml +8 -0
- package/test/fixtures/qml/flea/demo.qml +24 -0
- package/test/fixtures/qml/flea/qmldir +3 -0
- package/test/fixtures/qml/flea-theme/LICENSE-Flea +21 -0
- package/test/fixtures/qml/flea-theme/LICENSE-Omarchy +20 -0
- package/test/fixtures/qml/flea-theme/README.md +70 -0
- package/test/fixtures/qml/flea-theme/button.qml +17 -0
- package/test/fixtures/qml/flea-theme/demo.qml +27 -0
- package/test/fixtures/qml/flea-theme/field.qml +21 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/BorderGeometry.js +373 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Color.qml +258 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/I18n.qml +118 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Numbers.js +19 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Plural.js +91 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Style.qml +561 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Util.qml +188 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/qmldir +13 -0
- package/test/fixtures/qml/flea-theme/segment.qml +17 -0
- package/test/fixtures/qml/flea-theme/settings.qml +58 -0
- package/test/fixtures/qml/flea-theme/text-metrics.qml +10 -0
- package/test/fixtures/qml/flea-theme/ui/DialogButton.qml +150 -0
- package/test/fixtures/qml/flea-theme/ui/DialogField.qml +147 -0
- package/test/fixtures/qml/flea-theme/ui/EscapeHint.qml +11 -0
- package/test/fixtures/qml/flea-theme/ui/Glass.qml +114 -0
- package/test/fixtures/qml/flea-theme/ui/Glyph.qml +54 -0
- package/test/fixtures/qml/flea-theme/ui/GlyphSolid.qml +22 -0
- package/test/fixtures/qml/flea-theme/ui/Reveal.qml +54 -0
- package/test/fixtures/qml/flea-theme/ui/SettingsRuler.qml +85 -0
- package/test/fixtures/qml/flea-theme/ui/SettingsSegment.qml +85 -0
- package/test/fixtures/qml/flea-theme/ui/StableModel.qml +89 -0
- package/test/fixtures/qml/flea-theme/ui/Theme.qml +460 -0
- package/test/fixtures/qml/flea-theme/ui/ThemeColors.qml +43 -0
- package/test/fixtures/qml/flea-theme/ui/ViewState.qml +565 -0
- package/test/fixtures/qml/flea-theme/ui/js/Anchor.js +379 -0
- package/test/fixtures/qml/flea-theme/ui/js/AnchorHold.js +162 -0
- package/test/fixtures/qml/flea-theme/ui/js/Archive.js +157 -0
- package/test/fixtures/qml/flea-theme/ui/js/BackReturn.js +110 -0
- package/test/fixtures/qml/flea-theme/ui/js/Buttons.js +54 -0
- package/test/fixtures/qml/flea-theme/ui/js/ColumnMenu.js +111 -0
- package/test/fixtures/qml/flea-theme/ui/js/Columns.js +298 -0
- package/test/fixtures/qml/flea-theme/ui/js/Contrast.js +157 -0
- package/test/fixtures/qml/flea-theme/ui/js/Density.js +44 -0
- package/test/fixtures/qml/flea-theme/ui/js/DirSizes.js +129 -0
- package/test/fixtures/qml/flea-theme/ui/js/ExtThumbs.js +115 -0
- package/test/fixtures/qml/flea-theme/ui/js/Filter.js +284 -0
- package/test/fixtures/qml/flea-theme/ui/js/FolderSorts.js +108 -0
- package/test/fixtures/qml/flea-theme/ui/js/Format.js +305 -0
- package/test/fixtures/qml/flea-theme/ui/js/Icons.js +206 -0
- package/test/fixtures/qml/flea-theme/ui/js/Input.js +39 -0
- package/test/fixtures/qml/flea-theme/ui/js/KeyName.js +64 -0
- package/test/fixtures/qml/flea-theme/ui/js/Keymap.js +370 -0
- package/test/fixtures/qml/flea-theme/ui/js/Kinds.js +145 -0
- package/test/fixtures/qml/flea-theme/ui/js/Lists.js +11 -0
- package/test/fixtures/qml/flea-theme/ui/js/MakeDefault.js +186 -0
- package/test/fixtures/qml/flea-theme/ui/js/Match.js +27 -0
- package/test/fixtures/qml/flea-theme/ui/js/Material.js +109 -0
- package/test/fixtures/qml/flea-theme/ui/js/Menu.js +513 -0
- package/test/fixtures/qml/flea-theme/ui/js/Motion.js +16 -0
- package/test/fixtures/qml/flea-theme/ui/js/Mounts.js +320 -0
- package/test/fixtures/qml/flea-theme/ui/js/MouseNav.js +13 -0
- package/test/fixtures/qml/flea-theme/ui/js/Nav.js +328 -0
- package/test/fixtures/qml/flea-theme/ui/js/Palette.js +33 -0
- package/test/fixtures/qml/flea-theme/ui/js/Places.js +236 -0
- package/test/fixtures/qml/flea-theme/ui/js/Protocols.js +296 -0
- package/test/fixtures/qml/flea-theme/ui/js/RecentMode.js +154 -0
- package/test/fixtures/qml/flea-theme/ui/js/Search.js +396 -0
- package/test/fixtures/qml/flea-theme/ui/js/Settings.js +476 -0
- package/test/fixtures/qml/flea-theme/ui/js/SettingsAbout.js +99 -0
- package/test/fixtures/qml/flea-theme/ui/js/SettingsShelf.js +52 -0
- package/test/fixtures/qml/flea-theme/ui/js/Sort.js +127 -0
- package/test/fixtures/qml/flea-theme/ui/js/StateWords.js +42 -0
- package/test/fixtures/qml/flea-theme/ui/js/Swap.js +166 -0
- package/test/fixtures/qml/flea-theme/ui/js/TextSize.js +107 -0
- package/test/fixtures/qml/flea-theme/ui/js/Thumbs.js +158 -0
- package/test/fixtures/qml/flea-theme/ui/js/UiState.js +438 -0
- package/test/fixtures/qml/flea-theme/ui/js/Update.js +132 -0
- package/test/fixtures/qml/flea-theme/ui/js/UserDirs.js +56 -0
- package/test/fixtures/qml/flea-theme/ui/qmldir +227 -0
- package/test/fixtures/qml/hello.qml +26 -0
- package/test/fixtures/qml/imports/Demo/Toolkit/VersionLabel.qml +2 -0
- package/test/fixtures/qml/imports/Demo/Toolkit/VersionLabelNew.qml +2 -0
- package/test/fixtures/qml/imports/Demo/Toolkit/qmldir +3 -0
- package/test/fixtures/qml/imports/components/Badge.qml +15 -0
- package/test/fixtures/qml/imports/logic/base.js +2 -0
- package/test/fixtures/qml/imports/logic/counter.js +4 -0
- package/test/fixtures/qml/imports/logic/math.js +3 -0
- package/test/fixtures/qml/imports/logic/shared.js +3 -0
- package/test/fixtures/qml/imports/main.qml +21 -0
- package/test/fixtures/qml/imports/theme/Theme.qml +8 -0
- package/test/fixtures/qml/imports/theme/qmldir +2 -0
- package/test/fixtures/qml/multiply.qml +61 -0
- package/test/fixtures/qml-canvas-dom.js +90 -0
- package/test/fixtures/qml-fonts/main.qml +10 -0
- package/test/fixtures/qml-locale/check.mjs +6 -0
- package/test/fixtures/qml-locale/main.qml +8 -0
- package/test/fixtures/qml-media-audio.js +39 -0
- package/test/fixtures/qml-shader/grab.qml +14 -0
- package/test/fixtures/qml-shader/gradient.frag +5 -0
- package/test/fixtures/qml-shader/main.qml +14 -0
- package/test/fixtures/qml-shader/texture-grab.qml +25 -0
- package/test/fixtures/qml-shader/texture-size.frag +5 -0
- package/test/fixtures/qml-shader-check.mjs +24 -0
- package/test/fixtures/title-no-paint.js +20 -0
- package/test/helpers/flea-sandbox.js +48 -0
- package/test/helpers/quickshell-fixture.js +125 -0
- package/test/html-clipboard-wayland.test.js +47 -0
- package/test/index.test.js +13 -0
- package/test/manual-casty-without-qml.js +87 -0
- package/test/manual-double-click.html +21 -0
- package/test/manual-flea-application.js +49 -0
- package/test/manual-flea-binary.js +62 -0
- package/test/manual-flea-qml.js +9 -0
- package/test/manual-flea-settings.js +40 -0
- package/test/manual-flea-theme.js +40 -0
- package/test/manual-mouse-buttons.html +18 -0
- package/test/manual-omastorm-engine.mjs +19 -0
- package/test/manual-omastorm-shaders.mjs +28 -0
- package/test/manual-omastorm-software.mjs +25 -0
- package/test/manual-pointer-scroll.html +43 -0
- package/test/manual-qml-removal.js +46 -0
- package/test/manual-without-qml.js +45 -0
- package/test/pointer-drag.test.js +104 -0
- package/test/qml-canvas-dom.test.js +37 -0
- package/test/qml-canvas.test.js +21 -0
- package/test/qml-clipboard-bridge.test.js +25 -0
- package/test/qml-clipboard-wayland.test.js +40 -0
- package/test/qml-connections-timing.test.js +95 -0
- package/test/qml-controls-window.test.js +182 -0
- package/test/qml-dynamic.test.js +401 -0
- package/test/qml-flea-app.test.js +146 -0
- package/test/qml-flea-backend.test.js +78 -0
- package/test/qml-flea-columns-backend.test.js +38 -0
- package/test/qml-flea-compile.test.js +78 -0
- package/test/qml-flea-launcher.test.js +88 -0
- package/test/qml-flea-markdown-backend.test.js +31 -0
- package/test/qml-flea-media.test.js +28 -0
- package/test/qml-flea-navigation-backend.test.js +35 -0
- package/test/qml-flea-navigation-timing.test.js +147 -0
- package/test/qml-flea-preview-backend.test.js +53 -0
- package/test/qml-flea-previews.test.js +163 -0
- package/test/qml-flea-rows.test.js +101 -0
- package/test/qml-flea-textures.test.js +59 -0
- package/test/qml-flea-view-switch.test.js +33 -0
- package/test/qml-flea-wayland.test.js +68 -0
- package/test/qml-flea.test.js +34 -0
- package/test/qml-fonts.test.js +31 -0
- package/test/qml-grid-multiline.test.js +48 -0
- package/test/qml-host.test.js +238 -0
- package/test/qml-imports.test.js +102 -0
- package/test/qml-inherited-handlers.test.js +51 -0
- package/test/qml-input-selection.test.js +66 -0
- package/test/qml-interactions.test.js +309 -0
- package/test/qml-language.test.js +167 -0
- package/test/qml-launcher.test.js +54 -0
- package/test/qml-layout-text.test.js +205 -0
- package/test/qml-locale.test.js +45 -0
- package/test/qml-media.test.js +63 -0
- package/test/qml-nonvisual-visible.test.js +19 -0
- package/test/qml-persisted-delegates.test.js +45 -0
- package/test/qml-quickshell-controls.test.js +65 -0
- package/test/qml-quickshell-settings.test.js +62 -0
- package/test/qml-repeater.test.js +72 -0
- package/test/qml-shader-runtime.test.js +6 -0
- package/test/qml-shortcuts.test.js +39 -0
- package/test/qml-socket.test.js +60 -0
- package/test/qml-software-shader.test.js +55 -0
- package/test/qml-style-updates.test.js +124 -0
- package/test/qml-textures.test.js +66 -0
- package/test/qml-views.test.js +332 -0
- package/test/qml-window-update.test.js +36 -0
- package/test/qml-worker.test.js +69 -0
- package/test/qml.test.js +83 -0
- package/test/render-interval.test.js +33 -0
- package/test/renderer-host.test.js +11 -0
- package/test/text-input-pointer.test.js +31 -0
- package/test/text-input-scroll.test.js +29 -0
- package/test/text-input.test.js +47 -0
- package/test/title-no-paint.test.js +6 -0
- package/test/wayland-frontend.test.js +83 -0
- package/test/wayland-scroll.test.js +40 -0
- package/test/wayland-urlbar.test.js +61 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
pragma Singleton
|
|
2
|
+
import QtQuick
|
|
3
|
+
import qs.Commons as Commons
|
|
4
|
+
import Quickshell
|
|
5
|
+
import Quickshell.Hyprland
|
|
6
|
+
import Quickshell.Io
|
|
7
|
+
|
|
8
|
+
// Shared structural style tokens for the shell. Color is the palette
|
|
9
|
+
// singleton; Style holds everything else themes can influence — corner
|
|
10
|
+
// rounding, gap to screen edges, state affordances, spacing, typography
|
|
11
|
+
// scale, and bar dimensions.
|
|
12
|
+
//
|
|
13
|
+
// `cornerRadius` mirrors Hyprland's `decoration:rounding`. `gapsOut` is
|
|
14
|
+
// half of Hyprland's `general:gaps_out` — Hyprland's value works well as
|
|
15
|
+
// a window-to-window gap but feels too cavernous when used as the
|
|
16
|
+
// distance from a panel/notification to the screen edge, so the shell
|
|
17
|
+
// halves it. Themes and user Hyprland config own those values; the
|
|
18
|
+
// shell picks them up by re-running `hyprctl getoption` on startup and
|
|
19
|
+
// after theme IPC applies a theme.
|
|
20
|
+
//
|
|
21
|
+
// Typography, spacing, and bar size come from theme/shell.toml.
|
|
22
|
+
// `[font] base-size` is the rem root; every `Style.font.<token>` derives
|
|
23
|
+
// from it via the scale multipliers below unless the theme pins that
|
|
24
|
+
// specific token. `[spacing] scale` multiplies shared margins, gaps,
|
|
25
|
+
// padding, controls, and panel dimensions while preserving each component's
|
|
26
|
+
// proportions; by default it also tracks `base-size`. `[bar]
|
|
27
|
+
// size-horizontal` / `size-vertical` set the cross-axis dimension for
|
|
28
|
+
// top/bottom and left/right bars at the default 12px font size; by default
|
|
29
|
+
// those dimensions scale with `base-size` so larger fonts don't clip.
|
|
30
|
+
QtObject {
|
|
31
|
+
id: root
|
|
32
|
+
|
|
33
|
+
property int cornerRadius: 0
|
|
34
|
+
property int gapsOut: 5
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------- state tokens
|
|
37
|
+
//
|
|
38
|
+
// Shared interactive-state tokens for every reusable surface in the kit.
|
|
39
|
+
// The vocabulary:
|
|
40
|
+
// normal — idle control chrome
|
|
41
|
+
// hover-cursor — mouse hover OR panel keyboard cursor (`hasCursor`)
|
|
42
|
+
// selected — persistent chosen/current state
|
|
43
|
+
// focus — actual Qt activeFocus, defaulting to hover-cursor
|
|
44
|
+
//
|
|
45
|
+
// Each state has a color token plus fill/border alphas. Color tokens
|
|
46
|
+
// may be palette roles (`foreground`, `accent`, `urgent`, `background`)
|
|
47
|
+
// or hex colors. Set a state's border width to 0 to drop that border.
|
|
48
|
+
property var styleOverrides: ({})
|
|
49
|
+
|
|
50
|
+
function styleRawNum(key) {
|
|
51
|
+
var v = styleOverrides[key]
|
|
52
|
+
var n = Number(v)
|
|
53
|
+
return isFinite(n) ? n : null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function styleNum(key, fallback) {
|
|
57
|
+
var n = styleRawNum(key)
|
|
58
|
+
return n === null ? fallback : n
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function styleAlpha(key, fallback) {
|
|
62
|
+
return Util.clampAlpha(styleNum(key, fallback))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function styleString(key, fallback) {
|
|
66
|
+
var v = styleOverrides[key]
|
|
67
|
+
if (typeof v !== "string") return fallback
|
|
68
|
+
v = v.replace(/^\s+|\s+$/g, "")
|
|
69
|
+
return v.length > 0 ? v : fallback
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
readonly property string normalColorToken: styleString("normal-color", "foreground")
|
|
73
|
+
readonly property string hoverColorToken: styleString("hover-cursor-color", "foreground")
|
|
74
|
+
readonly property string selectedColorToken: styleString("selected-color", "foreground")
|
|
75
|
+
readonly property string pressedColorToken: styleString("pressed-color", hoverColorToken)
|
|
76
|
+
readonly property string focusColorToken: styleString("focus-color", hoverColorToken)
|
|
77
|
+
readonly property string selectionColorToken: styleString("selection-color", "foreground")
|
|
78
|
+
|
|
79
|
+
readonly property int normalBorderWidth: Math.max(0, Math.round(styleNum("normal-border-width", 1)))
|
|
80
|
+
readonly property int hoverBorderWidth: Math.max(0, Math.round(styleNum("hover-cursor-border-width", normalBorderWidth)))
|
|
81
|
+
readonly property int selectedBorderWidth: Math.max(0, Math.round(styleNum("selected-border-width", 0)))
|
|
82
|
+
readonly property int focusBorderWidth: Math.max(0, Math.round(styleNum("focus-border-width", hoverBorderWidth)))
|
|
83
|
+
|
|
84
|
+
readonly property real normalFillAlpha: styleAlpha("normal-fill-alpha", 0.04)
|
|
85
|
+
readonly property real hoverFillAlpha: styleAlpha("hover-cursor-fill-alpha", 0.08)
|
|
86
|
+
readonly property real selectedFillAlpha: styleAlpha("selected-fill-alpha", 0.18)
|
|
87
|
+
readonly property real pressedFillAlpha: styleAlpha("pressed-fill-alpha", 0.22)
|
|
88
|
+
readonly property real focusFillAlpha: styleAlpha("focus-fill-alpha", hoverFillAlpha)
|
|
89
|
+
readonly property real selectionFillAlpha: styleAlpha("selection-fill-alpha", 0.35)
|
|
90
|
+
|
|
91
|
+
readonly property real normalBorderAlpha: styleAlpha("normal-border-alpha", 0.4)
|
|
92
|
+
readonly property real hoverBorderAlpha: styleAlpha("hover-cursor-border-alpha", 0.25)
|
|
93
|
+
readonly property real selectedBorderAlpha: styleAlpha("selected-border-alpha", 1.0)
|
|
94
|
+
readonly property real focusBorderAlpha: styleAlpha("focus-border-alpha", hoverBorderAlpha)
|
|
95
|
+
|
|
96
|
+
function colorFromHex(value, fallback) {
|
|
97
|
+
var s = String(value || "").replace(/^\s+|\s+$/g, "")
|
|
98
|
+
var shortHex = s.match(/^#([0-9A-Fa-f]{3})$/)
|
|
99
|
+
if (shortHex) {
|
|
100
|
+
var sh = shortHex[1]
|
|
101
|
+
return Qt.rgba(
|
|
102
|
+
parseInt(sh.charAt(0) + sh.charAt(0), 16) / 255,
|
|
103
|
+
parseInt(sh.charAt(1) + sh.charAt(1), 16) / 255,
|
|
104
|
+
parseInt(sh.charAt(2) + sh.charAt(2), 16) / 255,
|
|
105
|
+
1)
|
|
106
|
+
}
|
|
107
|
+
var hex = s.match(/^#([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/)
|
|
108
|
+
if (!hex) return fallback
|
|
109
|
+
var h = hex[1]
|
|
110
|
+
return Qt.rgba(
|
|
111
|
+
parseInt(h.substr(0, 2), 16) / 255,
|
|
112
|
+
parseInt(h.substr(2, 2), 16) / 255,
|
|
113
|
+
parseInt(h.substr(4, 2), 16) / 255,
|
|
114
|
+
hex[2] ? parseInt(hex[2], 16) / 255 : 1)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function resolveStateColor(token, foreground, accent, urgent, fallback) {
|
|
118
|
+
var fb = fallback || foreground || Commons.Color.foreground
|
|
119
|
+
var s = String(token || "").replace(/^\s+|\s+$/g, "")
|
|
120
|
+
var role = s.toLowerCase()
|
|
121
|
+
if (role === "foreground" || role === "text") return foreground || Commons.Color.foreground
|
|
122
|
+
if (role === "accent") return accent || Commons.Color.accent
|
|
123
|
+
if (role === "urgent") return urgent || Commons.Color.urgent
|
|
124
|
+
if (role === "background") return Commons.Color.background
|
|
125
|
+
if (role === "transparent") return Qt.rgba(0, 0, 0, 0)
|
|
126
|
+
return colorFromHex(s, fb)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function normalStateColor(foreground, accent, urgent) {
|
|
130
|
+
return resolveStateColor(normalColorToken, foreground, accent, urgent, foreground || Commons.Color.foreground)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function hoverStateColor(foreground, accent, urgent) {
|
|
134
|
+
return resolveStateColor(hoverColorToken, foreground, accent, urgent, foreground || Commons.Color.foreground)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function selectedStateColor(foreground, accent, urgent) {
|
|
138
|
+
return resolveStateColor(selectedColorToken, foreground, accent, urgent, foreground || Commons.Color.foreground)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function pressedStateColor(foreground, accent, urgent) {
|
|
142
|
+
return resolveStateColor(pressedColorToken, foreground, accent, urgent, hoverStateColor(foreground, accent, urgent))
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function focusStateColor(foreground, accent, urgent) {
|
|
146
|
+
var role = String(focusColorToken || "").replace(/^\s+|\s+$/g, "").toLowerCase()
|
|
147
|
+
if (role === "hover" || role === "hover-cursor" || role === "inherit")
|
|
148
|
+
return hoverStateColor(foreground, accent, urgent)
|
|
149
|
+
return resolveStateColor(focusColorToken, foreground, accent, urgent, hoverStateColor(foreground, accent, urgent))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function selectionStateColor(foreground, accent, urgent) {
|
|
153
|
+
return resolveStateColor(selectionColorToken, foreground, accent, urgent, foreground || Commons.Color.foreground)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function normalFillFor(foreground, accent, urgent) { return Util.alpha(normalStateColor(foreground, accent, urgent), normalFillAlpha) }
|
|
157
|
+
function hoverFillFor(foreground, accent, urgent) { return Util.alpha(hoverStateColor(foreground, accent, urgent), hoverFillAlpha) }
|
|
158
|
+
function selectedFillFor(foreground, accent, urgent) { return Util.alpha(selectedStateColor(foreground, accent, urgent), selectedFillAlpha) }
|
|
159
|
+
function pressedFillFor(foreground, accent, urgent) { return Util.alpha(pressedStateColor(foreground, accent, urgent), pressedFillAlpha) }
|
|
160
|
+
function focusFillFor(foreground, accent, urgent) { return Util.alpha(focusStateColor(foreground, accent, urgent), focusFillAlpha) }
|
|
161
|
+
function selectionFillFor(foreground, accent, urgent) { return Util.alpha(selectionStateColor(foreground, accent, urgent), selectionFillAlpha) }
|
|
162
|
+
|
|
163
|
+
function normalBorderFor(foreground, accent, urgent) { return Util.alpha(normalStateColor(foreground, accent, urgent), normalBorderAlpha) }
|
|
164
|
+
function hoverBorderFor(foreground, accent, urgent) { return Util.alpha(hoverStateColor(foreground, accent, urgent), hoverBorderAlpha) }
|
|
165
|
+
function selectedBorderFor(foreground, accent, urgent) { return Util.alpha(selectedStateColor(foreground, accent, urgent), selectedBorderAlpha) }
|
|
166
|
+
function focusBorderFor(foreground, accent, urgent) { return Util.alpha(focusStateColor(foreground, accent, urgent), focusBorderAlpha) }
|
|
167
|
+
|
|
168
|
+
// Composite helpers for the focus > hover > normal priority chain used by
|
|
169
|
+
// every form control surface (TextField, NumberField, Dropdown, Toggle,
|
|
170
|
+
// etc.). Saves callers from re-writing the three-line ternary ladder for
|
|
171
|
+
// fill / border / border-width on every Rectangle background.
|
|
172
|
+
function controlFill(focused, hot, foreground, accent) {
|
|
173
|
+
if (focused) return focusFillFor(foreground, accent)
|
|
174
|
+
if (hot) return hoverFillFor(foreground, accent)
|
|
175
|
+
return normalFillFor(foreground, accent)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function controlBorder(focused, hot, foreground, accent) {
|
|
179
|
+
if (focused) return focusBorderFor(foreground, accent)
|
|
180
|
+
if (hot) return hoverBorderFor(foreground, accent)
|
|
181
|
+
return normalBorderFor(foreground, accent)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function controlBorderWidth(focused, hot) {
|
|
185
|
+
if (focused) return focusBorderWidth
|
|
186
|
+
if (hot) return hoverBorderWidth
|
|
187
|
+
return normalBorderWidth
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Convenience colors resolved against the foundational palette.
|
|
191
|
+
readonly property color normalFill: normalFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
192
|
+
readonly property color hoverFill: hoverFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
193
|
+
readonly property color selectedFill: selectedFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
194
|
+
readonly property color pressedFill: pressedFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
195
|
+
readonly property color focusFillColor: focusFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
196
|
+
readonly property color normalBorderColor: normalBorderFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
197
|
+
readonly property color hoverBorderColor: hoverBorderFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
198
|
+
readonly property color selectedBorderColor: selectedBorderFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
199
|
+
readonly property color focusBorderColor: focusBorderFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
200
|
+
readonly property color selectedAccentFill: Util.alpha(Commons.Color.accent, selectedFillAlpha)
|
|
201
|
+
readonly property color selectionFill: selectionFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
|
202
|
+
|
|
203
|
+
// ---------------------------------------------------------- spacing
|
|
204
|
+
//
|
|
205
|
+
// The spacing scale is the shell equivalent of rem for margins, gaps,
|
|
206
|
+
// and padding. Components keep their existing proportions by asking for
|
|
207
|
+
// the old pixel value through `Style.space(px)` (or `spaceReal(px)` for
|
|
208
|
+
// fractional geometry); themes can make the shell denser or roomier
|
|
209
|
+
// with `[spacing] scale`, or pin individual tokens.
|
|
210
|
+
property real spacingScale: 1.0
|
|
211
|
+
property bool spacingScaleWithFont: true
|
|
212
|
+
property var spacingOverrides: ({})
|
|
213
|
+
readonly property real effectiveSpacingScale: spacingScale * (spacingScaleWithFont ? fontScale : 1)
|
|
214
|
+
|
|
215
|
+
function spaceReal(px) {
|
|
216
|
+
var n = Number(px)
|
|
217
|
+
if (!isFinite(n) || n <= 0) return 0
|
|
218
|
+
return n * effectiveSpacingScale
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function space(px) {
|
|
222
|
+
var n = spaceReal(px)
|
|
223
|
+
if (n <= 0) return 0
|
|
224
|
+
return Math.max(1, Math.round(n))
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function spacingToken(key, fallback) {
|
|
228
|
+
var v = spacingOverrides[key]
|
|
229
|
+
var n = Number(v)
|
|
230
|
+
return (isFinite(n) && n >= 0) ? Math.round(n) : space(fallback)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
readonly property QtObject spacing: QtObject {
|
|
234
|
+
readonly property real scale: root.effectiveSpacingScale
|
|
235
|
+
|
|
236
|
+
readonly property int hairline: root.space(1)
|
|
237
|
+
readonly property int xxs: root.spacingToken("xxs", 2)
|
|
238
|
+
readonly property int xs: root.spacingToken("xs", 3)
|
|
239
|
+
readonly property int sm: root.spacingToken("sm", 4)
|
|
240
|
+
readonly property int md: root.spacingToken("md", 6)
|
|
241
|
+
readonly property int lg: root.spacingToken("lg", 8)
|
|
242
|
+
readonly property int xl: root.spacingToken("xl", 10)
|
|
243
|
+
readonly property int xxl: root.spacingToken("xxl", 12)
|
|
244
|
+
readonly property int xxxl: root.spacingToken("xxxl", 14)
|
|
245
|
+
readonly property int huge: root.spacingToken("huge", 18)
|
|
246
|
+
|
|
247
|
+
readonly property int controlGap: root.spacingToken("control-gap", 8)
|
|
248
|
+
readonly property int controlPaddingX: root.spacingToken("control-padding-x", 10)
|
|
249
|
+
readonly property int controlPaddingY: root.spacingToken("control-padding-y", 6)
|
|
250
|
+
readonly property int inputPaddingY: root.spacingToken("input-padding-y", 7)
|
|
251
|
+
readonly property int controlHeight: root.spacingToken("control-height", 28)
|
|
252
|
+
readonly property int popupRowHeight: root.spacingToken("popup-row-height", 28)
|
|
253
|
+
readonly property int dropdownWidth: root.spacingToken("dropdown-width", 240)
|
|
254
|
+
readonly property int searchableDropdownWidth: root.spacingToken("searchable-dropdown-width", 260)
|
|
255
|
+
readonly property int numberFieldWidth: root.spacingToken("number-field-width", 120)
|
|
256
|
+
readonly property int searchablePopupMinHeight: root.spacingToken("searchable-popup-min-height", 220)
|
|
257
|
+
readonly property int rowGap: root.spacingToken("row-gap", 8)
|
|
258
|
+
readonly property int rowPaddingX: root.spacingToken("row-padding-x", 12)
|
|
259
|
+
readonly property int labelGap: root.spacingToken("label-gap", 4)
|
|
260
|
+
readonly property int panelGap: root.spacingToken("panel-gap", 14)
|
|
261
|
+
readonly property int panelPadding: root.spacingToken("panel-padding", 18)
|
|
262
|
+
readonly property int popupPadding: root.spacingToken("popup-padding", 14)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ---------------------------------------------------------- typography
|
|
266
|
+
//
|
|
267
|
+
// `fontFamily` defaults to "monospace" so the bar and every qs.Ui
|
|
268
|
+
// component follows the fontconfig alias `omarchy-font-set` writes.
|
|
269
|
+
// Themes can override per-token via [font] in shell.toml, but the
|
|
270
|
+
// family stays system-wide.
|
|
271
|
+
property string fontFamily: "monospace"
|
|
272
|
+
|
|
273
|
+
// The concrete family `monospace` resolves to right now, e.g.
|
|
274
|
+
// "JetBrainsMono Nerd Font". Bind `font.family` to `fontFamily` (so the
|
|
275
|
+
// alias path keeps working when the user runs `omarchy font set`), but
|
|
276
|
+
// read `resolvedFontFamily` when you want to *display* what's drawing.
|
|
277
|
+
property string resolvedFontFamily: "monospace"
|
|
278
|
+
|
|
279
|
+
// The only sanity floor is 1px. Themes and users can make this as large
|
|
280
|
+
// as they like; if the shell gets ridiculous, that's their call.
|
|
281
|
+
property int fontBaseSize: 12
|
|
282
|
+
|
|
283
|
+
property var fontOverrides: ({})
|
|
284
|
+
property var barOverrides: ({})
|
|
285
|
+
property bool barScaleWithFont: true
|
|
286
|
+
readonly property real fontScale: Math.max(1 / 12, fontBaseSize / 12)
|
|
287
|
+
|
|
288
|
+
function fontPx(mult) {
|
|
289
|
+
return Math.max(1, Math.round(fontBaseSize * mult))
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function fontToken(key, fallback) {
|
|
293
|
+
var v = fontOverrides[key]
|
|
294
|
+
var n = Number(v)
|
|
295
|
+
return (isFinite(n) && n > 0) ? Math.round(n) : fallback
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function barToken(key, fallback) {
|
|
299
|
+
var v = barOverrides[key]
|
|
300
|
+
var n = Number(v)
|
|
301
|
+
var base = (isFinite(n) && n > 0) ? n : fallback
|
|
302
|
+
if (barScaleWithFont) base *= fontScale
|
|
303
|
+
return Math.max(1, Math.round(base))
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function boolToken(value, fallback) {
|
|
307
|
+
if (value === undefined || value === null) return fallback
|
|
308
|
+
var s = String(value).replace(/^\s+|\s+$/g, "").toLowerCase()
|
|
309
|
+
if (s === "true" || s === "1" || s === "yes" || s === "on") return true
|
|
310
|
+
if (s === "false" || s === "0" || s === "no" || s === "off") return false
|
|
311
|
+
return fallback
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// The menu, polkit, emojis, and clipboard surfaces honor an
|
|
315
|
+
// OMARCHY_MENU_FONT override for users who want a different family on the
|
|
316
|
+
// summoned popups than on the bar. Resolved once at startup; an empty env
|
|
317
|
+
// value falls back to the shared fontconfig alias.
|
|
318
|
+
readonly property string menuFontFamily: {
|
|
319
|
+
var override = Quickshell.env("OMARCHY_MENU_FONT")
|
|
320
|
+
return (override && override.length > 0) ? override : fontFamily
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
readonly property QtObject font: QtObject {
|
|
324
|
+
readonly property string family: root.fontFamily
|
|
325
|
+
readonly property string resolvedFamily: root.resolvedFontFamily
|
|
326
|
+
readonly property string menuFamily: root.menuFontFamily
|
|
327
|
+
readonly property int baseSize: root.fontBaseSize
|
|
328
|
+
|
|
329
|
+
readonly property int caption: root.fontToken("caption", root.fontPx(0.833)) // 10
|
|
330
|
+
readonly property int bodySmall: root.fontToken("body-small", root.fontPx(0.917)) // 11
|
|
331
|
+
readonly property int body: root.fontToken("body", root.fontPx(1.0)) // 12
|
|
332
|
+
readonly property int subtitle: root.fontToken("subtitle", root.fontPx(1.083)) // 13
|
|
333
|
+
readonly property int title: root.fontToken("title", root.fontPx(1.167)) // 14
|
|
334
|
+
readonly property int heading: root.fontToken("heading", root.fontPx(1.333)) // 16
|
|
335
|
+
readonly property int display: root.fontToken("display", root.fontPx(2.0)) // 24
|
|
336
|
+
readonly property int displayLarge: root.fontToken("display-large", root.fontPx(2.333)) // 28
|
|
337
|
+
|
|
338
|
+
readonly property int iconSmall: root.fontToken("icon-small", bodySmall)
|
|
339
|
+
readonly property int icon: root.fontToken("icon", title)
|
|
340
|
+
readonly property int iconLarge: root.fontToken("icon-large", root.fontPx(1.5)) // 18
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
readonly property QtObject bar: QtObject {
|
|
344
|
+
readonly property int sizeHorizontal: root.barToken("size-horizontal", 26)
|
|
345
|
+
readonly property int sizeVertical: root.barToken("size-vertical", 28)
|
|
346
|
+
// Calibrated notch cutout height in logical px, for panels whose real
|
|
347
|
+
// cutout differs from the derived default (see BarModel.notchHeight).
|
|
348
|
+
// 0 means derive it. Physical alignment, so it never scales with font.
|
|
349
|
+
readonly property int notchHeight: {
|
|
350
|
+
var v = Number(root.barOverrides["notch-height"])
|
|
351
|
+
return (isFinite(v) && v > 0) ? Math.round(v) : 0
|
|
352
|
+
}
|
|
353
|
+
readonly property int iconSlot: root.barToken("icon-slot", 27)
|
|
354
|
+
readonly property int iconCanvas: root.barToken("icon-canvas", 16)
|
|
355
|
+
readonly property int iconFont: root.barToken("icon-font", 13)
|
|
356
|
+
readonly property int iconSize: Math.min(iconCanvas, root.barToken("icon-size", 12))
|
|
357
|
+
readonly property int statusSlot: root.barToken("status-slot", 21)
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Off with Hyprland's own animations, as `omarchy toggle animations` turns
|
|
361
|
+
// them off for machines that render on the CPU. Every shell animation runs
|
|
362
|
+
// for Style.duration(ms), which is then 0, so nothing is drawn in between.
|
|
363
|
+
property bool reduceMotion: false
|
|
364
|
+
|
|
365
|
+
function duration(ms) {
|
|
366
|
+
return reduceMotion ? 0 : ms
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function refresh() {
|
|
370
|
+
hyprctlProc.running = true
|
|
371
|
+
gapsOutProc.running = true
|
|
372
|
+
animationsProc.running = true
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function scheduleRefresh() {
|
|
376
|
+
refreshTimer.restart()
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function applyRoundingJson(raw) {
|
|
380
|
+
try {
|
|
381
|
+
var json = JSON.parse(raw || "{}")
|
|
382
|
+
var n = Number(json.int)
|
|
383
|
+
if (isFinite(n) && n >= 0) cornerRadius = n
|
|
384
|
+
} catch (e) {
|
|
385
|
+
// hyprctl missing / Hyprland not running — leave the previous value.
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function applyGapsOutJson(raw) {
|
|
390
|
+
try {
|
|
391
|
+
var json = JSON.parse(raw || "{}")
|
|
392
|
+
var css = String(json.css || "")
|
|
393
|
+
var parts = css.match(/-?\d+(?:\.\d+)?/g) || []
|
|
394
|
+
var n = parts.length > 0 ? Number(parts[0]) : Number(json.int)
|
|
395
|
+
if (isFinite(n) && n >= 0) gapsOut = Math.max(0, Math.round(n / 2))
|
|
396
|
+
} catch (e) {
|
|
397
|
+
// hyprctl missing / Hyprland not running — leave the previous value.
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Pull typography, bar dimensions, state tokens, and spacing out of the
|
|
402
|
+
// shell.toml dict that Color already parsed. Called by Commons.Color.loadShell so
|
|
403
|
+
// a single parse pass feeds both singletons.
|
|
404
|
+
function applyShellValues(values) {
|
|
405
|
+
var fontOut = {}
|
|
406
|
+
var barOut = {}
|
|
407
|
+
var styleOut = {}
|
|
408
|
+
var spacingOut = {}
|
|
409
|
+
var nextBase = 12
|
|
410
|
+
var nextSpacingScale = 1.0
|
|
411
|
+
var nextSpacingScaleWithFont = true
|
|
412
|
+
var nextBarScaleWithFont = true
|
|
413
|
+
var v = values || {}
|
|
414
|
+
for (var fullKey in v) {
|
|
415
|
+
var dot = fullKey.indexOf(".")
|
|
416
|
+
if (dot < 0) continue
|
|
417
|
+
var section = fullKey.substr(0, dot)
|
|
418
|
+
var key = fullKey.substr(dot + 1)
|
|
419
|
+
var raw = v[fullKey]
|
|
420
|
+
if (section === "font") {
|
|
421
|
+
var ival = parseInt(raw, 10)
|
|
422
|
+
if (!isFinite(ival)) continue
|
|
423
|
+
if (key === "base-size") nextBase = ival
|
|
424
|
+
else fontOut[key] = ival
|
|
425
|
+
} else if (section === "bar") {
|
|
426
|
+
if (key === "scale-with-font") {
|
|
427
|
+
nextBarScaleWithFont = boolToken(raw, nextBarScaleWithFont)
|
|
428
|
+
} else if (key === "size-horizontal" || key === "size-vertical" || key === "notch-height"
|
|
429
|
+
|| key === "icon-slot" || key === "icon-canvas" || key === "icon-font"
|
|
430
|
+
|| key === "icon-size" || key === "status-slot") {
|
|
431
|
+
var b = parseInt(raw, 10)
|
|
432
|
+
if (isFinite(b)) barOut[key] = b
|
|
433
|
+
}
|
|
434
|
+
} else if (section === "spacing") {
|
|
435
|
+
if (key === "scale-with-font") {
|
|
436
|
+
nextSpacingScaleWithFont = boolToken(raw, nextSpacingScaleWithFont)
|
|
437
|
+
} else {
|
|
438
|
+
var fval = parseFloat(raw)
|
|
439
|
+
if (!isFinite(fval)) continue
|
|
440
|
+
if (key === "scale") nextSpacingScale = fval
|
|
441
|
+
else spacingOut[key] = fval
|
|
442
|
+
}
|
|
443
|
+
} else if (section === "controls" || section === "style") {
|
|
444
|
+
// Strings are passed through; styleRawNum/styleString coerce on read.
|
|
445
|
+
// [style] is the legacy name for [controls].
|
|
446
|
+
styleOut[key] = raw
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// Keep only a 1px sanity floor. Per-token overrides aren't clamped
|
|
450
|
+
// either — a theme that wants display-large = 64 should be allowed to
|
|
451
|
+
// ship it.
|
|
452
|
+
if (!isFinite(nextBase) || nextBase < 1) nextBase = 1
|
|
453
|
+
if (!isFinite(nextSpacingScale) || nextSpacingScale < 0) nextSpacingScale = 1.0
|
|
454
|
+
spacingScale = nextSpacingScale
|
|
455
|
+
spacingScaleWithFont = nextSpacingScaleWithFont
|
|
456
|
+
fontBaseSize = nextBase
|
|
457
|
+
fontOverrides = fontOut
|
|
458
|
+
barOverrides = barOut
|
|
459
|
+
barScaleWithFont = nextBarScaleWithFont
|
|
460
|
+
spacingOverrides = spacingOut
|
|
461
|
+
styleOverrides = styleOut
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
property Process hyprctlProc: Process {
|
|
465
|
+
id: hyprctlProc
|
|
466
|
+
command: ["hyprctl", "-j", "getoption", "decoration:rounding"]
|
|
467
|
+
stdout: StdioCollector {
|
|
468
|
+
waitForEnd: true
|
|
469
|
+
onStreamFinished: root.applyRoundingJson(text)
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
property Process animationsProc: Process {
|
|
474
|
+
id: animationsProc
|
|
475
|
+
command: ["hyprctl", "-j", "getoption", "animations:enabled"]
|
|
476
|
+
stdout: StdioCollector {
|
|
477
|
+
waitForEnd: true
|
|
478
|
+
onStreamFinished: {
|
|
479
|
+
try {
|
|
480
|
+
root.reduceMotion = JSON.parse(text || "{}").bool === false
|
|
481
|
+
} catch (e) {
|
|
482
|
+
// hyprctl missing / Hyprland not running — leave the previous value.
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// A reload is when the animations toggle, a theme or the user's own config
|
|
489
|
+
// lands, and Hyprland only announces it once the new values are in effect.
|
|
490
|
+
property Connections hyprlandEvents: Connections {
|
|
491
|
+
target: Hyprland
|
|
492
|
+
function onRawEvent(event) {
|
|
493
|
+
if (event && String(event.name) === "configreloaded") root.refresh()
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
property Process gapsOutProc: Process {
|
|
498
|
+
id: gapsOutProc
|
|
499
|
+
command: ["hyprctl", "-j", "getoption", "general:gaps_out"]
|
|
500
|
+
stdout: StdioCollector {
|
|
501
|
+
waitForEnd: true
|
|
502
|
+
onStreamFinished: root.applyGapsOutJson(text)
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Resolve the fontconfig alias to a concrete family name. `omarchy font
|
|
507
|
+
// set <name>` rewrites ~/.config/fontconfig/fonts.conf and restarts the
|
|
508
|
+
// shell, but rerun on file change anyway so manual edits propagate too.
|
|
509
|
+
function resolveFontFamily() {
|
|
510
|
+
fcMatchProc.running = true
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
property Process fcMatchProc: Process {
|
|
514
|
+
id: fcMatchProc
|
|
515
|
+
command: ["fc-match", "-f", "%{family[0]}", "monospace"]
|
|
516
|
+
stdout: StdioCollector {
|
|
517
|
+
waitForEnd: true
|
|
518
|
+
onStreamFinished: {
|
|
519
|
+
var name = String(text || "").trim()
|
|
520
|
+
if (name.length > 0) root.resolvedFontFamily = name
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
property FileView fontconfigFile: FileView {
|
|
526
|
+
path: Quickshell.env("HOME") + "/.config/fontconfig/fonts.conf"
|
|
527
|
+
watchChanges: true
|
|
528
|
+
printErrors: false
|
|
529
|
+
onFileChanged: root.resolveFontFamily()
|
|
530
|
+
onLoaded: root.resolveFontFamily()
|
|
531
|
+
onLoadFailed: root.resolveFontFamily()
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Re-poll Hyprland a beat after either input file changes. Hyprland's
|
|
535
|
+
// auto-reload runs asynchronously when its sourced .lua files change,
|
|
536
|
+
// so racing it with an immediate hyprctl gives the old value. 200ms is
|
|
537
|
+
// generous enough for Hyprland to settle without being user-visible.
|
|
538
|
+
property Timer refreshTimer: Timer {
|
|
539
|
+
id: refreshTimer
|
|
540
|
+
interval: 200
|
|
541
|
+
repeat: false
|
|
542
|
+
onTriggered: root.refresh()
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// `omarchy toggle window-gaps` creates/removes this flag file. Hyprland
|
|
546
|
+
// reloads its config when sourced files change, then hyprctl reflects
|
|
547
|
+
// the new effective value.
|
|
548
|
+
property FileView windowNoGapsToggle: FileView {
|
|
549
|
+
path: Quickshell.env("HOME") + "/.local/state/omarchy/toggles/hypr/window-no-gaps.lua"
|
|
550
|
+
watchChanges: true
|
|
551
|
+
printErrors: false
|
|
552
|
+
onFileChanged: refreshTimer.restart()
|
|
553
|
+
onLoaded: refreshTimer.restart()
|
|
554
|
+
onLoadFailed: refreshTimer.restart()
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
Component.onCompleted: {
|
|
558
|
+
refresh()
|
|
559
|
+
resolveFontFamily()
|
|
560
|
+
}
|
|
561
|
+
}
|