diff --git a/.config/quickshell/ReloadPopup.qml b/.config/quickshell/ReloadPopup.qml
index c3f0aab9..eb19cbd9 100644
--- a/.config/quickshell/ReloadPopup.qml
+++ b/.config/quickshell/ReloadPopup.qml
@@ -97,6 +97,7 @@ Scope {
// A progress bar on the bottom of the screen, showing how long until the
// popup is removed.
Rectangle {
+ z: 2
id: bar
color: failed ? "#ff93000A" : "#ff0C1F13"
anchors.bottom: parent.bottom
@@ -109,9 +110,9 @@ Scope {
id: anim
target: bar
property: "width"
- from: rect.width
+ from: rect.width - bar.anchors.margins * 2
to: 0
- duration: failed ? 10000 : 800
+ duration: failed ? 10000 : 1000
onFinished: popupLoader.active = false
// Pause the animation when the mouse is hovering over the popup,
@@ -120,6 +121,18 @@ Scope {
paused: mouseArea.containsMouse
}
}
+ // Its bg
+ Rectangle {
+ z: 1
+ id: bar_bg
+ color: failed ? "#30af1b25" : "#4027643e"
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.margins: 10
+ height: 5
+ radius: 9999
+ width: rect.width - bar.anchors.margins * 2
+ }
// We could set `running: true` inside the animation, but the width of the
// rectangle might not be calculated yet, due to the layout.
diff --git a/.config/quickshell/assets/icons/ai-openai-symbolic.svg b/.config/quickshell/assets/icons/ai-openai-symbolic.svg
new file mode 120000
index 00000000..c9ee0b32
--- /dev/null
+++ b/.config/quickshell/assets/icons/ai-openai-symbolic.svg
@@ -0,0 +1 @@
+openai-symbolic.svg
\ No newline at end of file
diff --git a/.config/quickshell/assets/icons/arch-symbolic.svg b/.config/quickshell/assets/icons/arch-symbolic.svg
new file mode 100644
index 00000000..7de9094e
--- /dev/null
+++ b/.config/quickshell/assets/icons/arch-symbolic.svg
@@ -0,0 +1,113 @@
+
+
+
+
diff --git a/.config/quickshell/assets/icons/cachyos-symbolic.svg b/.config/quickshell/assets/icons/cachyos-symbolic.svg
new file mode 100644
index 00000000..4a9db19a
--- /dev/null
+++ b/.config/quickshell/assets/icons/cachyos-symbolic.svg
@@ -0,0 +1,318 @@
+
+
diff --git a/.config/quickshell/assets/icons/cloudflare-dns-symbolic.svg b/.config/quickshell/assets/icons/cloudflare-dns-symbolic.svg
new file mode 100644
index 00000000..bd48d3c9
--- /dev/null
+++ b/.config/quickshell/assets/icons/cloudflare-dns-symbolic.svg
@@ -0,0 +1,10 @@
+
diff --git a/.config/quickshell/assets/icons/crosshair-symbolic.svg b/.config/quickshell/assets/icons/crosshair-symbolic.svg
new file mode 100644
index 00000000..22967493
--- /dev/null
+++ b/.config/quickshell/assets/icons/crosshair-symbolic.svg
@@ -0,0 +1,65 @@
+
+
+
+
diff --git a/.config/quickshell/assets/icons/debian-symbolic.svg b/.config/quickshell/assets/icons/debian-symbolic.svg
new file mode 100644
index 00000000..252f8533
--- /dev/null
+++ b/.config/quickshell/assets/icons/debian-symbolic.svg
@@ -0,0 +1,91 @@
+
+
+
+
diff --git a/.config/quickshell/assets/icons/deepseek-symbolic.svg b/.config/quickshell/assets/icons/deepseek-symbolic.svg
new file mode 100644
index 00000000..029e1266
--- /dev/null
+++ b/.config/quickshell/assets/icons/deepseek-symbolic.svg
@@ -0,0 +1,47 @@
+
+
diff --git a/.config/quickshell/assets/icons/desktop-symbolic.svg b/.config/quickshell/assets/icons/desktop-symbolic.svg
new file mode 100644
index 00000000..04f7a3b5
--- /dev/null
+++ b/.config/quickshell/assets/icons/desktop-symbolic.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/.config/quickshell/assets/icons/endeavouros-symbolic.svg b/.config/quickshell/assets/icons/endeavouros-symbolic.svg
new file mode 100644
index 00000000..3be4cc40
--- /dev/null
+++ b/.config/quickshell/assets/icons/endeavouros-symbolic.svg
@@ -0,0 +1,96 @@
+
+
diff --git a/.config/quickshell/assets/icons/fedora-symbolic.svg b/.config/quickshell/assets/icons/fedora-symbolic.svg
new file mode 100644
index 00000000..1a4e8c87
--- /dev/null
+++ b/.config/quickshell/assets/icons/fedora-symbolic.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/.config/quickshell/assets/icons/flatpak-symbolic.svg b/.config/quickshell/assets/icons/flatpak-symbolic.svg
new file mode 100644
index 00000000..0c2bf628
--- /dev/null
+++ b/.config/quickshell/assets/icons/flatpak-symbolic.svg
@@ -0,0 +1,52 @@
+
+
diff --git a/.config/quickshell/assets/icons/github-symbolic.svg b/.config/quickshell/assets/icons/github-symbolic.svg
new file mode 100644
index 00000000..c1c9f19c
--- /dev/null
+++ b/.config/quickshell/assets/icons/github-symbolic.svg
@@ -0,0 +1,40 @@
+
+
diff --git a/.config/quickshell/assets/icons/google-gemini-symbolic.svg b/.config/quickshell/assets/icons/google-gemini-symbolic.svg
new file mode 100644
index 00000000..9de741be
--- /dev/null
+++ b/.config/quickshell/assets/icons/google-gemini-symbolic.svg
@@ -0,0 +1,56 @@
+
+
+
+
diff --git a/.config/quickshell/assets/icons/linux-symbolic.svg b/.config/quickshell/assets/icons/linux-symbolic.svg
new file mode 100644
index 00000000..63f9c7e5
--- /dev/null
+++ b/.config/quickshell/assets/icons/linux-symbolic.svg
@@ -0,0 +1,113 @@
+
+
+
+
diff --git a/.config/quickshell/assets/icons/microsoft-symbolic.svg b/.config/quickshell/assets/icons/microsoft-symbolic.svg
new file mode 100644
index 00000000..b90cfc63
--- /dev/null
+++ b/.config/quickshell/assets/icons/microsoft-symbolic.svg
@@ -0,0 +1,54 @@
+
+
diff --git a/.config/quickshell/assets/icons/nixos-symbolic.svg b/.config/quickshell/assets/icons/nixos-symbolic.svg
new file mode 100644
index 00000000..b697b0d1
--- /dev/null
+++ b/.config/quickshell/assets/icons/nixos-symbolic.svg
@@ -0,0 +1,77 @@
+
+
diff --git a/.config/quickshell/assets/icons/ollama-symbolic.svg b/.config/quickshell/assets/icons/ollama-symbolic.svg
new file mode 100644
index 00000000..01454815
--- /dev/null
+++ b/.config/quickshell/assets/icons/ollama-symbolic.svg
@@ -0,0 +1,60 @@
+
+
diff --git a/.config/quickshell/assets/icons/openai-symbolic.svg b/.config/quickshell/assets/icons/openai-symbolic.svg
new file mode 100644
index 00000000..8ffc912a
--- /dev/null
+++ b/.config/quickshell/assets/icons/openai-symbolic.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/.config/quickshell/assets/icons/openrouter-symbolic.svg b/.config/quickshell/assets/icons/openrouter-symbolic.svg
new file mode 100644
index 00000000..32aaaf50
--- /dev/null
+++ b/.config/quickshell/assets/icons/openrouter-symbolic.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/.config/quickshell/assets/icons/ubuntu-symbolic.svg b/.config/quickshell/assets/icons/ubuntu-symbolic.svg
new file mode 100644
index 00000000..07746c9f
--- /dev/null
+++ b/.config/quickshell/assets/icons/ubuntu-symbolic.svg
@@ -0,0 +1,85 @@
+
+
+
+
diff --git a/.config/quickshell/assets/images/default_wallpaper.png b/.config/quickshell/assets/images/default_wallpaper.png
new file mode 100644
index 00000000..77d890c2
Binary files /dev/null and b/.config/quickshell/assets/images/default_wallpaper.png differ
diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml
index b290c2a9..bbbf733f 100644
--- a/.config/quickshell/modules/common/Appearance.qml
+++ b/.config/quickshell/modules/common/Appearance.qml
@@ -114,10 +114,14 @@ Singleton {
property color colOnLayer2: m3colors.m3onSurface;
property color colLayer3: mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96);
property color colOnLayer3: m3colors.m3onSurface;
+ property color colLayer1Hover: mix(colLayer1, colOnLayer1, 0.85);
+ property color colLayer1Active: mix(colLayer1, colOnLayer1, 0.70);
property color colLayer2Hover: mix(colLayer2, colOnLayer2, 0.90);
property color colLayer2Active: mix(colLayer2, colOnLayer2, 0.80);
property color colLayer3Hover: mix(colLayer3, colOnLayer3, 0.90);
property color colLayer3Active: mix(colLayer3, colOnLayer3, 0.80);
+ property color colPrimaryHover: mix(m3colors.m3primary, colLayer1Hover, 0.7)
+ property color colPrimaryActive: mix(m3colors.m3primary, colLayer1Active, 0.4)
}
rounding: QtObject {
diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml
index 93fa413a..216a7dfd 100644
--- a/.config/quickshell/modules/common/ConfigOptions.qml
+++ b/.config/quickshell/modules/common/ConfigOptions.qml
@@ -20,4 +20,8 @@ Singleton {
property int updateInterval: 3000
}
+ property QtObject hacks: QtObject {
+ property int arbitraryRaceConditionDelay: 10
+ }
+
}
diff --git a/.config/quickshell/modules/common/widgets/CustomIcon.qml b/.config/quickshell/modules/common/widgets/CustomIcon.qml
new file mode 100644
index 00000000..1e8ab368
--- /dev/null
+++ b/.config/quickshell/modules/common/widgets/CustomIcon.qml
@@ -0,0 +1,24 @@
+import QtQuick
+import Qt.labs.platform
+import Quickshell
+import Quickshell.Widgets
+
+Item {
+ id: root
+
+ property string source: ""
+ property string iconFolder: StandardPaths.standardLocations(StandardPaths.ConfigLocation)[0] + "/quickshell/assets/icons" // The folder to check first
+ width: 30
+ height: 30
+
+ IconImage {
+ id: iconImage
+ anchors.fill: parent
+ source: {
+ if (iconFolder && iconFolder + "/" + root.source) {
+ return iconFolder + "/" + root.source
+ }
+ return root.source
+ }
+ }
+}
diff --git a/.config/quickshell/modules/sidebarRight/QuickToggleButton.qml b/.config/quickshell/modules/sidebarRight/QuickToggleButton.qml
new file mode 100644
index 00000000..0c3cb82c
--- /dev/null
+++ b/.config/quickshell/modules/sidebarRight/QuickToggleButton.qml
@@ -0,0 +1,33 @@
+import "../common"
+import "../common/widgets"
+import QtQuick
+import QtQuick.Controls
+
+Button {
+ id: button
+
+ property bool toggled
+
+ signal clicked()
+
+ implicitWidth: 40
+ implicitHeight: 40
+ onClicked: {
+ }
+
+ background: Rectangle {
+ anchors.fill: parent
+ radius: Appearance.rounding.full
+ color: toggled ?
+ (button.down ? Appearance.colors.colPrimaryActive : button.hovered ? Appearance.colors.colPrimaryHover : Appearance.m3colors.m3primary) :
+ (button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.colors.colLayer1Hover, 1))
+
+ MaterialSymbol {
+ anchors.centerIn: parent
+ text: "coffee"
+ color: toggled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer1
+ }
+
+ }
+
+}
diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml
index b26d59ee..4e846336 100644
--- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml
+++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml
@@ -5,14 +5,14 @@ import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell
+import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
import Qt5Compat.GraphicalEffects
Scope {
- id: bar
-
- readonly property int sidebarWidth: Appearance.sizes.sidebarWidth
+ property int sidebarWidth: Appearance.sizes.sidebarWidth
+ property int sidebarPadding: 15
Variants {
id: sidebarVariants
@@ -29,6 +29,7 @@ Scope {
exclusiveZone: 0
width: sidebarWidth
WlrLayershell.namespace: "quickshell:sidebarRight"
+ WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
color: "transparent"
anchors {
@@ -38,9 +39,29 @@ Scope {
}
HyprlandFocusGrab {
- active: sidebarRoot.visible
id: grab
windows: [ sidebarRoot ]
+ active: false
+ onCleared: () => {
+ // sidebarRoot.visible = false
+ if (!active) sidebarRoot.visible = false
+ }
+ }
+
+ Connections {
+ target: sidebarRoot
+ function onVisibleChanged() {
+ delayedGrabTimer.start()
+ }
+ }
+
+ Timer {
+ id: delayedGrabTimer
+ interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
+ repeat: false
+ onTriggered: {
+ grab.active = sidebarRoot.visible
+ }
}
// Background
@@ -60,6 +81,70 @@ Scope {
event.accepted = true; // Prevent further propagation of the event
}
}
+
+ ColumnLayout {
+ anchors.centerIn: parent
+ height: parent.height - sidebarPadding * 2
+ width: parent.width - sidebarPadding * 2
+ spacing: sidebarPadding
+
+ RowLayout {
+ Layout.fillHeight: false
+ spacing: 10
+ Layout.margins: 10
+ Layout.topMargin: 10
+
+ CustomIcon {
+ width: 25
+ height: 25
+ source: SystemInfo.distroIcon
+ }
+
+ StyledText {
+ font.pointSize: Appearance.font.pointSize.normal
+ color: Appearance.colors.colOnLayer0
+ text: `Uptime: ${DateTime.uptime}`
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+
+
+ }
+
+ Rectangle {
+ Layout.alignment: Qt.AlignHCenter
+ Layout.fillHeight: false
+ radius: Appearance.rounding.full
+ color: Appearance.colors.colLayer1
+ implicitWidth: sidebarQuickControlsRow.implicitWidth + 10
+ implicitHeight: sidebarQuickControlsRow.implicitHeight + 10
+
+
+ RowLayout {
+ id: sidebarQuickControlsRow
+ anchors.fill: parent
+ anchors.margins: 5
+ spacing: 5
+ Rectangle {
+ width: 40
+ height: 40
+ color: "#77000000"
+ radius: Appearance.rounding.full
+ }
+
+ QuickToggleButton {
+ toggled: false
+ }
+
+ }
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+ }
}
// Shadow
diff --git a/.config/quickshell/scripts/wayland-idle-inhibitor.py b/.config/quickshell/scripts/wayland-idle-inhibitor.py
new file mode 100755
index 00000000..9bdaabb0
--- /dev/null
+++ b/.config/quickshell/scripts/wayland-idle-inhibitor.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env -S\_/bin/sh\_-xc\_"source\_\$(eval\_echo\_\$ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate&&exec\_python\_-E\_"\$0"\_"\$@""
+
+# From https://github.com/stwa/wayland-idle-inhibitor
+# License: WTFPL Version 2
+
+import sys
+from dataclasses import dataclass
+from signal import SIGINT, SIGTERM, signal
+from threading import Event
+import setproctitle
+
+from pywayland.client.display import Display
+from pywayland.protocol.idle_inhibit_unstable_v1.zwp_idle_inhibit_manager_v1 import (
+ ZwpIdleInhibitManagerV1,
+)
+from pywayland.protocol.wayland.wl_compositor import WlCompositor
+from pywayland.protocol.wayland.wl_registry import WlRegistryProxy
+from pywayland.protocol.wayland.wl_surface import WlSurface
+
+
+@dataclass
+class GlobalRegistry:
+ surface: WlSurface | None = None
+ inhibit_manager: ZwpIdleInhibitManagerV1 | None = None
+
+
+def handle_registry_global(
+ wl_registry: WlRegistryProxy, id_num: int, iface_name: str, version: int
+) -> None:
+ global_registry: GlobalRegistry = wl_registry.user_data or GlobalRegistry()
+
+ if iface_name == "wl_compositor":
+ compositor = wl_registry.bind(id_num, WlCompositor, version)
+ global_registry.surface = compositor.create_surface() # type: ignore
+ elif iface_name == "zwp_idle_inhibit_manager_v1":
+ global_registry.inhibit_manager = wl_registry.bind(
+ id_num, ZwpIdleInhibitManagerV1, version
+ )
+
+
+def main() -> None:
+ done = Event()
+ signal(SIGINT, lambda _, __: done.set())
+ signal(SIGTERM, lambda _, __: done.set())
+
+ global_registry = GlobalRegistry()
+
+ display = Display()
+ display.connect()
+
+ registry = display.get_registry() # type: ignore
+ registry.user_data = global_registry
+ registry.dispatcher["global"] = handle_registry_global
+
+ def shutdown() -> None:
+ display.dispatch()
+ display.roundtrip()
+ display.disconnect()
+
+ display.dispatch()
+ display.roundtrip()
+
+ if global_registry.surface is None or global_registry.inhibit_manager is None:
+ print("Wayland seems not to support idle_inhibit_unstable_v1 protocol.")
+ shutdown()
+ sys.exit(1)
+
+ inhibitor = global_registry.inhibit_manager.create_inhibitor( # type: ignore
+ global_registry.surface
+ )
+
+ display.dispatch()
+ display.roundtrip()
+
+ print("Inhibiting idle...")
+ done.wait()
+ print("Shutting down...")
+
+ inhibitor.destroy()
+
+ shutdown()
+
+
+if __name__ == "__main__":
+ setproctitle.setproctitle("wayland-idle-inhibitor.py")
+ main()