Compare commits

...
8 Commits
21 changed files with 761 additions and 93 deletions

No files matched your search

+2
View File
@@ -31,6 +31,8 @@ in {
mode = "2560x1440@100";
position = "0x0";
scale = 1;
cm = "srgb";
supports_hdr = -1;
}
{
output = "HDMI-A-1";
+3
View File
@@ -25,6 +25,9 @@
];
programs.gamemode.enable = true;
programs.kdeconnect.enable = true;
home-manager.users.sweetbread.services.kdeconnect.enable = true;
services.printing.enable = true;
hardware.opentabletdriver.enable = true;
+10 -38
View File
@@ -1,50 +1,22 @@
{ pkgs, lib, ... }:
let
hyprLua = import ../../../modules/user/hyprland/lua.nix { inherit lib; };
monitor-switcher = pkgs.writers.writeBashBin "monitor_switcher" /*bash*/ ''
MODE=$1
case $MODE in
"tv")
hyprctl eval 'hl.monitor({ output = "DP-3", mode = "1920x1080@60", position = "3840x0", scale = 1 })'
hyprctl eval 'hl.monitor({ output = "HDMI-A-1", mode = "3840x2160@60", position = "0x0", scale = 1 })'
notify-send "TV mode"
;;
"mirror")
hyprctl eval 'hl.monitor({ output = "HDMI-A-1", mode = "3840x2160@60", position = "0x0", scale = 1 })'
hyprctl eval 'hl.monitor({ output = "DP-3", mode = "preferred", position = "auto", scale = 1, mirror = "HDMI-A-1" })'
notify-send "TV-only mode"
;;
"display"|*)
hyprctl eval 'hl.monitor({ output = "HDMI-A-1", disabled = true })'
hyprctl eval 'hl.monitor({ output = "DP-3", mode = "3440x1440@165", position = "0x0", scale = 1 })'
notify-send "Display mode"
;;
esac
'';
in {
{ ... }: {
wayland.windowManager.hyprland.settings = {
monitor = [
{
output = "DP-3";
mode = "3440x1440@165";
position = "auto-right";
output = "desc:Huawei Technologies Co. Inc. ZQE-CAA 0xC080F622";
mode = "3440x1440@120";
position = "1920x0";
scale = 1;
cm = "srgb";
supports_hdr = -1;
}
{
output = "HDMI-A-1";
output = "desc:Samsung Electric Company SAMSUNG 0x01000E00";
disabled = true;
mode = "1920x1080@60";
position = "0x0";
scale = 1;
}
];
bind = [
(hyprLua.bind "XF86Calculator" (hyprLua.exec "ghostty --title=pulsemixer -e pulsemixer"))
(hyprLua.bind "SUPER + F1" (hyprLua.exec "${lib.getExe monitor-switcher} tv"))
(hyprLua.bind "SUPER + F2" (hyprLua.exec "${lib.getExe monitor-switcher} mirror"))
(hyprLua.bind "SUPER + F3" (hyprLua.exec "${lib.getExe monitor-switcher}"))
];
};
}
+5 -2
View File
@@ -105,7 +105,10 @@ in {
{ _args = [ "XDG_SCREENSHOTS_DIR" "~/screens" ]; }
];
gesture = [
# Lucid's Rias integration loads support/hypr/modules/gestures.lua,
# which defines this workspace swipe (and a four-finger variant).
# Avoid registering the same 3-finger gesture twice in Hyprland.
gesture = lib.optionals (hostname != "Rias") [
{
fingers = 3;
direction = "horizontal";
@@ -154,7 +157,7 @@ in {
bind = [
(bind "SUPER + V" (exec "ghostty --title=clipse -e clipse"))
(hyprLua.bind "SUPER + SHIFT + V" (hyprLua.execLauncher "qs ipc call launcher clipboard"))
(bind "Print" (exec "qs ipc call snap toggle"))
(bind "Print" (exec "qs ipc call screenshot full"))
(bind "SUPER + Print" (exec "qs ipc call screenshot full"))
(bind "CTRL + Print" (exec "qs ipc call snap region"))
(bind "ALT + Print" (exec "qs ipc call snap window"))
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -21,18 +21,23 @@ Variants {
active: layer.visible
}
readonly property bool suppressed: Prefs.widgetHideFullscreen && layer.fullscreenUp
readonly property bool suppressed: Prefs.widgetHideFullscreen && layer.windowUp
readonly property var workspaceMonitor: Hyprland.monitorFor(layer.screen)
readonly property var activeWorkspace: workspaceMonitor ? workspaceMonitor.activeWorkspace : null
readonly property bool fullscreenUp: {
readonly property bool windowUp: {
const workspace = layer.activeWorkspace;
if (!workspace)
if (!workspace || !workspace.toplevels)
return false;
return Hyprland.toplevels.values.some((t) => {
return workspace.toplevels.values.some((t) => {
const o = t.lastIpcObject || {};
return o.workspace && o.workspace.id === workspace.id &&
(o.fullscreen || 0) > 0 && o.mapped !== false;
if (o.mapped === false || o.hidden === true)
return false;
if (o.size && (o.size[0] <= 0 || o.size[1] <= 0))
return false;
return (o.fullscreen || 0) > 0 || o.floating === false;
});
}
@@ -54,12 +59,12 @@ Variants {
right: true
}
// lastIpcObject only moves when something asks it to, so nudge it on the
// events that can change whether a window is fullscreen
// lastIpcObject only moves when something asks it to, so nudge it on
// the events that can change whether a tiled or fullscreen window exists.
Connections {
function onRawEvent(event) {
if (event.name === "fullscreen" || event.name === "activewindowv2" || event.name === "closewindow" || event.name === "workspace" || event.name === "focusedmon")
fullscreenPoll.restart();
if (event.name === "fullscreen" || event.name === "activewindowv2" || event.name === "closewindow" || event.name === "openwindow" || event.name === "workspace" || event.name === "focusedmon" || event.name === "movewindow" || event.name === "changefloatingmode")
windowPoll.restart();
}
@@ -74,7 +79,7 @@ Variants {
}
Timer {
id: fullscreenPoll
id: windowPoll
interval: 120
onTriggered: Hyprland.refreshToplevels()
@@ -266,6 +271,7 @@ Variants {
WidgetFrame {
board: deck
updatesEnabled: layer.visible
}
}
+136
View File
@@ -0,0 +1,136 @@
import QtQuick
import Quickshell
import Quickshell.Io
import qs
Column {
id: page
// the map is drawn over this
property string wallpaper: ""
spacing: Theme.dp(26)
// the header switch turns the whole layer off, so the page has nothing left to set
enabled: Prefs.widgetsEnabled
opacity: Prefs.widgetsEnabled ? 1 : 0.38
Behavior on opacity {
NumberAnimation {
duration: Theme.durShort
}
}
FileView {
path: Quickshell.env("HOME") + "/.cache/current_wallpaper"
blockLoading: true
printErrors: false
watchChanges: true
onFileChanged: reload()
onLoaded: page.wallpaper = text().trim()
}
WidgetsMap {
width: parent.width
wallpaper: page.wallpaper
}
SettingCard {
title: "ON THE DESKTOP"
SettingRow {
title: "Widget panel"
description: "Every widget there is, to drag out onto the desktop or click in, the ones already out there, and layouts to start from or save. It opens from the desktop's right-click menu too."
showDivider: false
M3Button {
text: "Open the panel"
variant: "tonal"
iconPath: "widgets"
onClicked: {
Prefs.settingsHideRequested();
Widgets.openPanel(Monitors.mainScreen ? Monitors.mainScreen.name : "");
}
}
}
SettingRow {
title: "Edit mode"
description: "The desktop shades over and everything on it can be moved: widgets, the bar's modules and the dock. Right-click anything for its options."
showDivider: false
M3Button {
text: "Edit the desktop"
variant: "tonal"
iconPath: "edit"
onClicked: Edit.enterFromSettings("widgets", "")
}
}
}
SettingCard {
title: "BEHAVIOUR"
SettingRow {
title: "Snap while dragging"
resetKey: "widgetSnap"
description: "Widgets catch on the screen's edges and centre lines, and line up with each other, so a hand-placed arrangement still looks deliberate."
M3Switch {
checked: Prefs.widgetSnap
onToggled: (v) => {
return Prefs.widgetSnap = v;
}
}
}
SettingRow {
title: "Pin everything"
resetKey: "widgetLockAll"
description: "Locks every widget where it stands, including the ones that are not individually pinned. Useful once the layout is settled."
M3Switch {
checked: Prefs.widgetLockAll
onToggled: (v) => {
return Prefs.widgetLockAll = v;
}
}
}
SettingRow {
title: "Keep above windows"
resetKey: "widgetOnTop"
description: "Off, widgets live on the desktop and windows cover them. On, they float over everything - handy for a clock or a timer you always want in sight."
M3Switch {
checked: Prefs.widgetOnTop
onToggled: (v) => {
return Prefs.widgetOnTop = v;
}
}
}
SettingRow {
title: "Hide when tiled or fullscreen windows are open"
resetKey: "widgetHideFullscreen"
description: "Widgets step aside while a tiled or fullscreen window is on the workspace; they return on empty workspaces and stay over floating windows."
showDivider: false
M3Switch {
checked: Prefs.widgetHideFullscreen
onToggled: (v) => {
return Prefs.widgetHideFullscreen = v;
}
}
}
}
}
+253
View File
@@ -0,0 +1,253 @@
--- a/lucidbar/Clock.qml
+++ b/lucidbar/Clock.qml
@@ -94,7 +94,7 @@
Timer {
interval: 1000
repeat: true
- running: true
+ running: root.visible && root.hostWindow !== null && root.hostWindow.visible
triggeredOnStart: true
onTriggered: root.now = Loc.now()
}
@@ -477,36 +477,7 @@
color: Theme.accent
transformOrigin: Item.Top
- SequentialAnimation on rotation {
- loops: Animation.Infinite
- running: bell.visible
-
- NumberAnimation {
- from: 0
- to: -14
- duration: Theme.barMs(100)
- easing.type: Easing.OutQuad
- }
-
- NumberAnimation {
- from: -14
- to: 14
- duration: Theme.barMs(160)
- easing.type: Easing.InOutQuad
- }
-
- NumberAnimation {
- from: 14
- to: 0
- duration: Theme.barMs(140)
- easing.type: Easing.OutQuad
- }
-
- PauseAnimation {
- duration: Theme.barMs(2800)
- }
-
- }
+
}
--- a/lucidbar/Mpris.qml
+++ b/lucidbar/Mpris.qml
@@ -649,7 +649,7 @@
// media card, both closed most of the time. a per-frame interpolation behind
// a closed panel measured ~18% of a core, so it waits until something shows it
FrameAnimation {
- running: root.isPlaying && !trackHitArea.dragging && (root.expanded || root.posWanted)
+ running: root.visible && root.hostWindow !== null && root.hostWindow.visible && root.isPlaying && !trackHitArea.dragging && (root.expanded || root.posWanted)
onTriggered: root.livePosSec = Math.min(root.lenSec, root.posBase + (Date.now() - root.posTimestamp) / 1000)
}
@@ -731,7 +731,7 @@
// silence costs the same as sound to capture and parse, so only listen
// while the pill's bars can dance or the panel is open on the waveform
- running: (root.isPlaying && compactBars.visible) || root.expanded
+ running: root.visible && root.hostWindow !== null && root.hostWindow.visible && ((root.isPlaying && compactBars.visible) || root.expanded)
command: ["cava", "-p", Quickshell.env('HOME') + "/.config/cava/quickshell.conf"]
onRunningChanged: {
if (!cavaProc.running && root.bars.length > 0)
@@ -948,7 +948,7 @@
to: 360
duration: 14000
loops: Animation.Infinite
- running: root.isPlaying && compactArt.visible
+ running: root.isPlaying && compactArt.visible && root.hostWindow !== null && root.hostWindow.visible
}
}
@@ -2906,7 +2906,7 @@
readonly property real segmentWidth: measure.implicitWidth
readonly property real naturalWidth: bare.implicitWidth
readonly property bool overflowing: mq.naturalWidth > mq.width
- readonly property bool animating: mq.scrolling && mq.overflowing
+ readonly property bool animating: mq.scrolling && mq.overflowing && mq.visible && mq.opacity > 0
property real currentX: 0
function updateScroll() {
--- a/lucidwidgets/WidgetFrame.qml
+++ b/lucidwidgets/WidgetFrame.qml
@@ -4,6 +4,8 @@
Item {
id: frame
+
+ property bool updatesEnabled: true
required property string uid
required property string wtype
--- a/lucidwidgets/WidgetBody.qml
+++ b/lucidwidgets/WidgetBody.qml
@@ -6,6 +6,7 @@
// set by the frame once the loader is ready
property var host: null
+ readonly property bool updatesEnabled: !body.host || (body.host.updatesEnabled !== false && body.host.onThisScreen !== false)
// a variant that draws straight onto the wallpaper with no container behind it
property bool bare: false
// a body with nothing worth showing right now: the frame fades the whole card
--- a/lucidwidgets/ClockWidget.qml
+++ b/lucidwidgets/ClockWidget.qml
@@ -43,7 +43,7 @@
Timer {
interval: 1000
repeat: true
- running: true
+ running: w.updatesEnabled && w.visible
triggeredOnStart: true
onTriggered: w.now = Loc.now()
}
--- a/lucidwidgets/SystemWidget.qml
+++ b/lucidwidgets/SystemWidget.qml
@@ -127,17 +127,23 @@
return w.inkAccent;
}
- Component.onCompleted: {
- if (!w.preview)
- Sys.hold(w.uid || "w", true, w.pollMs);
-
- }
- Component.onDestruction: Sys.hold(w.uid || "w", false)
- onPollMsChanged: {
- if (!w.preview)
- Sys.hold(w.uid || "w", true, w.pollMs);
-
- }
+ property string pollingTag: ""
+
+ function syncPolling() {
+ const tag = w.uid;
+ if (w.pollingTag !== "" && w.pollingTag !== tag)
+ Sys.hold(w.pollingTag, false);
+ w.pollingTag = tag;
+ if (tag !== "")
+ Sys.hold(tag, !w.preview && w.updatesEnabled, w.pollMs);
+ }
+
+ Component.onCompleted: w.syncPolling()
+ Component.onDestruction: Sys.hold(w.pollingTag, false)
+ onUidChanged: w.syncPolling()
+ onPollMsChanged: w.syncPolling()
+ onUpdatesEnabledChanged: w.syncPolling()
+ onPreviewChanged: w.syncPolling()
// rings: one thick m3 ring per reading, the icon inside, the number under it
Row {
--- a/lucidwidgets/FetchWidget.qml
+++ b/lucidwidgets/FetchWidget.qml
@@ -49,12 +49,22 @@
readonly property var swatches: [Theme.primary, Theme.secondary, Theme.tertiary, Theme.error, Theme.primaryContainer, Theme.secondaryContainer, Theme.tertiaryContainer, Theme.surfaceHighest]
defaultTone: "surface"
- Component.onCompleted: {
- if (!w.preview)
- Sys.hold("fetch-" + w.uid, true, 5000);
-
- }
- Component.onDestruction: Sys.hold("fetch-" + w.uid, false)
+ property string pollingTag: ""
+
+ function syncPolling() {
+ const tag = w.uid === "" ? "" : "fetch-" + w.uid;
+ if (w.pollingTag !== "" && w.pollingTag !== tag)
+ Sys.hold(w.pollingTag, false);
+ w.pollingTag = tag;
+ if (tag !== "")
+ Sys.hold(tag, !w.preview && w.updatesEnabled, 5000);
+ }
+
+ Component.onCompleted: w.syncPolling()
+ Component.onDestruction: Sys.hold(w.pollingTag, false)
+ onUidChanged: w.syncPolling()
+ onUpdatesEnabledChanged: w.syncPolling()
+ onPreviewChanged: w.syncPolling()
// card: the mark and who you are, then a labelled list
Item {
--- a/lucidwidgets/VisualiserWidget.qml
+++ b/lucidwidgets/VisualiserWidget.qml
@@ -50,6 +50,11 @@
if (w.preview || w.uid === "")
return ;
+ if (!w.updatesEnabled) {
+ Cava.drop(w.filed);
+ w.filed = "";
+ return;
+ }
Cava.want(w.uid, w.barCount);
w.filed = w.uid;
}
@@ -124,6 +129,7 @@
onWantCountChanged: w.refreshCount()
onResizingChanged: w.refreshCount()
onBarCountChanged: w.file()
+ onUpdatesEnabledChanged: w.file()
onUidChanged: {
if (w.filed !== "" && w.filed !== w.uid)
Cava.drop(w.filed);
@@ -158,7 +164,7 @@
Timer {
interval: 55
repeat: true
- running: w.preview
+ running: w.preview && w.updatesEnabled && w.visible
onTriggered: w.phase += 0.055
}
--- a/lucidprefs/ThemePage.qml
+++ b/lucidprefs/ThemePage.qml
@@ -770,6 +770,9 @@
"key": "any",
"label": "Any window"
}, {
+ "key": "non-float",
+ "label": "Non-float"
+ }, {
"key": "fullscreen",
"label": "Fullscreen"
}, {
--- a/LiveWall.qml
+++ b/LiveWall.qml
@@ -42,13 +42,18 @@
const out = {};
const mons = Hyprland.monitors.values;
for (let i = 0; i < mons.length; i++) {
const ws = mons[i].activeWorkspace;
- const windows = ws ? ws.toplevels.values.length : 0;
+ const windows = ws ? ws.toplevels.values : [];
let still = Lockscreen.locked || (root.gameMode && Prefs.liveGameMode === "pause");
if (Prefs.livePauseUnder === "any")
- still = still || windows > 0;
+ still = still || windows.length > 0;
+ else if (Prefs.livePauseUnder === "non-float")
+ still = still || windows.some((t) => {
+ const o = t && t.lastIpcObject;
+ return o && o.mapped !== false && o.hidden !== true && o.floating !== true;
+ });
else if (Prefs.livePauseUnder === "fullscreen")
still = still || (ws !== null && ws.hasFullscreen);
out[mons[i].name] = !still;
}
@@ -0,0 +1,75 @@
{
"version": 1,
"binds": [
{ "id": "wallpaper-picker", "keys": "SUPER + W", "desc": "Wallpaper picker", "category": "Lucid", "type": "exec", "cmd": "hyprctl eval 'hl.config({ input = { follow_mouse = 2 } })' && qs ipc call launcher wallpaper" },
{ "id": "wallpaper-random", "keys": "SUPER + SHIFT + W", "desc": "Set a random wallpaper", "category": "Desktop", "type": "exec", "cmd": "wallpaper_changer" },
{ "id": "calculator-volume", "keys": "XF86Calculator", "desc": "Open volume mixer", "category": "Apps", "type": "exec", "cmd": "ghostty --title=pulsemixer -e pulsemixer" },
{ "id": "zoom-reset-scroll-up", "keys": "SUPER + SHIFT + mouse_up", "desc": "Reset cursor zoom", "category": "Accessibility", "type": "lua", "lua": "function() hl.config({ cursor = { zoom_factor = 1 } }) end" },
{ "id": "zoom-reset-scroll-down", "keys": "SUPER + SHIFT + mouse_down", "desc": "Reset cursor zoom", "category": "Accessibility", "type": "lua", "lua": "function() hl.config({ cursor = { zoom_factor = 1 } }) end" },
{ "id": "zoom-reset-minus", "keys": "SUPER + SHIFT + minus", "desc": "Reset cursor zoom", "category": "Accessibility", "type": "lua", "lua": "function() hl.config({ cursor = { zoom_factor = 1 } }) end" },
{ "id": "zoom-reset-kp-subtract", "keys": "SUPER + SHIFT + KP_SUBTRACT", "desc": "Reset cursor zoom", "category": "Accessibility", "type": "lua", "lua": "function() hl.config({ cursor = { zoom_factor = 1 } }) end" },
{ "id": "zoom-reset-zero", "keys": "SUPER + SHIFT + 0", "desc": "Reset cursor zoom", "category": "Accessibility", "type": "lua", "lua": "function() hl.config({ cursor = { zoom_factor = 1 } }) end" },
{ "id": "zoom-in-equal", "keys": "SUPER + equal", "desc": "Zoom in", "category": "Accessibility", "type": "lua", "lua": "function() local current = hl.get_config('cursor.zoom_factor'); hl.config({ cursor = { zoom_factor = current * 1.1 } }) end", "opts": { "repeating": true } },
{ "id": "zoom-out-minus", "keys": "SUPER + minus", "desc": "Zoom out", "category": "Accessibility", "type": "lua", "lua": "function() local current = hl.get_config('cursor.zoom_factor'); hl.config({ cursor = { zoom_factor = math.max(1, current * 0.9) } }) end", "opts": { "repeating": true } },
{ "id": "zoom-in-kp-add", "keys": "SUPER + KP_ADD", "desc": "Zoom in", "category": "Accessibility", "type": "lua", "lua": "function() local current = hl.get_config('cursor.zoom_factor'); hl.config({ cursor = { zoom_factor = current * 1.1 } }) end", "opts": { "repeating": true } },
{ "id": "zoom-out-kp-subtract", "keys": "SUPER + KP_SUBTRACT", "desc": "Zoom out", "category": "Accessibility", "type": "lua", "lua": "function() local current = hl.get_config('cursor.zoom_factor'); hl.config({ cursor = { zoom_factor = math.max(1, current * 0.9) } }) end", "opts": { "repeating": true } },
{ "id": "widgets-panel", "keys": "SUPER + SHIFT + G", "desc": "Toggle widgets panel", "category": "Lucid", "type": "exec", "cmd": "qs ipc call widgets panel" },
{ "id": "launcher", "keys": "SUPER + D", "desc": "App launcher", "category": "Lucid", "type": "exec", "cmd": "hyprctl eval 'hl.config({ input = { follow_mouse = 2 } })' && qs ipc call launcher toggle" },
{ "id": "clipse", "keys": "SUPER + V", "desc": "Clipboard manager", "category": "Apps", "type": "exec", "cmd": "ghostty --title=clipse -e clipse" },
{ "id": "clipboard", "keys": "SUPER + SHIFT + V", "desc": "Clipboard history", "category": "Lucid", "type": "exec", "cmd": "hyprctl eval 'hl.config({ input = { follow_mouse = 2 } })' && qs ipc call launcher clipboard" },
{ "id": "screenshot", "keys": "Print", "desc": "Full screenshot", "category": "Screenshots", "type": "exec", "cmd": "qs ipc call screenshot full" },
{ "id": "screenshot-full", "keys": "SUPER + Print", "desc": "Full screenshot", "category": "Screenshots", "type": "exec", "cmd": "qs ipc call screenshot full" },
{ "id": "screenshot-region", "keys": "CTRL + Print", "desc": "Region screenshot", "category": "Screenshots", "type": "exec", "cmd": "qs ipc call snap region" },
{ "id": "screenshot-window", "keys": "ALT + Print", "desc": "Window screenshot", "category": "Screenshots", "type": "exec", "cmd": "qs ipc call snap window" },
{ "id": "terminal", "keys": "SUPER + RETURN", "desc": "Terminal", "category": "Apps", "type": "exec", "cmd": "ghostty" },
{ "id": "close-window", "keys": "SUPER + Q", "desc": "Close window", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.close()" },
{ "id": "exit-hyprland", "keys": "SUPER + M", "desc": "Exit Hyprland", "category": "Session", "type": "lua", "lua": "hl.dsp.exit()" },
{ "id": "file-manager", "keys": "SUPER + E", "desc": "File manager", "category": "Apps", "type": "exec", "cmd": "ghostty -e sh -c yazi" },
{ "id": "toggle-float", "keys": "SUPER + F", "desc": "Toggle floating window", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.float({ action = 'toggle' })" },
{ "id": "toggle-pseudo", "keys": "SUPER + P", "desc": "Toggle pseudo-tile", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.pseudo({ action = 'toggle' })" },
{ "id": "toggle-split", "keys": "SUPER + J", "desc": "Toggle split direction", "category": "Windows", "type": "lua", "lua": "hl.dsp.layout('togglesplit')" },
{ "id": "swap-split", "keys": "SUPER + K", "desc": "Swap split direction", "category": "Windows", "type": "lua", "lua": "hl.dsp.layout('swapsplit')" },
{ "id": "focus-left", "keys": "SUPER + LEFT", "desc": "Focus left", "category": "Windows", "type": "lua", "lua": "hl.dsp.focus({ direction = 'l' })" },
{ "id": "focus-right", "keys": "SUPER + RIGHT", "desc": "Focus right", "category": "Windows", "type": "lua", "lua": "hl.dsp.focus({ direction = 'r' })" },
{ "id": "focus-up", "keys": "SUPER + UP", "desc": "Focus up", "category": "Windows", "type": "lua", "lua": "hl.dsp.focus({ direction = 'u' })" },
{ "id": "focus-down", "keys": "SUPER + DOWN", "desc": "Focus down", "category": "Windows", "type": "lua", "lua": "hl.dsp.focus({ direction = 'd' })" },
{ "id": "swap-left", "keys": "SUPER + SHIFT + LEFT", "desc": "Move window left", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.swap({ direction = 'l' })" },
{ "id": "swap-right", "keys": "SUPER + SHIFT + RIGHT", "desc": "Move window right", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.swap({ direction = 'r' })" },
{ "id": "swap-up", "keys": "SUPER + SHIFT + UP", "desc": "Move window up", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.swap({ direction = 'u' })" },
{ "id": "swap-down", "keys": "SUPER + SHIFT + DOWN", "desc": "Move window down", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.swap({ direction = 'd' })" },
{ "id": "resize-left", "keys": "SUPER + CTRL + LEFT", "desc": "Resize window left", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.resize({ x = -60, y = 0, relative = true })" },
{ "id": "resize-right", "keys": "SUPER + CTRL + RIGHT", "desc": "Resize window right", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.resize({ x = 60, y = 0, relative = true })" },
{ "id": "resize-up", "keys": "SUPER + CTRL + UP", "desc": "Resize window up", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.resize({ x = 0, y = -60, relative = true })" },
{ "id": "resize-down", "keys": "SUPER + CTRL + DOWN", "desc": "Resize window down", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.resize({ x = 0, y = 60, relative = true })" },
{ "id": "workspace-focus", "keys": "SUPER + {key}", "desc": "Focus workspace {n}", "category": "Workspaces", "type": "lua", "lua": "hl.dsp.focus({ workspace = {n} })", "each": "workspace" },
{ "id": "workspace-move", "keys": "SUPER + SHIFT + {key}", "desc": "Move window to workspace {n}", "category": "Workspaces", "type": "lua", "lua": "hl.dsp.window.move({ workspace = {n}, follow = false })", "each": "workspace" },
{ "id": "scratchpad", "keys": "SUPER + ALT + P", "desc": "Toggle scratchpad", "category": "Workspaces", "type": "lua", "lua": "specials.scratchpad()" },
{ "id": "scratchpad-stash", "keys": "SUPER + ALT + S", "desc": "Stash or restore the focused window", "category": "Workspaces", "type": "lua", "lua": "specials.stash()" },
{ "id": "special-music", "keys": "SUPER + ALT + M", "desc": "Toggle Music workspace", "category": "Workspaces", "type": "lua", "lua": "specials.toggle('music')" },
{ "id": "special-comms", "keys": "SUPER + ALT + C", "desc": "Toggle Comms workspace", "category": "Workspaces", "type": "lua", "lua": "specials.toggle('comms')" },
{ "id": "special-todo", "keys": "SUPER + ALT + T", "desc": "Toggle To-do workspace", "category": "Workspaces", "type": "lua", "lua": "specials.toggle('todo')" },
{ "id": "special-sysmon", "keys": "SUPER + ALT + B", "desc": "Toggle system monitor workspace", "category": "Workspaces", "type": "lua", "lua": "specials.toggle('sysmon')" },
{ "id": "daemons-workspace", "keys": "SUPER + ALT + D", "desc": "Daemons workspace", "category": "Workspaces", "type": "lua", "lua": "specials.toggle('daemons')" },
{ "id": "fullscreen", "keys": "SUPER + SHIFT + F", "desc": "Toggle fullscreen", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.fullscreen({ action = 'toggle', mode = 'fullscreen' })" },
{ "id": "workspace-next-scroll", "keys": "SUPER + mouse_down", "desc": "Next workspace", "category": "Workspaces", "type": "lua", "lua": "hl.dsp.focus({ workspace = 'e-1' })" },
{ "id": "workspace-previous-scroll", "keys": "SUPER + mouse_up", "desc": "Previous workspace", "category": "Workspaces", "type": "lua", "lua": "hl.dsp.focus({ workspace = 'e+1' })" },
{ "id": "keyboard-brightness-up", "keys": "SUPER + F3", "desc": "Keyboard backlight up", "category": "Displays", "type": "exec", "cmd": "brightnessctl -d *::kbd_backlight set +33%" },
{ "id": "keyboard-brightness-down", "keys": "SUPER + F2", "desc": "Keyboard backlight down", "category": "Displays", "type": "exec", "cmd": "brightnessctl -d *::kbd_backlight set 33%-" },
{ "id": "audio-mute", "keys": "XF86AudioMute", "desc": "Toggle audio mute", "category": "Media", "type": "exec", "cmd": "pamixer -t" },
{ "id": "microphone-mute", "keys": "XF86AudioMicMute", "desc": "Toggle microphone mute", "category": "Media", "type": "exec", "cmd": "pamixer --default-source -t" },
{ "id": "play-pause", "keys": "XF86AudioPlay", "desc": "Play or pause media", "category": "Media", "type": "exec", "cmd": "playerctl play-pause" },
{ "id": "file-manager-media", "keys": "XF86Explorer", "desc": "File manager", "category": "Apps", "type": "exec", "cmd": "ghostty -e sh -c yazi" },
{ "id": "email", "keys": "XF86Mail", "desc": "Email", "category": "Apps", "type": "exec", "cmd": "thunderbird" },
{ "id": "browser", "keys": "XF86WWW", "desc": "Web browser", "category": "Apps", "type": "exec", "cmd": "google-chrome-stable" },
{ "id": "display-brightness-down", "keys": "XF86MonBrightnessDown", "desc": "Brightness down", "category": "Displays", "type": "exec", "cmd": "brightnessctl set 5%-" },
{ "id": "display-brightness-up", "keys": "XF86MonBrightnessUp", "desc": "Brightness up", "category": "Displays", "type": "exec", "cmd": "brightnessctl set +5%" },
{ "id": "volume-up", "keys": "XF86AudioRaiseVolume", "desc": "Volume up", "category": "Media", "type": "exec", "cmd": "pamixer -i 5", "opts": { "repeating": true } },
{ "id": "volume-down", "keys": "XF86AudioLowerVolume", "desc": "Volume down", "category": "Media", "type": "exec", "cmd": "pamixer -d 5", "opts": { "repeating": true } },
{ "id": "previous-seek", "keys": "XF86AudioPrev", "desc": "Seek backward", "category": "Media", "type": "exec", "cmd": "playerctl position 5-", "opts": { "click": true } },
{ "id": "next-seek", "keys": "XF86AudioNext", "desc": "Seek forward", "category": "Media", "type": "exec", "cmd": "playerctl position 5+", "opts": { "click": true } },
{ "id": "previous-track", "keys": "XF86AudioPrev", "desc": "Previous track", "category": "Media", "type": "exec", "cmd": "playerctl previous", "opts": { "long_press": true } },
{ "id": "next-track", "keys": "XF86AudioNext", "desc": "Next track", "category": "Media", "type": "exec", "cmd": "playerctl next", "opts": { "long_press": true } },
{ "id": "move-window-drag", "keys": "SUPER + mouse:272", "desc": "Move window with mouse", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.drag()", "opts": { "mouse": true } },
{ "id": "resize-window-drag", "keys": "SUPER + mouse:273", "desc": "Resize window with mouse", "category": "Windows", "type": "lua", "lua": "hl.dsp.window.resize()", "opts": { "mouse": true } }
]
}
@@ -0,0 +1,9 @@
-- Initial Rias display layout; Home Manager seeds this only while the
-- user-owned Lucid monitor list is empty.
return {
monitors = {
{ output = "desc:Huawei Technologies Co. Inc. ZQE-CAA 0xC080F622", mode = "3440x1440@120.00", position = "1920x0", scale = "1" },
{ output = "desc:Samsung Electric Company SAMSUNG 0x01000E00", mode = "1920x1080@60.00", position = "0x0", scale = "1" },
},
workspaces = {},
}
File renamed without changes.
@@ -170,11 +170,11 @@
"mediaStyle": "disc",
"mediaTitleWidth": 300,
"mediaWheelVolume": true,
"monitorBarScreen": "",
"monitorBarScreen": "*",
"monitorDockScreen": "",
"monitorSetups": "{}",
"monitorShellScreen": "",
"monitorWorkspaces": "{}",
"monitorSetups": "{\"desc:Huawei Technologies Co. Inc. ZQE-CAA 0xC080F622\":{\"x\":1920,\"y\":0,\"mode\":\"3440x1440@120.00\"},\"desc:Samsung Electric Company SAMSUNG 0x01000E00\":{\"x\":0,\"y\":0,\"mode\":\"1920x1080@60.00\"}}",
"monitorShellScreen": "desc:Huawei Technologies Co. Inc. ZQE-CAA 0xC080F622",
"monitorWorkspaces": "{\"mode\":\"shared\",\"assign\":{}}",
"motionScale": 1,
"nightLight": false,
"nightLightFrom": 1260,
@@ -133,6 +133,9 @@ ShellRoot {
SettingsHost {
}
DisplayTrial {
}
Binding {
target: Monitors
property: "barWindows"
File renamed without changes.
+6 -9
View File
@@ -1,9 +1,7 @@
{ pkgs, lib, config, osConfig, ... }: {
wayland.windowManager.hyprland = let
{ pkgs, lib, config, osConfig, ... }:
let
colors = config.lib.stylix.colors;
accent = colors.${config.stylix.accent};
hyprLua = import ../../../modules/user/hyprland/lua.nix { inherit lib; };
wallpaper_changer = pkgs.writers.writePython3Bin "wallpaper_changer" {
libraries = [ pkgs.python3Packages.requests ];
flakeIgnore = [ "E111" "E121" "E241" "E501" "E701" "E731" ];
@@ -128,7 +126,10 @@
f"{folder}/{filename}",
], check=False)
'';
in {
in {
home.packages = [ wallpaper_changer ];
wayland.windowManager.hyprland = {
settings = {
config = {
general = {
@@ -198,10 +199,6 @@
}
];
bind = [
(hyprLua.bind "SUPER + W" (hyprLua.execLauncher "qs ipc call launcher wallpaper"))
(hyprLua.bind "SUPER + SHIFT + W" (hyprLua.exec "${lib.getExe wallpaper_changer}"))
];
};
};
}
+238 -29
View File
@@ -1,22 +1,46 @@
{ config, lib, osConfig, pkgs, ... }:
let
host = osConfig.networking.hostName;
isRias = host == "Rias";
liveDecoder = if builtins.elem osConfig.networking.hostName [ "Rias" "Eclipse" ] then "cuda" else "vaapi";
source = pkgs.fetchgit {
url = "https://github.com/Sn3akyy1/lucid.git";
rev = "bdd7f79da18efd837f79dcecbe5d2ec178abc10c";
hash = "sha256-b6qylKjCGYy2Yo64i1w9g4oGrYgcXf502jY9qNNWhSI=";
sparseCheckout = [
"/*"
"!/wallpapers/*"
"!/assets/*.webp"
];
nonConeMode = true;
source = pkgs.applyPatches {
src = pkgs.fetchgit {
url = "https://github.com/Sn3akyy1/lucid.git";
rev = "bdd7f79da18efd837f79dcecbe5d2ec178abc10c";
hash = "sha256-b6qylKjCGYy2Yo64i1w9g4oGrYgcXf502jY9qNNWhSI=";
sparseCheckout = [
"/*"
"!/wallpapers/*"
"!/assets/*.webp"
];
nonConeMode = true;
};
patches = [ (pkgs.writeText "lucid-scratchpad-target.patch" ''
diff --git a/support/hypr/modules/specials.lua b/support/hypr/modules/specials.lua
--- a/support/hypr/modules/specials.lua
+++ b/support/hypr/modules/specials.lua
@@ -176,8 +176,11 @@
function M.scratchpad()
return function()
if space(config(), "special").enabled == false then return end
- local shown = hl.get_active_special_workspace()
- local name = shown and (shown.name:gsub("^special:", "")) or "special"
- hl.dispatch(hl.dsp.workspace.toggle_special(name))
+ local shown = hl.get_active_special_workspace()
+ if shown and shown.name == "special:special" then
+ hl.dispatch(hl.dsp.workspace.toggle_special("special"))
+ else
+ hl.dispatch(hl.dsp.focus({ workspace = "special:special" }))
+ end
end
end
'') ];
};
wallpaperDir = "${config.home.homeDirectory}/Wallpapers";
wallpaperScript = "${config.home.homeDirectory}/.config/hypr/scripts/wallpaper/set-wallpaper.sh";
widgetLayout = if osConfig.networking.hostName == "Rias"
then ../../../modules/user/lucid-widgets-rias.json
else ../../../modules/user/lucid-widgets.json;
then ../../../modules/user/lucid/lucid-widgets-rias.json
else ../../../modules/user/lucid/lucid-widgets.json;
defaultWallpaper = "${wallpaperDir}/bluehour.jpg";
hyprLua = import ../../../modules/user/hyprland/lua.nix { inherit lib; };
colors = config.lib.stylix.colors.withHashtag;
@@ -82,7 +106,107 @@ PY
user = true;
});
themeName = pkgs.writeText "lucid-current-theme" "stylix\n";
themeAutoPatch = pkgs.writeText "lucid-theme-auto.patch" ''
--- a/Prefs.qml
+++ b/Prefs.qml
@@ -455,5 +455,12 @@
function setColorMode(mode) {
+ if (mode === "auto") {
+ root.setAutoColorMode(true);
+ return;
+ }
- if ((mode !== "dark" && mode !== "light") || mode === root.colorMode)
+ if (mode !== "dark" && mode !== "light")
return;
+ root.setAutoColorMode(false);
+ if (mode === root.colorMode)
+ return;
// set straight away so the control answers the click; the cache file is
@@ -484,2 +491,4 @@
function setAutoColorMode(on) {
+ if (on && root.currentTheme !== "matugen" && root.currentTheme !== "pywal")
+ return;
root.autoColorMode = on;
@@ -1669,1 +1678,5 @@
- onLoaded: root.currentTheme = text().trim() || "matugen"
+ onLoaded: {
+ root.currentTheme = text().trim() || "matugen";
+ if (root.currentTheme !== "matugen" && root.currentTheme !== "pywal" && root.autoColorMode)
+ root.setAutoColorMode(false);
+ }
--- a/lucidprefs/ThemePage.qml
+++ b/lucidprefs/ThemePage.qml
@@ -11,9 +11,14 @@
readonly property string home: Quickshell.env("HOME")
readonly property string currentTheme: Prefs.currentTheme
- readonly property var modeOptions: [{
+ readonly property bool wallpaperDerivedTheme: page.currentTheme === "matugen" || page.currentTheme === "pywal"
+ readonly property var modeOptions: [{
"key": "dark",
"label": "Dark"
}, {
"key": "light",
"label": "Light"
}]
+ readonly property var autoModeOptions: page.modeOptions.concat([{
+ "key": "auto",
+ "label": "Auto"
+ }])
@@ -22,1 +27,1 @@
- readonly property string modeHint: page.currentTheme === "matugen" || page.currentTheme === "pywal" ? "Re-derives the palette from your wallpaper in the mode you pick. Applications are asked to match." : (page.currentTheme === "colour" ? "Builds the palette from your colour again in the mode you pick. Applications are asked to match." : "Builds a light palette from this theme's own colours. Applications are asked to match.")
+ readonly property string modeHint: page.wallpaperDerivedTheme ? "Auto follows the wallpaper brightness whenever you change the wallpaper. Dark and Light stay fixed until you choose another mode." : (page.currentTheme === "colour" ? "Builds the palette from your colour again in the mode you pick. Applications are asked to match." : "Builds a light palette from this theme's own colours. Applications are asked to match.")
@@ -273,6 +278,6 @@
M3Segmented {
- width: Theme.dp(200)
- current: Prefs.colorMode
- options: page.modeOptions
+ width: Theme.dp(page.wallpaperDerivedTheme ? 300 : 200)
+ current: Prefs.autoColorMode && page.wallpaperDerivedTheme ? "auto" : Prefs.colorMode
+ options: page.wallpaperDerivedTheme ? page.autoModeOptions : page.modeOptions
onChosen: (key) => {
return Prefs.setColorMode(key);
@@ -284,13 +289,0 @@
- SettingRow {
- title: "Follow the wallpaper"
- description: "Picks light for a bright wallpaper and dark for a dark one, every time the wallpaper changes. A hand-picked mode holds until the wallpaper changes next."
-
- M3Switch {
- checked: Prefs.autoColorMode
- onToggled: (v) => {
- return Prefs.setAutoColorMode(v);
- }
- }
-
- }
-
'';
settingsScreenPatch = pkgs.writeText "lucid-settings-screen.patch" ''
--- a/lucidprefs/Settings.qml
+++ b/lucidprefs/Settings.qml
@@ -9,2 +9,4 @@
FloatingWindow {
id: win
+ property var preferredScreen: null
+ screen: win.preferredScreen || Monitors.mainScreen
'';
wallpaperAutoPatch = pkgs.writeText "lucid-wallpaper-auto.patch" ''
--- a/set-wallpaper.sh
+++ b/set-wallpaper.sh
@@ -32,4 +32,5 @@
MODE="''${2:-}"
if [[ -z "$MODE" ]]; then
- if grep -qE '"autoColorMode"[[:space:]]*:[[:space:]]*true' "$HOME/.config/quickshell/lucidprefs/prefs.json" 2>/dev/null; then
+ if [[ "$CURRENT_THEME" == matugen || "$CURRENT_THEME" == pywal ]] && \
+ grep -qE '"autoColorMode"[[:space:]]*:[[:space:]]*true' "$HOME/.config/quickshell/lucidprefs/prefs.json" 2>/dev/null; then
MODE=auto
'';
kdeConnectBridgePython = pkgs.python3.withPackages (ps: [ ps.pygobject3 ]);
applyTheme = pkgs.writeShellScript "lucid-apply-theme" ''
case "''${1:-}" in
--apps-only) exit 0 ;;
--shell-only) shift ;;
esac
exec "$HOME/.config/lucid/apply-theme-upstream.sh" --shell-only "$@"
'';
qmlPackages = with pkgs.qt6; [ qt5compat qtmultimedia ];
@@ -90,11 +214,11 @@ PY
lucid = pkgs.writeShellScript "lucid" ''
export NIXPKGS_QT6_QML_IMPORT_PATH="${lib.makeSearchPath "lib/qt-6/qml" qmlPackages}:''${NIXPKGS_QT6_QML_IMPORT_PATH:-}"
export QT_PLUGIN_PATH="${lib.makeSearchPath "lib/qt-6/plugins" qmlPackages}:''${QT_PLUGIN_PATH:-}"
export PATH="${lib.makeBinPath (with pkgs; [ bash cliphist coreutils curl ffmpeg grim imagemagick jq libnotify pulseaudio python3 wf-recorder wl-clipboard xdg-utils ])}:${tesseract}/bin:$PATH"
export PATH="${lib.makeBinPath (with pkgs; [ bash cliphist coreutils curl ffmpeg grim imagemagick jq libnotify pulseaudio kdeConnectBridgePython pywal16 wf-recorder wl-clipboard xdg-utils ])}:${tesseract}/bin:$PATH"
exec ${pkgs.quickshell}/bin/qs --no-duplicate --path "${config.home.homeDirectory}/.config/quickshell"
'';
startWallpaper = pkgs.writeShellScript "lucid-wallpaper-start" ''
export PATH="${lib.makeBinPath (with pkgs; [ awww bash coreutils ffmpeg imagemagick jq util-linux ])}:$PATH"
export PATH="${lib.makeBinPath (with pkgs; [ awww bash coreutils ffmpeg imagemagick jq python3 pywal16 util-linux ])}:$PATH"
selected="${defaultWallpaper}"
if [ -s "${config.home.homeDirectory}/.cache/current_live_wallpaper" ]; then
saved=$(${pkgs.coreutils}/bin/head -n1 "${config.home.homeDirectory}/.cache/current_live_wallpaper")
@@ -117,7 +241,7 @@ PY
in {
programs.waybar.enable = lib.mkForce false;
services.mako.enable = lib.mkForce false;
home.packages = with pkgs; [ cliphist ffmpeg grim imagemagick libnotify wf-recorder tesseract ];
home.packages = with pkgs; [ cliphist ffmpeg grim imagemagick libnotify pywal16 wf-recorder tesseract ];
home.activation.installLucid = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
target="${config.home.homeDirectory}/.config/quickshell"
@@ -137,6 +261,17 @@ in {
--exclude='/lucidkeys/state.json' \
--exclude='/lucidwidgets/widgets.json' \
"${source}/" "$target/"
$DRY_RUN_CMD ${pkgs.patch}/bin/patch --batch -p1 -d "$target" < ${../../../modules/user/lucid/idle-work.patch}
if ! grep -Fq 'mode === "auto"' "$target/Prefs.qml"; then
$DRY_RUN_CMD ${pkgs.patch}/bin/patch --batch --forward -p1 -d "$target" < ${themeAutoPatch}
fi
if ! grep -Fq 'property var preferredScreen: null' "$target/lucidprefs/Settings.qml"; then
$DRY_RUN_CMD ${pkgs.patch}/bin/patch --batch --forward -p1 -d "$target" < ${settingsScreenPatch}
fi
settings_qml="$target/lucidprefs/Settings.qml"
if ! grep -Fq 'win.preferredScreen = Monitors.focusedScreen || Monitors.mainScreen;' "$settings_qml"; then
$DRY_RUN_CMD sed -i '/if (win.visible) {/a\ win.preferredScreen = Monitors.focusedScreen || Monitors.mainScreen;' "$settings_qml"
fi
dock_qml="$target/luciddocks/Dock.qml"
if grep -Fq '/var/lib/snapd/desktop/applications; do' "$dock_qml"; then
$DRY_RUN_CMD sed -i \
@@ -165,32 +300,47 @@ in {
// Nix focus workaround for Hyprland 0.57: detach pointer and keyboard focus while menus are open.\
Quickshell.execDetached(["hyprctl", "eval", "hl.config({ input = { follow_mouse = " + (dockWindow.menuOpen ? 2 : 1) + " } })"]);' "$dock_qml"
fi
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid-shell.qml} "$target/shell.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/LucidBar.qml} "$target/LucidBar.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/Agenda.qml} "$target/Agenda.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/CalendarSource.qml} "$target/CalendarSource.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/ClockCalendar.qml} "$target/lucidbar/ClockCalendar.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/thunderbird-calendar.py} "$target/thunderbird-calendar.py"
$DRY_RUN_CMD install -m644 ${../../../modules/user/WidgetLayer.qml} "$target/lucidwidgets/WidgetLayer.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/lucid-shell.qml} "$target/shell.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/LucidBar.qml} "$target/LucidBar.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/Agenda.qml} "$target/Agenda.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/CalendarSource.qml} "$target/CalendarSource.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/ClockCalendar.qml} "$target/lucidbar/ClockCalendar.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/thunderbird-calendar.py} "$target/thunderbird-calendar.py"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/WidgetLayer.qml} "$target/lucidwidgets/WidgetLayer.qml"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/WidgetsPage.qml} "$target/lucidprefs/WidgetsPage.qml"
$DRY_RUN_CMD mkdir -p "${wallpaperDir}" \
"${config.home.homeDirectory}/.config/hypr/scripts/wallpaper"
$DRY_RUN_CMD install -m755 "${source}/support/wallpaper/set-wallpaper.sh" \
"${wallpaperScript}"
if ! grep -Fq 'CURRENT_THEME" == matugen' "${wallpaperScript}"; then
$DRY_RUN_CMD ${pkgs.patch}/bin/patch --batch --forward -p1 -d "$(dirname ${lib.escapeShellArg wallpaperScript})" < ${wallpaperAutoPatch}
fi
lucid_dir="${config.home.homeDirectory}/.config/lucid"
$DRY_RUN_CMD mkdir -p "$lucid_dir/themes"
if [ "${host}" = Rias ] && [ ! -s "$lucid_dir/keybinds.json" ]; then
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/lucid-keybinds-rias.json} "$lucid_dir/keybinds.json"
fi
monitor_file="${config.home.homeDirectory}/.config/hypr/lucid-monitors.lua"
if [ "${host}" = Rias ] && { [ ! -s "$monitor_file" ] || ! grep -qE 'output[[:space:]]*=' "$monitor_file"; } && \
! grep -qE 'workspace[[:space:]]*=' "$monitor_file" 2>/dev/null; then
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/lucid-monitors-rias.lua} "$monitor_file"
fi
$DRY_RUN_CMD ${pkgs.rsync}/bin/rsync -rltp --chmod=Du+rwx,Fu+rw --ignore-existing \
"${source}/support/lucid/themes/" "$lucid_dir/themes/"
for script in palette-edit.py lucid_palette.py add-theme.py scheme-gallery.py gen-light-palette.py; do
$DRY_RUN_CMD install -m644 "${source}/support/lucid/$script" "$lucid_dir/$script"
done
for script in gen-pywal-palette.py set-mode.sh wallpaper-mode.sh; do
$DRY_RUN_CMD install -m755 "${source}/support/lucid/$script" "$lucid_dir/$script"
done
$DRY_RUN_CMD install -m755 "${source}/support/lucid/apply-theme.sh" \
"$lucid_dir/apply-theme-upstream.sh"
$DRY_RUN_CMD install -m755 ${applyTheme} \
"$lucid_dir/apply-theme.sh"
if [ ! -e "$target/lucidprefs/prefs.json" ]; then
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid-prefs.json} "$target/lucidprefs/prefs.json"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/lucid-prefs.json} "$target/lucidprefs/prefs.json"
fi
if [ -z "''${DRY_RUN_CMD:-}" ] && [ -f "$target/lucidprefs/prefs.json" ]; then
prefs_tmp=$(${pkgs.coreutils}/bin/mktemp "$target/lucidprefs/prefs.json.XXXXXX")
@@ -207,7 +357,7 @@ in {
fi
fi
if [ ! -e "$target/luciddocks/pinned.json" ]; then
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid-pinned.json} "$target/luciddocks/pinned.json"
$DRY_RUN_CMD install -m644 ${../../../modules/user/lucid/lucid-pinned.json} "$target/luciddocks/pinned.json"
fi
if [ ! -e "$target/lucidwidgets/widgets.json" ]; then
$DRY_RUN_CMD install -m644 ${widgetLayout} "$target/lucidwidgets/widgets.json"
@@ -260,10 +410,69 @@ in {
Install.WantedBy = [ "hyprland-session.target" ];
};
wayland.windowManager.hyprland.settings = {
on = [ (hyprLua.onStart [ "systemctl --user start lucid.service" ]) ];
bind = [
(hyprLua.bind "SUPER + SHIFT + G" (hyprLua.exec "qs ipc call widgets panel"))
];
wayland.windowManager.hyprland = {
settings = {
on = [ (hyprLua.onStart [ "systemctl --user start lucid.service" ]) ];
bind = lib.mkIf isRias (lib.mkForce []);
};
# Home Manager autoloads these before its generated settings. Lucid's
# stateful UI modules are installed too, then required after the Nix base
# config below so saved UI choices take effect without losing that base.
extraLuaFiles = lib.mkIf isRias {
"modules/binds.lua" = builtins.toPath "${source}/support/hypr/modules/binds.lua";
"modules/json.lua" = builtins.toPath "${source}/support/hypr/modules/json.lua";
"modules/decorations.lua" = builtins.toPath "${source}/support/hypr/modules/decorations.lua";
"modules/gestures.lua" = builtins.toPath "${source}/support/hypr/modules/gestures.lua";
"modules/input.lua" = builtins.toPath "${source}/support/hypr/modules/input.lua";
"modules/layout.lua" = builtins.toPath "${source}/support/hypr/modules/layout.lua";
"modules/layerrules.lua" = builtins.toPath "${source}/support/hypr/modules/layerrules.lua";
"modules/lumen.lua" = builtins.toPath "${source}/support/hypr/modules/lumen.lua";
"modules/misc.lua" = builtins.toPath "${source}/support/hypr/modules/misc.lua";
"modules/plugins.lua" = builtins.toPath "${source}/support/hypr/modules/plugins.lua";
"modules/windowrules.lua" = builtins.toPath "${source}/support/hypr/modules/windowrules.lua";
"modules/glass.lua" = {
content = builtins.toPath "${source}/support/hypr/modules/glass.lua";
autoLoad = false;
};
"modules/monitors.lua" = {
content = builtins.toPath "${source}/support/hypr/modules/monitors.lua";
autoLoad = false;
};
"modules/settings.lua" = {
content = builtins.toPath "${source}/support/hypr/modules/settings.lua";
autoLoad = false;
};
"modules/specials.lua" = {
content = builtins.toPath "${source}/support/hypr/modules/specials.lua";
autoLoad = false;
};
"modules/startup.lua" = {
content = builtins.toPath "${source}/support/hypr/modules/startup.lua";
autoLoad = false;
};
};
# Nix owns session startup and environment exports; don't load Lucid's
# generic autostart/env defaults on top of the existing host setup.
extraConfig = lib.mkIf isRias ''
local config_home = os.getenv("XDG_CONFIG_HOME") or ${builtins.toJSON config.xdg.configHome}
package.path = config_home .. "/hypr/?.lua;" .. config_home .. "/hypr/?/init.lua;" .. package.path
require("modules.specials")
require("modules.monitors")
local lucid_monitor_apply = LucidMonitors.apply
LucidMonitors.apply = function(...)
lucid_monitor_apply(...)
hl.monitor({ output = "desc:Huawei Technologies Co. Inc. ZQE-CAA 0xC080F622", cm = "srgb", supports_hdr = -1 })
end
LucidMonitors.apply()
-- Lucid previously left empty workspaces 3-6 persistent on this host.
-- Retire those stale rules after applying the monitor layout so they do
-- not return on the next Hyprland reload.
for _, workspace in ipairs({ "3", "4", "5", "6" }) do
hl.workspace_rule({ workspace = workspace, persistent = false })
end
require("modules.settings")
require("modules.glass")
require("modules.startup")
'';
};
}