diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index d1affa686..d95366fb4 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -2,22 +2,33 @@
- Please, please, please, make multiple PRs if you have many features/fixes, and don't shove your personal changes along with the PR, including changed defaults
- We can accept features that we do not personally want, but in that case we will ask you to make it configurable/optionally loaded.
-- If you want to start working on something big to contribute, it might be a good idea to ask first to not waste your effort (but if you've already done it for yourself, it doesn't hurt to submit).
+- If you want to start working on something _big_ to contribute, it might be a good idea to ask first to not waste your effort (but if you've already done it for yourself, it doesn't hurt to submit).
-# Code details
+# Translations
-## Contributing to i18n
+See `dots/.config/quickshell/ii/translations/tools`
-For contributing in translation (i18n) for Quickshell, see also `dots/.config/quickshell/ii/translations/tools`.
+# Code
## Dynamic loading
-- If something's not always necessary, especially when guarded by a config option to enable/disable, put it in a `Loader`. One tip with `Loader`s is sometimes you will need to declare positioning properties (like `anchors`) in the `Loader`, not the `sourceComponent`.
+- If something's not always necessary, especially when guarded by a config option to enable/disable, put it in a `Loader`
+ - Note that you will need to declare positioning properties (like `anchors`) in the `Loader`, not the `sourceComponent`
+ - When something that's to be dynamically loaded doesn't affect its parent layout, you can have a fading animation by using FadeLoader and set the `shown` prop instead of `active` and `visible`
## Practical concerns
- Make sure what you add does not require significant resources for a minor purpose or harm usability just for the sake of looking nice. The dotfiles must remain practical for daily driving.
-- If there is something really fancy and impractical anyway, add a config option for it and make sure it's disabled by default.
+- If there is something really fancy and impractical anyway, add a config option for it and make sure it's disabled by default (example: constantly rotating background clock)
+
+## Style
+
+- Spaces
+ - Space properties and children data into meaningful groups. (but of course, don't use 2+ blanks in a row)
+ - Put spaces between text and operators: `if (condition) { ... } else { ... }` instead of `if(condition){ ... }else{ ... }`
+- As you can see, it's pretty easy to use lots of nesting. There's no hard limit, end-4 himself nests a lot too, but avoid/mitigate that:
+ - Prefer early return: Use something like `if (!condition) return; doStuff();` instead of `if (condition) { doStuff() }`
+ - If you feel it's a bother to refractor something into a new file, remember there's `component` to declare reusable components in the same file.
# Setting up
diff --git a/.github/README.md b/.github/README.md
index de4c9c790..a8134a426 100644
--- a/.github/README.md
+++ b/.github/README.md
@@ -81,7 +81,7 @@ Widget system: Quickshell | Support: Yes
|:---|:---------------|
|
|
|
| Window management | Weeb power |
-|
|
|
+|
|
|
### Other styles: Available at the end of the readme.
diff --git a/.gitignore b/.gitignore
index b59d26bf8..9e298d049 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,17 @@
/diagnose.result
/cache
+
# Ignore Python cache files
__pycache__/
*.py[cod]
-dots/.config/quickshell/ii/.qmlls.ini
-.update-lock
+
+/dots/.config/quickshell/ii/.qmlls.ini
+
+# exp-update
+/.update-lock
+
+# custom os-release
/os-release
-#emacs backup
+
+# Emacs auto backup file
*~
diff --git a/diagnose b/diagnose
index db4a239e0..3001a62a2 100755
--- a/diagnose
+++ b/diagnose
@@ -70,6 +70,7 @@ x git submodule status --recursive
e "Checking distro"
x _check_distro_id
+x cat os-release
#x _check_distro
e "Checking variables"
diff --git a/dots/.config/hypr/hyprland/execs.conf b/dots/.config/hypr/hyprland/execs.conf
index 4bb9c86e5..bb5dd7225 100644
--- a/dots/.config/hypr/hyprland/execs.conf
+++ b/dots/.config/hypr/hyprland/execs.conf
@@ -14,7 +14,7 @@ exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISP
exec-once = hyprpm reload
# Audio
-exec-once = easyeffects --gapplication-service
+exec-once = easyeffects --hide-window --service-mode
# Clipboard: history
# exec-once = wl-paste --watch cliphist store &
diff --git a/dots/.config/hypr/hyprland/keybinds.conf b/dots/.config/hypr/hyprland/keybinds.conf
index fdda9a714..020fe582d 100644
--- a/dots/.config/hypr/hyprland/keybinds.conf
+++ b/dots/.config/hypr/hyprland/keybinds.conf
@@ -24,8 +24,8 @@ bindit = ,Super_L, global, quickshell:workspaceNumber # [hidden]
bindit = ,Super_R, global, quickshell:workspaceNumber # [hidden]
bindd = Super, V, Clipboard history >> clipboard, global, quickshell:overviewClipboardToggle # Clipboard history >> clipboard
bindd = Super, Period, Emoji >> clipboard, global, quickshell:overviewEmojiToggle # Emoji >> clipboard
-bindd = Super, Tab, Toggle overview, global, quickshell:overviewToggle # [hidden] Toggle overview/launcher (alt)
-bindd = Super, A, Toggle left sidebar, global, quickshell:sidebarLeftToggle # Toggle left sidebar
+bind = Super, Tab, global, quickshell:overviewWorkspacesToggle # [hidden] Toggle overview/launcher (alt)
+bind = Super, A, global, quickshell:sidebarLeftToggle # Toggle left sidebar
bind = Super+Alt, A, global, quickshell:sidebarLeftToggleDetach # [hidden]
bind = Super, B, global, quickshell:sidebarLeftToggle # [hidden]
bind = Super, O, global, quickshell:sidebarLeftToggle # [hidden]
diff --git a/dots/.config/hypr/hyprland/rules.conf b/dots/.config/hypr/hyprland/rules.conf
index 01ac1056d..ea9e6fd72 100644
--- a/dots/.config/hypr/hyprland/rules.conf
+++ b/dots/.config/hypr/hyprland/rules.conf
@@ -133,12 +133,14 @@ layerrule = blurpopups, quickshell:.*
layerrule = blur, quickshell:.*
layerrule = ignorealpha 0.79, quickshell:.*
layerrule = animation slide, quickshell:bar
+layerrule = noanim, quickshell:actionCenter
layerrule = animation slide bottom, quickshell:cheatsheet
layerrule = animation slide bottom, quickshell:dock
layerrule = animation popin 120%, quickshell:screenCorners
layerrule = noanim, quickshell:lockWindowPusher
layerrule = animation fade, quickshell:notificationPopup
layerrule = noanim, quickshell:overlay
+layerrule = ignorealpha 1, quickshell:overlay
layerrule = noanim, quickshell:overview
layerrule = animation slide bottom, quickshell:osk
layerrule = noanim, quickshell:polkit
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/README.md b/dots/.config/quickshell/ii/assets/icons/fluent/README.md
index 5f4d3eaa2..c8fbd90e8 100644
--- a/dots/.config/quickshell/ii/assets/icons/fluent/README.md
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/README.md
@@ -1,5 +1,5 @@
-The "search" and "task view" icons are from here, with modifications
+The "start-here", "search" and "task view" icons are from here, with modifications
-https://www.figma.com/community/file/1123040825921884189/windows-11
+[Windows 11 by Joshua Oghenekaro Okwe - Figma](https://www.figma.com/community/file/1123040825921884189/windows-11)
-License: CC BY 4.0
+License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.en)
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/arrow-sync.svg b/dots/.config/quickshell/ii/assets/icons/fluent/arrow-sync.svg
new file mode 100644
index 000000000..73df6838e
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/arrow-sync.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/chevron-down.svg b/dots/.config/quickshell/ii/assets/icons/fluent/chevron-down.svg
new file mode 100644
index 000000000..604bf9887
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/chevron-down.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/pin-off.svg b/dots/.config/quickshell/ii/assets/icons/fluent/pin-off.svg
new file mode 100644
index 000000000..046a27cea
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/pin-off.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/pin.svg b/dots/.config/quickshell/ii/assets/icons/fluent/pin.svg
new file mode 100644
index 000000000..b31790338
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/pin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/settings.svg b/dots/.config/quickshell/ii/assets/icons/fluent/settings.svg
new file mode 100644
index 000000000..f1e568829
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/settings.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/start-here-pressed.svg b/dots/.config/quickshell/ii/assets/icons/fluent/start-here-pressed.svg
new file mode 100644
index 000000000..e6b950eca
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/start-here-pressed.svg
@@ -0,0 +1,24 @@
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/start-here.svg b/dots/.config/quickshell/ii/assets/icons/fluent/start-here.svg
new file mode 100644
index 000000000..708d5a71b
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/start-here.svg
@@ -0,0 +1,24 @@
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-dark.svg b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-dark.svg
new file mode 100644
index 000000000..af58d933f
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-dark.svg
@@ -0,0 +1,105 @@
+
+
+
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-light.svg b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-light.svg
new file mode 100644
index 000000000..8d0e69fce
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-light.svg
@@ -0,0 +1,81 @@
+
+
+
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg
index 2d972a7b4..8eb990cc4 100644
--- a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg
@@ -7,10 +7,11 @@
version="1.1"
viewBox="0 0 16.933 16.933"
id="svg2"
- sodipodi:docname="system-search.svg"
+ sodipodi:docname="system-search-dark.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
+
+
+
+
+
+ style="fill:url(#linearGradient4);fill-opacity:1;stroke:url(#linearGradient919)" />
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-dark.svg b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-dark.svg
new file mode 100644
index 000000000..a7e14009c
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-dark.svg
@@ -0,0 +1,132 @@
+
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-light.svg b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-light.svg
new file mode 100644
index 000000000..b1785dbd0
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-light.svg
@@ -0,0 +1,108 @@
+
+
diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml
index a724c043d..ec47c514b 100644
--- a/dots/.config/quickshell/ii/modules/common/Config.qml
+++ b/dots/.config/quickshell/ii/modules/common/Config.qml
@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
+import qs.modules.common.functions
Singleton {
id: root
@@ -147,6 +148,7 @@ Singleton {
property string networkEthernet: "kcmshell6 kcm_networkmanagement"
property string taskManager: "plasma-systemmonitor --page-name Processes"
property string terminal: "kitty -1" // This is only for shell actions
+ property string update: "kitty -1 --hold=yes fish -i -c 'sudo pacman -Syu'"
property string volumeMixer: `~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol"`
}
@@ -158,7 +160,8 @@ Singleton {
property string placementStrategy: "leastBusy" // "free", "leastBusy", "mostBusy"
property real x: 100
property real y: 100
- property string style: "cookie" // Options: "cookie", "digital"
+ property string style: "cookie" // Options: "cookie", "digital"
+ property string styleLocked: "cookie" // Options: "cookie", "digital"
property JsonObject cookie: JsonObject {
property bool aiStyling: false
property int sides: 14
@@ -236,13 +239,6 @@ Singleton {
property bool showPerformanceProfileToggle: false
property bool showScreenRecord: false
}
- property JsonObject tray: JsonObject {
- property bool monochromeIcons: true
- property bool showItemId: false
- property bool invertPinnedItems: true // Makes the below a whitelist for the tray and blacklist for the pinned area
- property list pinnedItems: [ ]
- property bool filterPassive: true
- }
property JsonObject workspaces: JsonObject {
property bool monochromeIcons: true
property int shown: 10
@@ -264,6 +260,9 @@ Singleton {
property bool showUnreadCount: false
}
}
+ property JsonObject tooltips: JsonObject {
+ property bool clickToShow: false
+ }
}
property JsonObject battery: JsonObject {
@@ -426,6 +425,14 @@ Singleton {
property int historyLength: 60
}
+ property JsonObject tray: JsonObject {
+ property bool monochromeIcons: true
+ property bool showItemId: false
+ property bool invertPinnedItems: true // Makes the below a whitelist for the tray and blacklist for the pinned area
+ property list pinnedItems: [ "Fcitx" ]
+ property bool filterPassive: true
+ }
+
property JsonObject musicRecognition: JsonObject {
property int timeout: 16
property int interval: 4
@@ -532,6 +539,12 @@ Singleton {
}
property bool secondPrecision: false
}
+
+ property JsonObject updates: JsonObject {
+ property int checkInterval: 120 // minutes
+ property int adviseUpdateThreshold: 75 // packages
+ property int stronglyAdviseUpdateThreshold: 200 // packages
+ }
property JsonObject wallpaperSelector: JsonObject {
property bool useSystemFileDialog: false
@@ -559,6 +572,10 @@ Singleton {
}
property JsonObject waffles: JsonObject {
+ // Animations on Windoes are kinda janky. Set the following to
+ // false will make (some) stuff also be like that for accuracy.
+ // Example: the right-click menu of the Start button
+ property bool smootherAnimations: true
property JsonObject bar: JsonObject {
property bool bottom: true
property bool leftAlignApps: false
diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml
index 8e70506d3..56f647684 100644
--- a/dots/.config/quickshell/ii/modules/common/Directories.qml
+++ b/dots/.config/quickshell/ii/modules/common/Directories.qml
@@ -32,7 +32,9 @@ Singleton {
property string shellConfig: FileUtils.trimFileProtocol(`${Directories.config}/illogical-impulse`)
property string shellConfigName: "config.json"
property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}`
- property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`)
+ property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`)
+ property string notesPath: FileUtils.trimFileProtocol(`${Directories.state}/user/notes.txt`)
+ property string conflictCachePath: FileUtils.trimFileProtocol(`${Directories.cache}/conflict-killer`)
property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`)
property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`)
property string generatedWallpaperCategoryPath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/wallpaper/category.txt`)
diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml
index 212fc34b9..478cadd10 100644
--- a/dots/.config/quickshell/ii/modules/common/Persistent.qml
+++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml
@@ -131,6 +131,14 @@ Singleton {
property real height: 600
property int tabIndex: 0
}
+ property JsonObject notes: JsonObject {
+ property bool pinned: false
+ property bool clickthrough: true
+ property real x: 1400
+ property real y: 42
+ property real width: 460
+ property real height: 330
+ }
}
property JsonObject timer: JsonObject {
diff --git a/dots/.config/quickshell/ii/modules/common/functions/StringUtils.qml b/dots/.config/quickshell/ii/modules/common/functions/StringUtils.qml
index 88ab95b2d..0839b5386 100644
--- a/dots/.config/quickshell/ii/modules/common/functions/StringUtils.qml
+++ b/dots/.config/quickshell/ii/modules/common/functions/StringUtils.qml
@@ -285,4 +285,14 @@ Singleton {
}
return str;
}
+
+ function toTitleCase(str) {
+ // Replace "-" and "_" with space, then capitalize each word
+ return str.replace(/[-_]/g, " ").replace(
+ /\w\S*/g,
+ function(txt) {
+ return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
+ }
+ );
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/common/widgets/FadeLoader.qml b/dots/.config/quickshell/ii/modules/common/widgets/FadeLoader.qml
index aaa2753f8..f5064939b 100644
--- a/dots/.config/quickshell/ii/modules/common/widgets/FadeLoader.qml
+++ b/dots/.config/quickshell/ii/modules/common/widgets/FadeLoader.qml
@@ -6,11 +6,13 @@ import qs.modules.common.widgets
Loader {
id: root
property bool shown: true
+ property alias fade: opacityBehavior.enabled
opacity: shown ? 1 : 0
visible: opacity > 0
active: opacity > 0
Behavior on opacity {
+ id: opacityBehavior
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
}
diff --git a/dots/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml b/dots/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml
index 1b68059d0..ec76349bb 100644
--- a/dots/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml
+++ b/dots/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml
@@ -18,10 +18,9 @@ StyledListView { // Scrollable window
required property int index
required property var modelData
popup: root.popup
- anchors.left: parent?.left
- anchors.right: parent?.right
+ width: ListView.view.width // https://doc.qt.io/qt-6/qml-qtquick-listview.html
notificationGroup: popup ?
Notifications.popupGroupsByAppName[modelData] :
Notifications.groupsByAppName[modelData]
}
-}
\ No newline at end of file
+}
diff --git a/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml b/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml
index bc72ee416..afc9957a4 100644
--- a/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml
+++ b/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml
@@ -14,6 +14,10 @@ Item {
property real horizontalPadding: 10
property real verticalPadding: 5
+ function updateAnchor() {
+ tooltipLoader.item?.anchor.updateAnchor();
+ }
+
readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition
property var anchorEdges: Edges.Top
property var anchorGravity: anchorEdges
diff --git a/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml b/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml
index b1f4579d2..13702e1f9 100644
--- a/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml
+++ b/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml
@@ -10,6 +10,7 @@ TextArea {
selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
selectionColor: Appearance.colors.colSecondaryContainer
placeholderTextColor: Appearance.m3colors.m3outline
+ color: Appearance.colors.colOnLayer0
font {
family: Appearance.font.family.main
pixelSize: Appearance?.font.pixelSize.small ?? 15
diff --git a/dots/.config/quickshell/ii/modules/common/widgets/ToolbarTabBar.qml b/dots/.config/quickshell/ii/modules/common/widgets/ToolbarTabBar.qml
index 4d4d56335..1bca18463 100644
--- a/dots/.config/quickshell/ii/modules/common/widgets/ToolbarTabBar.qml
+++ b/dots/.config/quickshell/ii/modules/common/widgets/ToolbarTabBar.qml
@@ -5,7 +5,6 @@ import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import Qt.labs.synchronizer
Item {
id: root
diff --git a/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml
index 6d636be89..97e1e468a 100644
--- a/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml
+++ b/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml
@@ -16,7 +16,7 @@ AbstractBackgroundWidget {
implicitHeight: contentColumn.implicitHeight
implicitWidth: contentColumn.implicitWidth
- readonly property string clockStyle: Config.options.background.widgets.clock.style
+ readonly property string clockStyle: GlobalStates.screenLocked ? Config.options.background.widgets.clock.styleLocked : Config.options.background.widgets.clock.style
readonly property bool forceCenter: (GlobalStates.screenLocked && Config.options.lock.centerClock)
readonly property bool shouldShow: (!Config.options.background.widgets.clock.showOnlyWhenLocked || GlobalStates.screenLocked)
property bool wallpaperSafetyTriggered: false
@@ -44,6 +44,7 @@ AbstractBackgroundWidget {
id: cookieClockLoader
anchors.horizontalCenter: parent.horizontalCenter
shown: root.clockStyle === "cookie" && (root.shouldShow)
+ fade: false
sourceComponent: Column {
spacing: 10
CookieClock {
@@ -61,6 +62,7 @@ AbstractBackgroundWidget {
id: digitalClockLoader
anchors.horizontalCenter: parent.horizontalCenter
shown: root.clockStyle === "digital" && (root.shouldShow)
+ fade: false
sourceComponent: ColumnLayout {
id: clockColumn
spacing: 6
diff --git a/dots/.config/quickshell/ii/modules/ii/bar/BatteryIndicator.qml b/dots/.config/quickshell/ii/modules/ii/bar/BatteryIndicator.qml
index 3cabf9f36..36799fefd 100644
--- a/dots/.config/quickshell/ii/modules/ii/bar/BatteryIndicator.qml
+++ b/dots/.config/quickshell/ii/modules/ii/bar/BatteryIndicator.qml
@@ -16,7 +16,7 @@ MouseArea {
implicitWidth: batteryProgress.implicitWidth
implicitHeight: Appearance.sizes.barHeight
- hoverEnabled: true
+ hoverEnabled: !Config.options.bar.tooltips.clickToShow
ClippedProgressBar {
id: batteryProgress
diff --git a/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml
index 958695a86..1d4b9f865 100644
--- a/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml
+++ b/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml
@@ -40,8 +40,7 @@ Item {
MouseArea {
id: mouseArea
anchors.fill: parent
- hoverEnabled: true
- acceptedButtons: Qt.NoButton
+ hoverEnabled: !Config.options.bar.tooltips.clickToShow
ClockWidgetPopup {
hoverTarget: mouseArea
diff --git a/dots/.config/quickshell/ii/modules/ii/bar/Resources.qml b/dots/.config/quickshell/ii/modules/ii/bar/Resources.qml
index 6c25ab507..2d9e936ac 100644
--- a/dots/.config/quickshell/ii/modules/ii/bar/Resources.qml
+++ b/dots/.config/quickshell/ii/modules/ii/bar/Resources.qml
@@ -9,7 +9,7 @@ MouseArea {
property bool alwaysShowAllResources: false
implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin
implicitHeight: Appearance.sizes.barHeight
- hoverEnabled: true
+ hoverEnabled: !Config.options.bar.tooltips.clickToShow
RowLayout {
id: rowLayout
diff --git a/dots/.config/quickshell/ii/modules/ii/bar/SysTray.qml b/dots/.config/quickshell/ii/modules/ii/bar/SysTray.qml
index 0233b2405..56d33e0d4 100644
--- a/dots/.config/quickshell/ii/modules/ii/bar/SysTray.qml
+++ b/dots/.config/quickshell/ii/modules/ii/bar/SysTray.qml
@@ -1,10 +1,11 @@
-import qs.modules.common
-import qs.modules.common.widgets
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
import Quickshell.Services.SystemTray
+import qs.services
+import qs.modules.common
+import qs.modules.common.widgets
Item {
id: root
@@ -17,13 +18,8 @@ Item {
property bool showOverflowMenu: true
property var activeMenu: null
- property bool smartTray: Config.options.bar.tray.filterPassive
- property list itemsInUserList: SystemTray.items.values.filter(i => (Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive)))
- property list itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive)))
-
- property bool invertPins: Config.options.bar.tray.invertPinnedItems
- property list pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList
- property list unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList
+ property list pinnedItems: TrayService.pinnedItems
+ property list unpinnedItems: TrayService.unpinnedItems
onUnpinnedItemsChanged: {
if (unpinnedItems.length == 0) root.closeOverflowMenu();
}
diff --git a/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml b/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml
index 1fe5df5f3..6230de0f8 100644
--- a/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml
+++ b/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml
@@ -1,11 +1,12 @@
-import qs.modules.common
-import qs.modules.common.widgets
-import qs.modules.common.functions
import QtQuick
import Quickshell
import Quickshell.Services.SystemTray
import Quickshell.Widgets
import Qt5Compat.GraphicalEffects
+import qs.services
+import qs.modules.common
+import qs.modules.common.widgets
+import qs.modules.common.functions
MouseArea {
id: root
@@ -31,10 +32,7 @@ MouseArea {
event.accepted = true;
}
onEntered: {
- tooltip.text = item.tooltipTitle.length > 0 ? item.tooltipTitle
- : (item.title.length > 0 ? item.title : item.id);
- if (item.tooltipDescription.length > 0) tooltip.text += " • " + item.tooltipDescription;
- if (Config.options.bar.tray.showItemId) tooltip.text += "\n[" + item.id + "]";
+ tooltip.text = TrayService.getTooltipForItem(root.item);
}
Loader {
@@ -65,7 +63,7 @@ MouseArea {
IconImage {
id: trayIcon
- visible: !Config.options.bar.tray.monochromeIcons
+ visible: !Config.options.tray.monochromeIcons
source: root.item.icon
anchors.centerIn: parent
width: parent.width
@@ -73,7 +71,7 @@ MouseArea {
}
Loader {
- active: Config.options.bar.tray.monochromeIcons
+ active: Config.options.tray.monochromeIcons
anchors.fill: trayIcon
sourceComponent: Item {
Desaturate {
diff --git a/dots/.config/quickshell/ii/modules/ii/bar/weather/WeatherBar.qml b/dots/.config/quickshell/ii/modules/ii/bar/weather/WeatherBar.qml
index 1fcde7176..e82f41dab 100644
--- a/dots/.config/quickshell/ii/modules/ii/bar/weather/WeatherBar.qml
+++ b/dots/.config/quickshell/ii/modules/ii/bar/weather/WeatherBar.qml
@@ -13,15 +13,19 @@ MouseArea {
implicitWidth: rowLayout.implicitWidth + 10 * 2
implicitHeight: Appearance.sizes.barHeight
- hoverEnabled: true
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ hoverEnabled: !Config.options.bar.tooltips.clickToShow
onPressed: {
- Weather.getData();
- Quickshell.execDetached(["notify-send",
- Translation.tr("Weather"),
- Translation.tr("Refreshing (manually triggered)")
- , "-a", "Shell"
- ])
+ if (mouse.button === Qt.RightButton) {
+ Weather.getData();
+ Quickshell.execDetached(["notify-send",
+ Translation.tr("Weather"),
+ Translation.tr("Refreshing (manually triggered)")
+ , "-a", "Shell"
+ ])
+ mouse.accepted = false
+ }
}
RowLayout {
diff --git a/dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml b/dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml
index f44efcb3e..d133fa654 100644
--- a/dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml
+++ b/dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml
@@ -5,7 +5,6 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
-import Qt.labs.synchronizer
import Quickshell.Io
import Quickshell
import Quickshell.Wayland
diff --git a/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml b/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml
index 41ed8cd07..8d2d270ae 100644
--- a/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml
+++ b/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml
@@ -67,11 +67,7 @@ DockButton {
}
altAction: () => {
- if (Config.options.dock.pinnedApps.indexOf(appToplevel.appId) !== -1) {
- Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.filter(id => id !== appToplevel.appId)
- } else {
- Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.concat([appToplevel.appId])
- }
+ TaskbarApps.togglePin(appToplevel.appId);
}
contentItem: Loader {
diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/Overlay.qml b/dots/.config/quickshell/ii/modules/ii/overlay/Overlay.qml
index 71ba510c6..65901ea13 100644
--- a/dots/.config/quickshell/ii/modules/ii/overlay/Overlay.qml
+++ b/dots/.config/quickshell/ii/modules/ii/overlay/Overlay.qml
@@ -25,7 +25,8 @@ Scope {
exclusionMode: ExclusionMode.Ignore
WlrLayershell.namespace: "quickshell:overlay"
WlrLayershell.layer: WlrLayer.Overlay
- WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
+ // Use OnDemand for pinned widgets to allow focus switching with mouse clicks
+ WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : (OverlayContext.clickableWidgets.length > 0 ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None)
visible: true
color: "transparent"
diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml
index 15e1ef91b..bb68cefc3 100644
--- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml
+++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml
@@ -11,6 +11,7 @@ Singleton {
{ identifier: "floatingImage", materialSymbol: "imagesmode" },
{ identifier: "recorder", materialSymbol: "screen_record" },
{ identifier: "resources", materialSymbol: "browse_activity" },
+ { identifier: "notes", materialSymbol: "note_stack" },
{ identifier: "volumeMixer", materialSymbol: "volume_up" },
]
diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml
index 6e4bc6522..e004be7dd 100644
--- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml
+++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml
@@ -8,10 +8,11 @@ import Quickshell
import Quickshell.Bluetooth
import qs.modules.ii.overlay.crosshair
import qs.modules.ii.overlay.volumeMixer
+import qs.modules.ii.overlay.floatingImage
import qs.modules.ii.overlay.fpsLimiter
import qs.modules.ii.overlay.recorder
import qs.modules.ii.overlay.resources
-import qs.modules.ii.overlay.floatingImage
+import qs.modules.ii.overlay.notes
DelegateChooser {
id: root
@@ -22,5 +23,6 @@ DelegateChooser {
DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} }
DelegateChoice { roleValue: "recorder"; Recorder {} }
DelegateChoice { roleValue: "resources"; Resources {} }
+ DelegateChoice { roleValue: "notes"; Notes {} }
DelegateChoice { roleValue: "volumeMixer"; VolumeMixer {} }
}
diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml b/dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml
new file mode 100644
index 000000000..64aa11d05
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml
@@ -0,0 +1,17 @@
+import QtQuick
+import QtQuick.Layouts
+import Quickshell
+import qs.services
+import qs.modules.common
+import qs.modules.ii.overlay
+
+StyledOverlayWidget {
+ id: root
+ title: Translation.tr("Notes")
+ showCenterButton: true
+
+ contentItem: NotesContent {
+ radius: root.contentRadius
+ isClickthrough: root.clickthrough
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml
new file mode 100644
index 000000000..e52c226b1
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml
@@ -0,0 +1,292 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Quickshell
+import Quickshell.Io
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.common.widgets
+import qs.modules.ii.overlay
+
+OverlayBackground {
+ id: root
+
+ property alias content: textInput.text
+ property bool pendingReload: false
+ property var copyListEntries: []
+ property string lastParsedCopylistText: ""
+ property var parsedCopylistLines: []
+ property bool isClickthrough: false
+ property real maxCopyButtonSize: 20
+
+ Component.onCompleted: {
+ noteFile.reload();
+ updateCopyListEntries();
+ }
+
+ function saveContent() {
+ if (!textInput)
+ return;
+ noteFile.setText(root.content);
+ }
+
+ function focusAtEnd() {
+ if (!textInput)
+ return;
+ textInput.forceActiveFocus();
+ const endPos = root.content.length;
+ applySelection(endPos, endPos);
+ }
+
+ function applySelection(cursorPos, anchorPos) {
+ if (!textInput)
+ return;
+ const textLength = root.content.length;
+ const cursor = Math.max(0, Math.min(cursorPos, textLength));
+ const anchor = Math.max(0, Math.min(anchorPos, textLength));
+ textInput.select(anchor, cursor);
+ if (cursor === anchor)
+ textInput.deselect();
+ }
+
+ function scheduleCopylistUpdate(immediate = false) {
+ if (!textInput)
+ return;
+ if (immediate) {
+ copyListDebounce?.stop();
+ updateCopyListEntries();
+ } else {
+ copyListDebounce.restart();
+ }
+ }
+
+ function updateCopyListEntries() {
+ if (!textInput)
+ return;
+ const textValue = root.content;
+ if (!textValue || textValue.length === 0) {
+ lastParsedCopylistText = "";
+ parsedCopylistLines = [];
+ root.copyListEntries = [];
+ return;
+ }
+
+ if (textValue !== lastParsedCopylistText) {
+ const lineRegex = /(.*?)(\r?\n|$)/g;
+ let match = null;
+ const parsed = [];
+ while ((match = lineRegex.exec(textValue)) !== null) {
+ const lineText = match[1];
+ const newlineText = match[2];
+ const lineStart = match.index;
+ const lineEnd = lineStart + lineText.length;
+ const bulletMatch = lineText.match(/^\s*-\s+(.*\S)\s*$/);
+ if (bulletMatch) {
+ parsed.push({
+ content: bulletMatch[1].trim(),
+ start: lineStart,
+ end: lineEnd
+ });
+ }
+ if (newlineText === "")
+ break;
+ }
+ lastParsedCopylistText = textValue;
+ parsedCopylistLines = parsed;
+ if (parsed.length === 0) {
+ root.copyListEntries = [];
+ return;
+ }
+ }
+
+ updateCopylistPositions();
+ }
+
+ function updateCopylistPositions() {
+ if (!textInput || parsedCopylistLines.length === 0)
+ return;
+ const rawSelectionStart = textInput.selectionStart;
+ const rawSelectionEnd = textInput.selectionEnd;
+ const selectionStart = rawSelectionStart === -1 ? textInput.cursorPosition : rawSelectionStart;
+ const selectionEnd = rawSelectionEnd === -1 ? textInput.cursorPosition : rawSelectionEnd;
+ const rangeStart = Math.min(selectionStart, selectionEnd);
+ const rangeEnd = Math.max(selectionStart, selectionEnd);
+
+ const entries = parsedCopylistLines.map(line => {
+ // Don't show copy button if line is (partially) selected
+ const caretIntersects = rangeEnd > line.start && rangeStart <= line.end;
+ if (caretIntersects)
+ return null;
+ const startRect = textInput.positionToRectangle(line.start);
+ let endRect = textInput.positionToRectangle(line.end);
+ if (!isFinite(startRect.y))
+ return null;
+ if (!isFinite(endRect.y))
+ endRect = startRect;
+ const lineBottom = endRect.y + endRect.height;
+ const rectHeight = Math.max(lineBottom - startRect.y, textInput.font.pixelSize + 8);
+ return {
+ content: line.content,
+ y: startRect.y,
+ height: rectHeight
+ };
+ }).filter(entry => entry !== null);
+
+ root.copyListEntries = entries;
+ }
+
+ implicitWidth: 300
+ implicitHeight: 200
+
+ ColumnLayout {
+ id: contentItem
+ anchors.fill: parent
+ spacing: -16
+
+ ScrollView {
+ id: editorScrollView
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ clip: true
+ ScrollBar.vertical.policy: ScrollBar.AsNeeded
+ onWidthChanged: root.scheduleCopylistUpdate(true)
+
+ StyledTextArea { // This has to be a direct child of ScrollView for proper scrolling
+ id: textInput
+ anchors {
+ left: parent.left
+ right: parent.right
+ }
+ wrapMode: TextEdit.Wrap
+ placeholderText: Translation.tr("Write something here...\nUse '-' to create copyable bullet points, like this:\n\nSheep fricker\n- 4x Slab\n- 1x Boat\n- 4x Redstone Dust\n- 1x Sticky Piston\n- 1x End Rod\n- 4x Redstone Repeater\n- 1x Redstone Torch\n- 1x Sheep")
+ selectByMouse: true
+ persistentSelection: true
+ textFormat: TextEdit.PlainText
+ background: null
+ padding: 24
+
+ onTextChanged: {
+ if (textInput.activeFocus) {
+ saveDebounce.restart();
+ }
+ root.scheduleCopylistUpdate(true);
+ }
+
+ onHeightChanged: root.scheduleCopylistUpdate(true)
+ onContentHeightChanged: root.scheduleCopylistUpdate(true)
+ onCursorPositionChanged: root.scheduleCopylistUpdate()
+ onSelectionStartChanged: root.scheduleCopylistUpdate()
+ onSelectionEndChanged: root.scheduleCopylistUpdate()
+ }
+
+ Item {
+ anchors.fill: parent
+ visible: root.copyListEntries.length > 0
+ clip: true
+
+ Repeater {
+ model: ScriptModel {
+ values: root.copyListEntries
+ }
+ delegate: RippleButton {
+ id: copyButton
+ required property var modelData
+ readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), root.maxCopyButtonSize)
+ readonly property real iconSizeLocal: Appearance.font.pixelSize.normal
+ readonly property real hitPadding: 6
+ property bool justCopied: false
+
+ implicitHeight: lineHeight
+ implicitWidth: lineHeight
+ buttonRadius: height / 2
+ y: modelData.y
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ z: 5
+
+ Timer {
+ id: resetState
+ interval: 700
+ onTriggered: {
+ copyButton.justCopied = false;
+ }
+ }
+
+ onClicked: {
+ Quickshell.clipboardText = copyButton.modelData.content;
+ justCopied = true;
+ resetState.start();
+ }
+
+ contentItem: Item {
+ anchors.centerIn: parent
+ MaterialSymbol {
+ id: iconItem
+ anchors.centerIn: parent
+ text: copyButton.justCopied ? "check" : "content_copy"
+ iconSize: copyButton.iconSizeLocal
+ color: Appearance.colors.colOnLayer1
+ }
+ }
+ }
+ }
+ }
+ }
+
+ StyledText {
+ id: statusLabel
+ Layout.fillWidth: true
+ Layout.margins: 16
+ horizontalAlignment: Text.AlignRight
+ text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved ")
+ color: Appearance.colors.colSubtext
+ }
+ }
+
+ Timer {
+ id: saveDebounce
+ interval: 500
+ repeat: false
+ onTriggered: saveContent()
+ }
+
+ Timer {
+ id: copyListDebounce
+ interval: 100
+ repeat: false
+ onTriggered: updateCopylistPositions()
+ }
+
+ FileView {
+ id: noteFile
+ path: Qt.resolvedUrl(Directories.notesPath)
+ onLoaded: {
+ root.content = noteFile.text();
+ if (root.content !== root.content) {
+ const previousCursor = textInput.cursorPosition;
+ const previousAnchor = textInput.selectionStart;
+ root.content = root.content;
+ applySelection(previousCursor, previousAnchor);
+ }
+ if (pendingReload) {
+ pendingReload = false;
+ Qt.callLater(root.focusAtEnd);
+ }
+ Qt.callLater(root.updateCopyListEntries);
+ }
+ onLoadFailed: error => {
+ if (error === FileViewError.FileNotFound) {
+ root.content = "";
+ noteFile.setText(root.content);
+ if (pendingReload) {
+ pendingReload = false;
+ Qt.callLater(root.focusAtEnd);
+ }
+ Qt.callLater(root.updateCopyListEntries);
+ } else {
+ console.log("[Overlay Notes] Error loading file: " + error);
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/resources/Resources.qml b/dots/.config/quickshell/ii/modules/ii/overlay/resources/Resources.qml
index 8bec779bd..512307fc1 100644
--- a/dots/.config/quickshell/ii/modules/ii/overlay/resources/Resources.qml
+++ b/dots/.config/quickshell/ii/modules/ii/overlay/resources/Resources.qml
@@ -5,7 +5,6 @@ import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
import Qt5Compat.GraphicalEffects
-import Qt.labs.synchronizer
import qs
import qs.services
import qs.modules.common
diff --git a/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml b/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml
index 6385b2485..248b46b56 100644
--- a/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml
+++ b/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml
@@ -167,6 +167,9 @@ Scope {
function toggle() {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
}
+ function workspacesToggle() {
+ GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
+ }
function close() {
GlobalStates.overviewOpen = false;
}
@@ -189,6 +192,14 @@ Scope {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
}
}
+ GlobalShortcut {
+ name: "overviewWorkspacesToggle"
+ description: "Toggles overview on press"
+
+ onPressed: {
+ GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
+ }
+ }
GlobalShortcut {
name: "overviewClose"
description: "Closes overview"
diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml
index 74d5c5f6a..487665851 100644
--- a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml
+++ b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml
@@ -285,48 +285,36 @@ Rectangle {
}
}
}
-
Repeater {
model: ScriptModel {
- values: Array.from({ length: root.messageBlocks.length }, (msg, i) => {
- return ({
- type: root.messageBlocks[i].type
- })
- });
+ values: root.messageBlocks
}
-
delegate: DelegateChooser {
id: messageDelegate
role: "type"
DelegateChoice { roleValue: "code"; MessageCodeBlock {
- required property int index
- property var thisBlock: root.messageBlocks[index]
editing: root.editing
renderMarkdown: root.renderMarkdown
enableMouseSelection: root.enableMouseSelection
- segmentContent: thisBlock.content
- segmentLang: thisBlock.lang
+ segmentContent: modelData.content
+ segmentLang: modelData.lang
messageData: root.messageData
} }
DelegateChoice { roleValue: "think"; MessageThinkBlock {
- required property int index
- property var thisBlock: root.messageBlocks[index]
editing: root.editing
renderMarkdown: root.renderMarkdown
enableMouseSelection: root.enableMouseSelection
- segmentContent: thisBlock.content
+ segmentContent: modelData.content
messageData: root.messageData
done: root.messageData?.done ?? false
- completed: thisBlock.completed ?? false
+ completed: modelData.completed ?? false
} }
DelegateChoice { roleValue: "text"; MessageTextBlock {
- required property int index
- property var thisBlock: root.messageBlocks[index]
editing: root.editing
renderMarkdown: root.renderMarkdown
enableMouseSelection: root.enableMouseSelection
- segmentContent: thisBlock.content
+ segmentContent: modelData.content
messageData: root.messageData
done: root.messageData?.done ?? false
forceDisableChunkSplitting: root.messageData?.content.includes("```") ?? true
diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml
index 1463c6e60..ee00ffdff 100644
--- a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml
+++ b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml
@@ -156,7 +156,6 @@ Item {
property bool editing: root.editing
property bool renderMarkdown: root.renderMarkdown
property bool enableMouseSelection: root.enableMouseSelection
- property string segmentContent: root.segmentContent
property var messageData: root.messageData
property bool done: root.done
@@ -165,8 +164,9 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
+ segmentContent: root.segmentContent
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml
index ae76d5751..d592de63b 100644
--- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml
+++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml
@@ -12,6 +12,7 @@ AndroidQuickToggleButton {
name: Translation.tr("Bluetooth")
statusText: BluetoothStatus.firstActiveDevice?.name ?? Translation.tr("No device")
+ available: BluetoothStatus.available
toggled: BluetoothStatus.enabled
buttonIcon: BluetoothStatus.connected ? "bluetooth_connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth_disabled"
mainAction: () => {
@@ -27,4 +28,3 @@ AndroidQuickToggleButton {
)
}
}
-
diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml
index bfd14335c..0ce6b7ab4 100644
--- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml
+++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml
@@ -9,6 +9,7 @@ AndroidQuickToggleButton {
name: Translation.tr("EasyEffects")
+ available: EasyEffects.available
toggled: EasyEffects.active
buttonIcon: "graphic_eq"
diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml
index 96401a6c0..31ad2f262 100644
--- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml
+++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml
@@ -15,6 +15,7 @@ GroupButton {
required property string name
required property var mainAction
property string statusText: toggled ? Translation.tr("Active") : Translation.tr("Inactive")
+ property bool available: true
required property real baseCellWidth
required property real baseCellHeight
@@ -42,6 +43,7 @@ GroupButton {
signal openMenu()
+ enabled: available || editMode
padding: 6
horizontalPadding: padding
verticalPadding: padding
@@ -52,8 +54,8 @@ GroupButton {
colBackgroundToggledActive: (altAction && expandedSize) ? Appearance.colors.colLayer2Active : Appearance.colors.colPrimaryActive
buttonRadius: toggled ? Appearance.rounding.large : height / 2
buttonRadiusPressed: Appearance.rounding.normal
- property color colText: (toggled && !(altAction && expandedSize)) ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer2
- property color colIcon: expandedSize ? (root.toggled ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer3) : colText
+ property color colText: (toggled && !(altAction && expandedSize) && enabled) ? Appearance.colors.colOnPrimary : ColorUtils.transparentize(Appearance.colors.colOnLayer2, enabled ? 0 : 0.7)
+ property color colIcon: expandedSize ? ((root.toggled) ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer3) : colText
onClicked: {
if (root.expandedSize && root.altAction) root.altAction();
diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/BatteryIndicator.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/BatteryIndicator.qml
index d2b729244..3f20cbd2c 100644
--- a/dots/.config/quickshell/ii/modules/ii/verticalBar/BatteryIndicator.qml
+++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/BatteryIndicator.qml
@@ -15,7 +15,7 @@ MouseArea {
readonly property bool isLow: percentage <= Config.options.battery.low / 100
implicitHeight: batteryProgress.implicitHeight
- hoverEnabled: true
+ hoverEnabled: !Config.options.bar.tooltips.clickToShow
ClippedProgressBar {
id: batteryProgress
diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/Resources.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/Resources.qml
index 353874723..1c3815721 100644
--- a/dots/.config/quickshell/ii/modules/ii/verticalBar/Resources.qml
+++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/Resources.qml
@@ -9,7 +9,7 @@ MouseArea {
property bool alwaysShowAllResources: false
implicitHeight: columnLayout.implicitHeight
implicitWidth: columnLayout.implicitWidth
- hoverEnabled: true
+ hoverEnabled: !Config.options.bar.tooltips.clickToShow
ColumnLayout {
id: columnLayout
diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml
index 15a49c5a5..3f9ca818a 100644
--- a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml
+++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml
@@ -33,8 +33,7 @@ Item {
MouseArea {
id: mouseArea
anchors.fill: parent
- hoverEnabled: true
- acceptedButtons: Qt.NoButton
+ hoverEnabled: !Config.options.bar.tooltips.clickToShow
Bar.ClockWidgetPopup {
hoverTarget: mouseArea
diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalMedia.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalMedia.qml
index 8d38caa76..4db432b26 100644
--- a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalMedia.qml
+++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalMedia.qml
@@ -28,7 +28,7 @@ MouseArea {
}
acceptedButtons: Qt.MiddleButton | Qt.BackButton | Qt.ForwardButton | Qt.RightButton | Qt.LeftButton
- hoverEnabled: true
+ hoverEnabled: !Config.options.bar.tooltips.clickToShow
onPressed: (event) => {
if (event.button === Qt.MiddleButton) {
activePlayer.togglePlaying();
diff --git a/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml b/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml
index ec9dc320d..66630cc24 100644
--- a/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml
+++ b/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml
@@ -55,6 +55,20 @@ ContentPage {
ContentSection {
icon: "clock_loader_40"
title: Translation.tr("Widget: Clock")
+ id: settingsClock
+
+ function stylePresent(styleName) {
+ if (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === styleName) {
+ return true;
+ }
+ if (Config.options.background.widgets.clock.styleLocked === styleName) {
+ return true;
+ }
+ return false;
+ }
+
+ readonly property bool digitalPresent: stylePresent("digital")
+ readonly property bool cookiePresent: stylePresent("cookie")
ConfigRow {
Layout.fillWidth: true
@@ -107,6 +121,7 @@ ContentPage {
}
ContentSubsection {
+ visible: !Config.options.background.widgets.clock.showOnlyWhenLocked
title: Translation.tr("Clock style")
ConfigSelectionArray {
currentValue: Config.options.background.widgets.clock.style
@@ -129,7 +144,29 @@ ContentPage {
}
ContentSubsection {
- visible: Config.options.background.widgets.clock.style === "digital"
+ title: Translation.tr("Clock style (locked)")
+ ConfigSelectionArray {
+ currentValue: Config.options.background.widgets.clock.styleLocked
+ onSelected: newValue => {
+ Config.options.background.widgets.clock.styleLocked = newValue;
+ }
+ options: [
+ {
+ displayName: Translation.tr("Digital"),
+ icon: "timer_10",
+ value: "digital"
+ },
+ {
+ displayName: Translation.tr("Cookie"),
+ icon: "cookie",
+ value: "cookie"
+ }
+ ]
+ }
+ }
+
+ ContentSubsection {
+ visible: settingsClock.digitalPresent
title: Translation.tr("Digital clock settings")
ConfigSwitch {
@@ -143,7 +180,7 @@ ContentPage {
}
ContentSubsection {
- visible: Config.options.background.widgets.clock.style === "cookie"
+ visible: settingsClock.cookiePresent
title: Translation.tr("Cookie clock settings")
ConfigSwitch {
@@ -197,7 +234,7 @@ ContentPage {
ConfigRow {
ConfigSwitch {
- enabled: Config.options.background.widgets.clock.style === "cookie" && Config.options.background.widgets.clock.cookie.dialNumberStyle === "dots" || Config.options.background.widgets.clock.cookie.dialNumberStyle === "full"
+ enabled: Config.options.background.widgets.clock.cookie.dialNumberStyle === "dots" || Config.options.background.widgets.clock.cookie.dialNumberStyle === "full"
buttonIcon: "brightness_7"
text: Translation.tr("Hour marks")
checked: Config.options.background.widgets.clock.cookie.hourMarks
@@ -213,7 +250,7 @@ ContentPage {
}
ConfigSwitch {
- enabled: Config.options.background.widgets.clock.style === "cookie" && Config.options.background.widgets.clock.cookie.dialNumberStyle !== "numbers"
+ enabled: Config.options.background.widgets.clock.cookie.dialNumberStyle !== "numbers"
buttonIcon: "timer_10"
text: Translation.tr("Digits in the middle")
checked: Config.options.background.widgets.clock.cookie.timeIndicators
@@ -231,7 +268,7 @@ ContentPage {
}
ContentSubsection {
- visible: Config.options.background.widgets.clock.style === "cookie"
+ visible: settingsClock.cookiePresent
title: Translation.tr("Dial style")
ConfigSelectionArray {
currentValue: Config.options.background.widgets.clock.cookie.dialNumberStyle
@@ -270,7 +307,7 @@ ContentPage {
}
ContentSubsection {
- visible: Config.options.background.widgets.clock.style === "cookie"
+ visible: settingsClock.cookiePresent
title: Translation.tr("Hour hand")
ConfigSelectionArray {
currentValue: Config.options.background.widgets.clock.cookie.hourHandStyle
@@ -303,7 +340,7 @@ ContentPage {
}
ContentSubsection {
- visible: Config.options.background.widgets.clock.style === "cookie"
+ visible: settingsClock.cookiePresent
title: Translation.tr("Minute hand")
ConfigSelectionArray {
@@ -342,7 +379,7 @@ ContentPage {
}
ContentSubsection {
- visible: Config.options.background.widgets.clock.style === "cookie"
+ visible: settingsClock.cookiePresent
title: Translation.tr("Second hand")
ConfigSelectionArray {
@@ -376,7 +413,7 @@ ContentPage {
}
ContentSubsection {
- visible: Config.options.background.widgets.clock.style === "cookie"
+ visible: settingsClock.cookiePresent
title: Translation.tr("Date style")
ConfigSelectionArray {
diff --git a/dots/.config/quickshell/ii/modules/settings/BarConfig.qml b/dots/.config/quickshell/ii/modules/settings/BarConfig.qml
index a53d30644..bfe4c256e 100644
--- a/dots/.config/quickshell/ii/modules/settings/BarConfig.qml
+++ b/dots/.config/quickshell/ii/modules/settings/BarConfig.qml
@@ -148,18 +148,18 @@ ContentPage {
ConfigSwitch {
buttonIcon: "keep"
text: Translation.tr('Make icons pinned by default')
- checked: Config.options.bar.tray.invertPinnedItems
+ checked: Config.options.tray.invertPinnedItems
onCheckedChanged: {
- Config.options.bar.tray.invertPinnedItems = checked;
+ Config.options.tray.invertPinnedItems = checked;
}
}
ConfigSwitch {
buttonIcon: "colors"
text: Translation.tr('Tint icons')
- checked: Config.options.bar.tray.monochromeIcons
+ checked: Config.options.tray.monochromeIcons
onCheckedChanged: {
- Config.options.bar.tray.monochromeIcons = checked;
+ Config.options.tray.monochromeIcons = checked;
}
}
}
@@ -334,4 +334,17 @@ ContentPage {
}
}
}
+
+ ContentSection {
+ icon: "tooltip"
+ title: Translation.tr("Tooltips")
+ ConfigSwitch {
+ buttonIcon: "ads_click"
+ text: Translation.tr("Click to show")
+ checked: Config.options.bar.tooltips.clickToShow
+ onCheckedChanged: {
+ Config.options.bar.tooltips.clickToShow = checked;
+ }
+ }
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml b/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml
index 738578585..1614ec47f 100644
--- a/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml
+++ b/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml
@@ -22,7 +22,7 @@ ContentPage {
// Use a nerdfont to see the icons
options: ([
"", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "⌘", "", "", ""
+ "", "", "", "", "", "", "⌘", "", "", ""
]).map(icon => { return {
displayName: icon,
value: icon
diff --git a/dots/.config/quickshell/ii/modules/waffle/README.md b/dots/.config/quickshell/ii/modules/waffle/README.md
new file mode 100644
index 000000000..299635be9
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/README.md
@@ -0,0 +1,37 @@
+## Waffle
+
+A recreation of Windoes. It's WIP!
+
+- If you install illogical-impulse fully, you can press Super+Alt+W to switch to this style.
+- If you're just copying the Quickshell config, run the config as usual (`qs -c ii`) then run `qs -c ii ipc call panelFamily cycle`
+
+## From EWW version to Quickshell
+
+Just a reflection, in case anyone's interested. My blog is probably a better place for this, but it does not exist. Besides, this is going to change as I do more stuff. Currently there's just the bar.
+
+### Improvements
+
+- QtQuick's `Button` has the `{top/bottom/left/right}Inset` properties, so we can have clickable regions expanding beyond the button background for free. With EWW it was annoying to wrap the button content with an `eventbox` that has some padding, then somehow use CSS selectors to make sure hovering effects work. I have to admit, (a large) part of that annoyance was with how bad my copy-pasting coding practice was at the time, but still...
+
+- Fancy effects: Gtk3 CSS does not support transformations. In QtQuick we can smack `rotation` and `scale` almost everywhere, so it's simple to make bouncy icons and rotating chevrons
+
+- Quickshell provides a system tray service (EWW does now but didn't at the time I created the EWW Windoes version), so now there's no Waybar needed for the tray.
+
+- QtQuick has `Loader`s, so we can have this live-switchable from the main style without killing the widget system, moving styles to the correct folder, and relaunching.
+
+- This time my computer is powerful enough to run a VM, so I don't have to occasionally reboot to take quick screenshots for reference. I try to make everything pixel-perfect so this is necessary. Speaking about pixel-perfectness, in the EWW version I hardcoded sizes, but this time I'm still doing that (lol), BUT that's normal and not a problem because Qt has the `QT_SCALE_FACTOR` env var for scaling. (Please feel free to prove me wrong in saying Gtk3 doesn't have that magic)
+
+### Challenges
+
+- Qt is not Gtk and definitely not React
+ - We don't get directional border on QtQuick `Rectangle`s like in CSS. I was able to get around this with manual drawing, but it was a bit more work
+
+- Fluent Icons is difficult to use, compared to Material Symbols
+ - No React, so no clean use via a library.
+ - If we use the font, there's no proper, searchable **codepoint** cheatsheet like Nerd Fonts, and there's no ligatures
+ - I resorted to downloading individual SVGs. Not that nice, but it's better than scanning the whole table of icons every time I want one. For this we have fluenticon.com and fluenticons.co, but icons are awkwardly named and there's no alias. Why is the reload/refresh icon called "arrow-sync"? Well, the name is not misleading, but arguably reload/refresh are more common actions. From Fluent Design's [page on Iconography](https://fluent2.microsoft.design/iconography):
+
+ > Fluent system icons are literal metaphors and are named for the shape or object they represent, not the functionality they provide
+
+ "sync" is functionality.
+
diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml
new file mode 100644
index 000000000..6d2e528db
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml
@@ -0,0 +1,77 @@
+import QtQuick
+import QtQuick.Layouts
+import Quickshell
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+WBarAttachedPanelContent {
+ id: root
+
+ contentItem: ColumnLayout {
+ anchors.centerIn: parent
+ spacing: 0
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ topLeftRadius: root.border.radius - root.border.border.width
+ topRightRadius: topLeftRadius
+ color: Looks.colors.bgPanelBody
+
+ implicitWidth: 360
+ implicitHeight: 380
+ }
+
+ Rectangle {
+ Layout.fillHeight: false
+ Layout.fillWidth: true
+ color: Looks.colors.bgPanelSeparator
+ implicitHeight: 1
+ }
+
+ Rectangle {
+ Layout.fillHeight: false
+ Layout.fillWidth: true
+ bottomLeftRadius: root.border.radius - root.border.border.width
+ bottomRightRadius: bottomLeftRadius
+ color: Looks.colors.bgPanelFooter
+
+ implicitWidth: 360
+ implicitHeight: 47
+
+ // Battery button
+ WPanelFooterButton {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 12
+
+ contentItem: Row {
+ spacing: 4
+
+ FluentIcon {
+ anchors.verticalCenter: parent.verticalCenter
+ icon: WIcons.batteryIcon
+ }
+ WText {
+ anchors.verticalCenter: parent.verticalCenter
+ text: `${Math.round(Battery.percentage * 100) || 0}%`
+ }
+ }
+ }
+
+ // Settings button
+ WPanelFooterButton {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 12
+
+ contentItem: FluentIcon {
+ icon: "settings"
+ }
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml
new file mode 100644
index 000000000..86e610238
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml
@@ -0,0 +1,85 @@
+import QtQuick
+import Quickshell
+import Quickshell.Io
+import Quickshell.Wayland
+import Quickshell.Hyprland
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.common.widgets
+
+Scope {
+ id: root
+
+ Connections {
+ target: GlobalStates
+
+ function onSidebarLeftOpenChanged() {
+ if (GlobalStates.sidebarLeftOpen) barLoader.active = true;
+ }
+ }
+
+ Loader {
+ id: barLoader
+ active: GlobalStates.sidebarLeftOpen
+ sourceComponent: PanelWindow {
+ id: panelWindow
+ exclusiveZone: 0
+ WlrLayershell.namespace: "quickshell:actionCenter"
+ WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
+ color: "transparent"
+
+ anchors {
+ bottom: Config.options.waffles.bar.bottom
+ top: !Config.options.waffles.bar.bottom
+ right: true
+ }
+
+ implicitWidth: content.implicitWidth + content.visualMargin * 2
+ implicitHeight: content.implicitHeight + content.visualMargin * 2
+
+ HyprlandFocusGrab {
+ id: focusGrab
+ active: true
+ windows: [panelWindow]
+ onCleared: content.close();
+ }
+
+ Connections {
+ target: GlobalStates
+ function onSidebarLeftOpenChanged() {
+ if (!GlobalStates.sidebarLeftOpen) content.close();
+ }
+ }
+
+ ActionCenterContent {
+ id: content
+ anchors.centerIn: parent
+
+ onClosed: {
+ barLoader.active = false;
+ GlobalStates.sidebarLeftOpen = false;
+ }
+ }
+ }
+ }
+
+ function toggleOpen() {
+ GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen;
+ }
+
+ IpcHandler {
+ target: "sidebarLeft"
+
+ function toggle() {
+ root.toggleOpen();
+ }
+ }
+
+ GlobalShortcut {
+ name: "sidebarLeftToggle"
+ description: "Toggles left sidebar on press"
+
+ onPressed: root.toggleOpen();
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
index a35e12a2e..7f527c97d 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
@@ -17,10 +17,12 @@ BarButton {
rightInset: 2
implicitWidth: height - topInset - bottomInset + leftInset + rightInset
+ property real pressedScale: 5/6
+
onDownChanged: {
scaleAnim.duration = root.down ? 150 : 200
scaleAnim.easing.bezierCurve = root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut
- contentItem.scale = root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25
+ contentItem.scale = root.down ? root.pressedScale : 1 // If/When we do dragging, the scale is 1.25
}
background: Item {
@@ -45,9 +47,7 @@ BarButton {
anchors.fill: parent
anchors.rightMargin: 5
active: root.multiple
- sourceComponent: BackgroundAcrylicRectangle {
-
- }
+ sourceComponent: BackgroundAcrylicRectangle {}
}
}
@@ -75,7 +75,7 @@ BarButton {
component BackgroundAcrylicRectangle: AcrylicRectangle {
shiny: ((root.hovered && !root.down) || root.checked)
- color: root.colBackground
+ color: root.color
border.width: 1
border.color: root.colBackgroundBorder
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
index f70a80603..48ff26104 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
@@ -13,6 +13,8 @@ Kirigami.Icon {
property real implicitSize: 26
implicitWidth: implicitSize
implicitHeight: implicitSize
+
+ animated: true
roundToIconSize: false
fallback: root.iconName
source: tryCustomIcon ? `${Looks.iconsPath}/${root.iconName}${!root.separateLightDark ? "" : Looks.dark ? "-dark" : "-light"}.svg` : fallback
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
index ce1a4cdc7..f8192389a 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
@@ -8,11 +8,14 @@ import qs.modules.waffle.looks
Button {
id: root
- signal altAction()
- signal middleClickAction()
+ property var altAction: () => {}
+ property var middleClickAction: () => {}
- property color colBackground
+ property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
+ property color colBackgroundHover: Looks.colors.bg1Hover
+ property color colBackgroundActive: Looks.colors.bg1Active
property color colBackgroundBorder
+ property color color
Layout.fillHeight: true
topInset: 4
bottomInset: 4
@@ -37,16 +40,16 @@ Button {
}
}
- colBackground: {
+ colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, (root.checked || root.hovered) ? Looks.contentTransparency : 1)
+ color: {
if (root.down) {
- return Looks.colors.bg1Active
+ return root.colBackgroundActive
} else if ((root.hovered && !root.down) || root.checked) {
- return Looks.colors.bg1Hover
+ return root.colBackgroundHover
} else {
- return ColorUtils.transparentize(Looks.colors.bg1)
+ return root.colBackground
}
}
- colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, root.checked ? Looks.contentTransparency : 1)
MouseArea {
anchors.fill: parent
@@ -66,7 +69,8 @@ Button {
background: AcrylicRectangle {
shiny: ((root.hovered && !root.down) || root.checked)
- color: root.colBackground
+ color: root.color
+ radius: Looks.radius.medium
border.width: 1
border.color: root.colBackgroundBorder
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml
new file mode 100644
index 000000000..311e5e4c9
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml
@@ -0,0 +1,41 @@
+import QtQuick
+import Quickshell
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+import qs.modules.waffle.bar
+
+BarButton {
+ id: root
+
+ property alias iconName: iconContent.icon
+ property alias iconSource: iconContent.source
+ property alias iconSize: iconContent.implicitSize
+ property alias iconRotation: iconContent.rotation
+ property alias iconMonochrome: iconContent.monochrome
+ property alias iconScale: iconContent.scale
+ property alias tooltipText: tooltip.text
+ property alias overlayingItems: iconContent.data
+
+ implicitWidth: 32
+
+ contentItem: Item {
+ anchors.centerIn: parent
+ implicitWidth: iconContent.implicitWidth
+ implicitHeight: iconContent.implicitHeight
+
+ FluentIcon {
+ id: iconContent
+ anchors.centerIn: parent
+ implicitSize: 16
+ icon: root.iconName
+ monochrome: false
+ }
+ }
+
+ BarToolTip {
+ id: tooltip
+ extraVisibleCondition: root.shouldShowTooltip && text !== ""
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml
new file mode 100644
index 000000000..871abc23f
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml
@@ -0,0 +1,59 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Quickshell
+import Quickshell.Hyprland
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+BarPopup {
+ id: root
+ default property var menuData
+ property var model: [
+ { iconName: "start-here", text: "Start", action: () => {print("hello")} },
+ { type : "separator" },
+ ]
+ readonly property bool hasIcons: model.some(item => item.iconName !== undefined && item.iconName !== "")
+ padding: 2
+
+ contentItem: ColumnLayout {
+ anchors.centerIn: parent
+ spacing: 0
+
+ Repeater {
+ model: root.model
+ delegate: DelegateChooser {
+ role: "type"
+ DelegateChoice {
+ roleValue: "separator"
+ Rectangle {
+ Layout.topMargin: 2
+ Layout.bottomMargin: 2
+ Layout.fillWidth: true
+ implicitHeight: 1
+ color: Looks.colors.bg0Border
+ }
+ }
+ DelegateChoice {
+ roleValue: undefined
+ WButton {
+ id: btn
+ Layout.fillWidth: true
+
+ required property var modelData
+ forceShowIcon: root.hasIcons
+ icon.name: modelData.iconName ? modelData.iconName : ""
+ monochromeIcon: modelData.monochromeIcon ?? true
+ text: modelData.text ? modelData.text : ""
+
+ onClicked: {
+ if (modelData.action) modelData.action();
+ root.close();
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml
new file mode 100644
index 000000000..a46811b82
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml
@@ -0,0 +1,131 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import Quickshell
+import Quickshell.Hyprland
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+Loader {
+ id: root
+
+ required property var contentItem
+ property real padding: Looks.radius.large - Looks.radius.medium
+ property bool noSmoothClosing: !Config.options.waffles.smootherAnimations
+ property bool closeOnFocusLost: true
+ signal focusCleared()
+
+ property Item anchorItem: parent
+ property real visualMargin: 12
+ readonly property bool barAtBottom: Config.options.waffles.bar.bottom
+ property real ambientShadowWidth: 1
+
+ onFocusCleared: {
+ if (!root.closeOnFocusLost) return;
+ root.close()
+ }
+
+ function grabFocus() { // Doesn't work
+ item.grabFocus();
+ }
+
+ function close() {
+ item.close();
+ }
+
+ function updateAnchor() {
+ item?.anchor.updateAnchor();
+ }
+
+ active: false
+ visible: active
+ sourceComponent: PopupWindow {
+ id: popupWindow
+ visible: true
+ Component.onCompleted: {
+ openAnim.start();
+ }
+
+ anchor {
+ adjustment: PopupAdjustment.ResizeY | PopupAdjustment.SlideX
+ item: root.anchorItem
+ gravity: root.barAtBottom ? Edges.Top : Edges.Bottom
+ edges: root.barAtBottom ? Edges.Top : Edges.Bottom
+ }
+
+ HyprlandFocusGrab {
+ id: focusGrab
+ active: true
+ windows: [popupWindow]
+ onCleared: root.focusCleared();
+ }
+
+ function close() {
+ if (root.noSmoothClosing) root.active = false;
+ else closeAnim.start();
+ }
+
+ function grabFocus() {
+ focusGrab.active = true; // Doesn't work
+ }
+
+ implicitWidth: realContent.implicitWidth + (root.ambientShadowWidth * 2) + (root.visualMargin * 2)
+ implicitHeight: realContent.implicitHeight + (root.ambientShadowWidth * 2) + (root.visualMargin * 2)
+
+ property real sourceEdgeMargin: -implicitHeight
+ PropertyAnimation {
+ id: openAnim
+ target: popupWindow
+ property: "sourceEdgeMargin"
+ to: (root.ambientShadowWidth + root.visualMargin)
+ duration: 200
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
+ }
+ SequentialAnimation {
+ id: closeAnim
+ PropertyAnimation {
+ target: popupWindow
+ property: "sourceEdgeMargin"
+ to: -implicitHeight
+ duration: 150
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut
+ }
+ ScriptAction {
+ script: {
+ root.active = false;
+ }
+ }
+ }
+
+ color: "transparent"
+ WAmbientShadow {
+ target: realContent
+ }
+
+ Rectangle {
+ id: realContent
+ z: 1
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: root.barAtBottom ? undefined : parent.top
+ bottom: root.barAtBottom ? parent.bottom : undefined
+ margins: root.ambientShadowWidth + root.visualMargin
+ // Opening anim
+ bottomMargin: root.barAtBottom ? popupWindow.sourceEdgeMargin : (root.ambientShadowWidth + root.visualMargin)
+ topMargin: root.barAtBottom ? (root.ambientShadowWidth + root.visualMargin) : popupWindow.sourceEdgeMargin
+ }
+ color: Looks.colors.bg1
+ radius: Looks.radius.large
+
+ // test
+ implicitWidth: root.contentItem.implicitWidth + (root.padding * 2)
+ implicitHeight: root.contentItem.implicitHeight + (root.padding * 2)
+
+ children: [root.contentItem]
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
index a86faaece..3e8dd6282 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
@@ -9,9 +9,10 @@ import qs.modules.waffle.looks
AppButton {
id: root
- iconName: "system-search"
+ iconName: checked ? "system-search-checked" : "system-search"
separateLightDark: true
+ checked: GlobalStates.overviewOpen
onClicked: {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now...
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
index 4595802ee..f4a15cc00 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
@@ -1,6 +1,7 @@
import QtQuick
+import QtQuick.Controls
import QtQuick.Layouts
-import org.kde.kirigami as Kirigami
+import Quickshell
import qs
import qs.services
import qs.modules.common
@@ -10,7 +11,7 @@ AppButton {
id: root
leftInset: Config.options.waffles.bar.leftAlignApps ? 12 : 0
- iconName: "start-here"
+ iconName: down ? "start-here-pressed" : "start-here"
onClicked: {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now...
@@ -21,4 +22,45 @@ AppButton {
text: Translation.tr("Start")
extraVisibleCondition: root.shouldShowTooltip
}
+
+ altAction: () => {
+ contextMenu.active = true;
+ }
+
+ BarMenu {
+ id: contextMenu
+
+ model: [
+ {
+ text: Translation.tr("Terminal"),
+ action: () => {
+ Quickshell.execDetached(["bash", "-c", Config.options.apps.terminal]);
+ }
+ },
+ {
+ text: Translation.tr("Task Manager"),
+ action: () => {
+ Quickshell.execDetached(["bash", "-c", Config.options.apps.taskManager]);
+ }
+ },
+ {
+ text: Translation.tr("Settings"),
+ action: () => {
+ Quickshell.execDetached(["qs", "-p", Quickshell.shellPath("settings.qml")]);
+ }
+ },
+ {
+ text: Translation.tr("File Explorer"),
+ action: () => {
+ Qt.openUrlExternally(Directories.home);
+ }
+ },
+ {
+ text: Translation.tr("Search"),
+ action: () => {
+ Quickshell.execDetached(["qs", "-p", Quickshell.shellPath(""), "ipc", "call", "overview", "toggle"]);
+ }
+ },
+ ]
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
index 1de9654d5..2ce1cd862 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
@@ -8,9 +8,9 @@ import qs.modules.waffle.looks
BarButton {
id: root
- checked: GlobalStates.sidebarRightOpen
+ checked: GlobalStates.sidebarLeftOpen
onClicked: {
- GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; // For now...
+ GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen;
}
contentItem: Item {
@@ -85,11 +85,13 @@ BarButton {
BarToolTip {
extraVisibleCondition: root.shouldShowTooltip && volumeHoverArea.containsMouse
text: Translation.tr("Speakers (%1): %2") //
- .arg(Audio.sink?.nickname || Audio.sink?.description || Translation.tr("Unknown")) //
- .arg(`${Math.round(Audio.sink?.audio.volume * 100) || 0}%`) //
+ .arg(Audio.sink?.nickname || Audio.sink?.description || Translation.tr("Unknown")) //
+ .arg(Audio.sink?.audio.muted ? Translation.tr("Muted") : `${Math.round(Audio.sink?.audio.volume * 100) || 0}%`) //
}
BarToolTip {
extraVisibleCondition: root.shouldShowTooltip && batteryHoverArea.containsMouse
- text: Translation.tr("Battery: %1").arg(`${Math.round(Battery.percentage * 100) || 0}%`)
+ text: Translation.tr("Battery: %1%2") //
+ .arg(`${Math.round(Battery.percentage * 100) || 0}%`) //
+ .arg(Battery.isPluggedIn ? (" " + Translation.tr("(Plugged in)")) : "")
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
index cc35c8b41..760c00608 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
@@ -9,7 +9,8 @@ import qs.modules.waffle.looks
AppButton {
id: root
- iconName: "task-view"
+ iconName: (down && !checked) ? "task-view-pressed" : "task-view"
+ pressedScale: checked ? 5/6 : 1
separateLightDark: true
checked: GlobalStates.overviewOpen
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml
new file mode 100644
index 000000000..54286ac88
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml
@@ -0,0 +1,33 @@
+import QtQuick
+import Quickshell
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+import qs.modules.waffle.bar.tray
+
+BarIconButton {
+ id: root
+
+ visible: Updates.updateAdvised || Updates.updateStronglyAdvised
+ padding: 4
+ iconName: "arrow-sync"
+ iconSize: 20 // Needed because the icon appears to have some padding
+ tooltipText: Translation.tr("Get the latest features and security improvements with\nthe newest feature update.\n\n%1 packages").arg(Updates.count)
+
+ onClicked: {
+ Quickshell.execDetached(["bash", "-c", Config.options.apps.update]);
+ }
+
+ overlayingItems: Rectangle {
+ anchors {
+ right: parent.right
+ bottom: parent.bottom
+ margins: 1
+ }
+ implicitWidth: 8
+ implicitHeight: implicitWidth
+ radius: height / 2
+ color: Updates.updateStronglyAdvised ? Looks.colors.warning : Looks.colors.accent
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
index aa5f51f68..2326a47f7 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
@@ -9,9 +9,8 @@ import qs.modules.common
import qs.modules.common.widgets
Scope {
- id: bar
- property bool showBarBackground: Config.options.bar.showBackground
-
+ id: root
+
LazyLoader {
id: barLoader
active: GlobalStates.barOpen && !GlobalStates.screenLocked
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
index aa064118a..cfbc52779 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
@@ -4,6 +4,7 @@ import qs.modules.common
import qs.modules.common.widgets
import qs.modules.waffle.looks
import qs.modules.waffle.bar.tasks
+import qs.modules.waffle.bar.tray
Rectangle {
id: root
@@ -68,6 +69,8 @@ Rectangle {
shown: Config.options.waffles.bar.leftAlignApps
sourceComponent: WidgetsButton {}
}
+ Tray {}
+ UpdatesButton {}
SystemButton {}
TimeButton {}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
index 1c6c11859..51a3175bc 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
@@ -18,6 +18,11 @@ AppButton {
onClicked: {
GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen
}
+ onDownChanged: {
+ scaleAnim.duration = root.down ? 150 : 200
+ scaleAnim.easing.bezierCurve = root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut
+ iconWidget.scale = root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25
+ }
contentItem: Item {
anchors {
@@ -41,6 +46,13 @@ AppButton {
id: iconWidget
anchors.verticalCenter: parent.verticalCenter
iconName: root.iconName
+
+ Behavior on scale {
+ NumberAnimation {
+ id: scaleAnim
+ easing.type: Easing.BezierSpline
+ }
+ }
}
Column {
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml
index 53b68b82c..a5915e83e 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml
@@ -2,6 +2,7 @@ import QtQuick
import QtQuick.Layouts
import qs.services
import qs.modules.common
+import qs.modules.common.functions
import qs.modules.waffle.looks
import qs.modules.waffle.bar
import Quickshell
@@ -16,6 +17,7 @@ AppButton {
property bool hasWindows: appEntry.toplevels.length > 0
signal hoverPreviewRequested()
+ signal hoverPreviewDismissed()
multiple: appEntry.toplevels.length > 1
checked: active
@@ -37,12 +39,18 @@ AppButton {
}
}
- onMiddleClickAction: {
+ middleClickAction: () => {
if (root.desktopEntry) {
desktopEntry.execute()
}
}
+ altAction: () => {
+ root.hoverPreviewDismissed()
+ root.hoverTimer.stop()
+ contextMenu.active = true;
+ }
+
// Active indicator
Rectangle {
id: activeIndicator
@@ -74,4 +82,44 @@ AppButton {
extraVisibleCondition: root.shouldShowTooltip && !root.hasWindows
text: desktopEntry ? desktopEntry.name : appEntry.appId
}
+
+ BarMenu {
+ id: contextMenu
+
+ model: [
+ ...((root.desktopEntry?.actions.length > 0) ? root.desktopEntry.actions.map(action =>({
+ iconName: action.icon,
+ text: action.name,
+ action: () => {
+ action.execute()
+ }
+ })).concat({ type: "separator" }) : []),
+ {
+ iconName: root.iconName,
+ text: root.desktopEntry ? root.desktopEntry.name : StringUtils.toTitleCase(appEntry.appId),
+ monochromeIcon: false,
+ action: () => {
+ if (root.desktopEntry) {
+ root.desktopEntry.execute()
+ }
+ }
+ },
+ {
+ iconName: root.appEntry.pinned ? "pin-off" : "pin",
+ text: root.appEntry.pinned ? qsTr("Unpin from taskbar") : qsTr("Pin to taskbar"),
+ action: () => {
+ TaskbarApps.togglePin(root.appEntry.appId);
+ }
+ },
+ ...(root.appEntry.toplevels.length > 0 ? [{
+ iconName: "dismiss",
+ text: root.multiple ? qsTr("Close all windows") : qsTr("Close window"),
+ action: () => {
+ for (let toplevel of root.appEntry.toplevels) {
+ toplevel.close();
+ }
+ }
+ }] : []),
+ ]
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml
index 6d8aeba1a..18b11caee 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml
@@ -16,7 +16,7 @@ PopupWindow {
property Item anchorItem
//////////////////// Functions ////////////////////
- function close() {
+ function close() { // Closing doesn't animate, not sure if they're just lazy or it's intentional
marginBehavior.enabled = false;
root.visible = false;
}
@@ -36,7 +36,7 @@ PopupWindow {
///////////////////// Internals /////////////////////
readonly property bool bottom: Config.options.waffles.bar.bottom
property real visualMargin: 12
- property alias ambientShadowWidth: ambientShadow.border.width
+ property real ambientShadowWidth: 1
visible: false
color: "transparent"
@@ -64,16 +64,8 @@ PopupWindow {
hoverEnabled: true
// Shadow
- Rectangle {
- id: ambientShadow
- anchors {
- fill: contentItem
- margins: -border.width
- }
- border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency)
- border.width: 1
- color: "transparent"
- radius: Looks.radius.large + border.width
+ WAmbientShadow {
+ target: contentItem
}
Rectangle {
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml
index 895b1353f..f33c6e12a 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml
@@ -17,10 +17,17 @@ MouseArea {
previewPopup.show(appEntry, button);
}
+ Behavior on implicitWidth {
+ animation: Looks.transition.move.createObject(this)
+ }
+
// Apps row
RowLayout {
id: row
- anchors.fill: parent
+ anchors {
+ top: parent.top
+ bottom: parent.bottom
+ }
spacing: 0
Repeater {
@@ -36,6 +43,9 @@ MouseArea {
onHoverPreviewRequested: {
root.showPreviewPopup(appEntry, this)
}
+ onHoverPreviewDismissed: {
+ previewPopup.close()
+ }
}
}
}
@@ -46,4 +56,5 @@ MouseArea {
tasksHovered: root.containsMouse
anchor.window: root.QsWindow.window
}
+
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml
new file mode 100644
index 000000000..f05f2593e
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml
@@ -0,0 +1,118 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Layouts
+import Qt.labs.synchronizer
+import Quickshell
+import qs.services
+import qs.modules.common
+import qs.modules.common.widgets
+import qs.modules.waffle.looks
+import qs.modules.waffle.bar
+
+RowLayout {
+ id: root
+
+ property bool overflowOpen: false
+ property bool dragging: false
+
+ Layout.fillHeight: true
+ spacing: 0
+
+ BarIconButton {
+ id: overflowButton
+
+ visible: (TrayService.unpinnedItems.length > 0 || root.dragging)
+ checked: root.overflowOpen
+
+ iconName: "chevron-down"
+ iconMonochrome: true
+ iconRotation: (Config.options.waffles.bar.bottom ? 180 : 0) + (root.overflowOpen ? 180 : 0)
+ Behavior on iconRotation {
+ animation: Looks.transition.rotate.createObject(this)
+ }
+
+ onClicked: {
+ root.overflowOpen = !root.overflowOpen;
+ }
+
+ TrayOverflowMenu {
+ id: trayOverflowLayout
+ Synchronizer on active {
+ property alias source: root.overflowOpen
+ }
+ }
+
+ BarToolTip {
+ extraVisibleCondition: overflowButton.shouldShowTooltip
+ text: qsTr("Show hidden icons")
+ }
+
+ DropArea {
+ id: pinDropArea
+ anchors.fill: parent
+ property bool willPin: false
+ onEntered: willPin = true
+ onExited: willPin = false
+ }
+ }
+
+ Repeater {
+ model: ScriptModel {
+ values: TrayService.pinnedItems
+ }
+ delegate: TrayButton {
+ id: trayButton
+ required property var modelData
+ item: modelData
+
+ property real initialX
+ property real initialY
+
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+ drag.target: parent
+ drag.axis: Drag.XAxis
+ drag.threshold: 2
+
+ onPressed: event => {
+ trayButton.Drag.hotSpot.x = event.x;
+ trayButton.initialX = trayButton.x;
+ root.dragging = true;
+ trayButton.Drag.active = true;
+ }
+ onPositionChanged: {
+ pinTooltip.updateAnchor();
+ }
+ onReleased: {
+ if (!dragArea.drag.active) {
+ trayButton.click();
+ } else {
+ if (pinDropArea.containsDrag && pinDropArea.willPin) {
+ // Quickshell would crash if we don't hide this item first. Took me fucking 3 hours to figure out...
+ trayButton.visible = false;
+ TrayService.togglePin(trayButton.item.id);
+ pinDropArea.willPin = false;
+ } else {
+ trayButton.x = trayButton.initialX;
+ }
+ }
+ trayButton.Drag.active = false;
+ root.dragging = false;
+ }
+ }
+
+ BarToolTip {
+ id: pinTooltip
+ extraVisibleCondition: trayButton.Drag.active && pinDropArea.containsDrag && pinDropArea.willPin
+ realContentHorizontalPadding: 6
+ realContentVerticalPadding: 6
+ realContentItem: FluentIcon {
+ anchors.centerIn: parent
+ icon: "pin-off"
+ implicitSize: 18
+ }
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml
new file mode 100644
index 000000000..e3c85e290
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml
@@ -0,0 +1,52 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Layouts
+import Quickshell
+import Quickshell.Services.SystemTray
+import qs.services
+import qs.modules.common
+import qs.modules.common.widgets
+import qs.modules.waffle.looks
+import qs.modules.waffle.bar
+
+BarIconButton {
+ id: root
+
+ required property SystemTrayItem item
+ property alias menuOpen: menu.visible
+ readonly property bool barAtBottom: Config.options.waffles.bar.bottom
+ iconSource: item.icon
+ iconScale: 0
+ Component.onCompleted: {
+ root.iconScale = 1
+ }
+ Behavior on iconScale {
+ animation: Looks.transition.enter.createObject(this)
+ }
+
+ onClicked: {
+ item.activate();
+ }
+
+ altAction: () => {
+ if (item.hasMenu) menu.open()
+ }
+
+ // This is lazy, but it's not like tray menus on Windoes are consistent...
+ // TODO: Figure out how to do cascading menus then use a custom menu
+ QsMenuAnchor {
+ id: menu
+ menu: root.item.menu
+ anchor {
+ adjustment: PopupAdjustment.ResizeY | PopupAdjustment.SlideX
+ item: root
+ gravity: root.barAtBottom ? Edges.Top : Edges.Bottom
+ edges: root.barAtBottom ? Edges.Top : Edges.Bottom
+ }
+ }
+
+ BarToolTip {
+ extraVisibleCondition: root.shouldShowTooltip && !root.Drag.active
+ text: TrayService.getTooltipForItem(root.item)
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml
new file mode 100644
index 000000000..2b3044643
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml
@@ -0,0 +1,124 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Quickshell
+import Quickshell.Hyprland
+import qs.services
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+import qs.modules.waffle.bar
+
+BarPopup {
+ id: root
+
+ closeOnFocusLost: false
+ onFocusCleared: {
+ const hasMenuOpen = contentItem.children.some(c => (c.menuOpen));
+ if (!hasMenuOpen)
+ root.close();
+ else
+ root.grabFocus();
+ }
+
+ contentItem: Item {
+ id: contentItem
+ anchors.centerIn: parent
+ implicitWidth: contentGrid.implicitWidth
+ implicitHeight: contentGrid.implicitHeight
+ GridLayout {
+ id: contentGrid
+ anchors.centerIn: parent
+ rows: Math.floor(Math.sqrt(TrayService.unpinnedItems.length))
+ columns: Math.ceil(TrayService.unpinnedItems.length / rows)
+ columnSpacing: 0
+ rowSpacing: 0
+
+ Repeater {
+ model: ScriptModel {
+ values: TrayService.unpinnedItems
+ onValuesChanged: {
+ root.updateAnchor();
+ if (values.length === 0) {
+ root.close();
+ }
+ }
+ }
+ delegate: TrayButton {
+ id: trayButton
+ required property var modelData
+ item: modelData
+
+ topInset: 0
+ bottomInset: 0
+ implicitWidth: 40
+ implicitHeight: 40
+
+ colBackground: ColorUtils.transparentize(Looks.colors.bg2)
+ colBackgroundHover: Looks.colors.bg2Hover
+ colBackgroundActive: Looks.colors.bg2Active
+
+ onMenuOpenChanged: {
+ // The overflow menu should only be closed when the user clicks outside
+ // However the focus grab refuses to reactivate, so we can't have that
+ // But most of the time the user dismisses the menu by clicking outside anyway,
+ // so this is acceptable.
+ if (!menuOpen) {
+ root.close();
+ }
+ }
+
+ property real initialX
+ property real initialY
+
+ Behavior on x {
+ animation: Looks.transition.move.createObject(this)
+ }
+ Behavior on y {
+ animation: Looks.transition.move.createObject(this)
+ }
+
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+ drag.target: parent
+ drag.threshold: 2
+
+ onPressed: event => {
+ trayButton.Drag.hotSpot.x = event.x;
+ trayButton.Drag.hotSpot.y = event.y;
+ trayButton.initialX = trayButton.x;
+ trayButton.initialY = trayButton.y;
+ trayButton.Drag.active = true;
+ }
+ onReleased: {
+ if (!dragArea.drag.active) {
+ trayButton.click();
+ } else {
+ if (!unpinDropArea.containsDrag && unpinDropArea.willUnpin) {
+ // Quickshell would crash if we don't hide this item first. Took me fucking 3 hours to figure out...
+ trayButton.visible = false;
+ TrayService.togglePin(trayButton.item.id);
+ unpinDropArea.willUnpin = false;
+ } else {
+ trayButton.x = trayButton.initialX;
+ trayButton.y = trayButton.initialY;
+ }
+ }
+ trayButton.Drag.active = false;
+ }
+ }
+ }
+ }
+ }
+
+ DropArea {
+ id: unpinDropArea
+ anchors.fill: parent
+ property bool willUnpin: false
+ onEntered: willUnpin = false
+ onExited: willUnpin = true
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
index 81b6ebf08..5a7f15902 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
@@ -6,6 +6,7 @@ import qs.modules.waffle.looks
Kirigami.Icon {
id: root
required property string icon
+ property alias monochrome: root.isMask
// Should be 16, but it appears the icons have some padding,
// Unlike the Windows-only Segoe UI icons, the open source FluentUI ones are hella small
property int implicitSize: 20
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
index 09176830f..a01628d4a 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
@@ -17,9 +17,12 @@ Singleton {
property real backgroundTransparency: 0.17
property real contentTransparency: 0.25
- property real shadowTransparency: 0.6
colors: QtObject {
id: colors
+ property color ambientShadow: ColorUtils.transparentize("#000000", 0.75)
+ property color bgPanelFooter: root.dark ? "#1C1C1C" : "#EEEEEE"
+ property color bgPanelBody: root.dark ? "#242424" : "#F2F2F2"
+ property color bgPanelSeparator: root.dark ? "#191919" : "#E0E0E0"
property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE"
property color bg0Border: root.dark ? "#404040" : "#BEBEBE"
property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7"
@@ -34,6 +37,7 @@ Singleton {
property color fg1: root.dark ? "#D1D1D1" : "#626262"
property color danger: "#C42B1C"
property color dangerActive: "#B62D1F"
+ property color warning: "#FF9900"
// property color accent: root.dark ? "#A5C6D8" : "#5377A3"
property color accent: Appearance.m3colors.m3primary
property color accentUnfocused: root.dark ? "#989898" : "#848484"
@@ -61,7 +65,7 @@ Singleton {
}
property QtObject pixelSize: QtObject {
property real normal: 11
- property real large: 15
+ property real large: 14
}
}
@@ -115,6 +119,14 @@ Singleton {
}
}
+ property Component rotate: Component {
+ NumberAnimation {
+ duration: 170
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: transition.easing.bezierCurve.easeInOut
+ }
+ }
+
property Component anchor: Component {
AnchorAnimation {
duration: 160
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WAmbientShadow.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WAmbientShadow.qml
new file mode 100644
index 000000000..79a3ca857
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WAmbientShadow.qml
@@ -0,0 +1,25 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import Quickshell
+import Quickshell.Hyprland
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+Rectangle {
+ id: root
+
+ required property var target
+ z: 0
+
+ anchors {
+ fill: target
+ margins: -border.width
+ }
+
+ border.color: Looks.colors.ambientShadow
+ border.width: 1
+ color: "transparent"
+ radius: target.radius + border.width
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml
new file mode 100644
index 000000000..3350c5887
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml
@@ -0,0 +1,79 @@
+import QtQuick
+import QtQuick.Layouts
+import Quickshell
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+Item {
+ id: root
+
+ signal closed()
+
+ property alias border: borderRect
+ required default property Item contentItem
+ property real visualMargin: 12
+
+ function close() {
+ closeAnim.start();
+ }
+
+ readonly property bool barAtBottom: Config.options.waffles.bar.bottom
+
+ implicitHeight: borderRect.implicitHeight
+ implicitWidth: borderRect.implicitWidth
+
+ Rectangle {
+ id: borderRect
+
+ color: "transparent"
+ radius: Looks.radius.large
+ border.color: Looks.colors.bg2Border
+ border.width: 1
+ implicitWidth: contentItem.implicitWidth + border.width * 2
+ implicitHeight: contentItem.implicitHeight + border.width * 2
+ children: [root.contentItem]
+
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: root.barAtBottom ? undefined : parent.top
+ bottom: root.barAtBottom ? parent.bottom : undefined
+ // Opening anim
+ bottomMargin: root.barAtBottom ? sourceEdgeMargin : 0
+ topMargin: root.barAtBottom ? 0 : sourceEdgeMargin
+ }
+
+ Component.onCompleted: {
+ openAnim.start();
+ }
+
+ property real sourceEdgeMargin: -(implicitHeight + root.visualMargin)
+ PropertyAnimation {
+ id: openAnim
+ target: borderRect
+ property: "sourceEdgeMargin"
+ to: 0
+ duration: 200
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
+ }
+ SequentialAnimation {
+ id: closeAnim
+ PropertyAnimation {
+ target: borderRect
+ property: "sourceEdgeMargin"
+ to: -(implicitHeight + root.visualMargin)
+ duration: 150
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut
+ }
+ ScriptAction {
+ script: {
+ root.closed();
+ }
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml
new file mode 100644
index 000000000..3b48a79e3
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml
@@ -0,0 +1,95 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+// Generic button with background
+Button {
+ id: root
+
+ property color colBackgroundHover: Looks.colors.bg2Hover
+ property color colBackgroundActive: Looks.colors.bg2Active
+ property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
+
+ property alias monochromeIcon: buttonIcon.monochrome
+ property bool forceShowIcon: false
+
+ property var altAction: () => {}
+ property var middleClickAction: () => {}
+
+ property real inset: 2
+ topInset: inset
+ bottomInset: inset
+ leftInset: inset
+ rightInset: inset
+ horizontalPadding: 10
+ verticalPadding: 6
+ implicitHeight: contentItem.implicitHeight + verticalPadding * 2
+ implicitWidth: contentItem.implicitWidth + horizontalPadding * 2
+
+ background: Rectangle {
+ radius: Looks.radius.medium
+ color: {
+ if (root.down) {
+ return root.colBackgroundActive;
+ } else if ((root.hovered && !root.down) || root.checked) {
+ return root.colBackgroundHover;
+ } else {
+ return root.colBackground;
+ }
+ }
+ Behavior on color {
+ animation: Looks.transition.color.createObject(this)
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.RightButton | Qt.MiddleButton
+ onClicked: (event) => {
+ if (event.button === Qt.LeftButton) root.clicked();
+ if (event.button === Qt.RightButton) root.altAction();
+ if (event.button === Qt.MiddleButton) root.middleClickAction();
+ }
+ }
+
+ contentItem: Item {
+ anchors {
+ fill: parent
+ margins: root.inset
+ }
+ implicitWidth: contentLayout.implicitWidth
+ implicitHeight: contentLayout.implicitHeight
+ RowLayout {
+ id: contentLayout
+ anchors {
+ fill: parent
+ leftMargin: root.horizontalPadding
+ rightMargin: root.horizontalPadding
+ }
+ spacing: 12
+ FluentIcon {
+ id: buttonIcon
+ visible: root.icon.name !== "" || root.forceShowIcon
+ monochrome: true
+ implicitSize: 16
+ Layout.leftMargin: 6
+ Layout.fillWidth: false
+ Layout.alignment: Qt.AlignVCenter
+ icon: root.icon.name
+ }
+ WText {
+ Layout.rightMargin: 12
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
+ text: root.text
+ horizontalAlignment: Text.AlignLeft
+ font {
+ pixelSize: Looks.font.pixelSize.large
+ }
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPanelFooterButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPanelFooterButton.qml
new file mode 100644
index 000000000..9b017d75f
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPanelFooterButton.qml
@@ -0,0 +1,32 @@
+import QtQuick
+import QtQuick.Controls
+import Quickshell
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+Button {
+ id: root
+
+ implicitHeight: 36
+
+ property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
+ property color colBackgroundHover: Looks.colors.bg1Hover
+ property color colBackgroundActive: Looks.colors.bg1Active
+ property color color
+ property color colForeground: Looks.colors.fg
+ color: {
+ if (root.down) {
+ return root.colBackgroundActive
+ } else if ((root.hovered && !root.down) || root.checked) {
+ return root.colBackgroundHover
+ } else {
+ return root.colBackground
+ }
+ }
+
+ background: Rectangle {
+ radius: Looks.radius.medium
+ color: root.color
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml
index b35258204..feddc3793 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml
@@ -10,42 +10,37 @@ import qs.modules.waffle.looks
PopupToolTip {
id: root
- property real padding: 2
- verticalPadding: padding
- horizontalPadding: padding
+ property Item realContentItem
+ realContentItem: WText {
+ text: root.text
+ anchors.centerIn: parent
+ }
+
+ property real visualMargin: 11
+ verticalPadding: visualMargin
+ horizontalPadding: visualMargin
+ property real realContentVerticalPadding: 8
+ property real realContentHorizontalPadding: 10
contentItem: Item {
anchors.centerIn: parent
- implicitWidth: realContent.implicitWidth + root.verticalPadding * 2
- implicitHeight: realContent.implicitHeight + root.horizontalPadding * 2
+ implicitWidth: realContent.implicitWidth + 2 * 2
+ implicitHeight: realContent.implicitHeight + 2 * 2
- Rectangle {
- id: ambientShadow
- z: 0
- anchors {
- fill: realContent
- margins: -border.width
- }
- border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency)
- border.width: 1
- color: "transparent"
- radius: realContent.radius + border.width
+ WAmbientShadow {
+ target: realContent
}
Rectangle {
id: realContent
z: 1
anchors.centerIn: parent
- implicitWidth: tooltipText.implicitWidth + 10 * 2
- implicitHeight: tooltipText.implicitHeight + 8 * 2
+ implicitWidth: root.realContentItem.implicitWidth + root.realContentHorizontalPadding * 2
+ implicitHeight: root.realContentItem.implicitHeight + root.realContentVerticalPadding * 2
color: Looks.colors.bg1
radius: Looks.radius.medium
- WText {
- id: tooltipText
- text: root.text
- anchors.centerIn: parent
- }
+ children: [root.realContentItem]
}
}
}
diff --git a/dots/.config/quickshell/ii/services/Brightness.qml b/dots/.config/quickshell/ii/services/Brightness.qml
index f3cec016c..465d8729c 100644
--- a/dots/.config/quickshell/ii/services/Brightness.qml
+++ b/dots/.config/quickshell/ii/services/Brightness.qml
@@ -135,10 +135,18 @@ Singleton {
}
function syncBrightness() {
- const brightnessValue = Math.max(monitor.multipliedBrightness, 0)
- const rawValueRounded = Math.max(Math.floor(brightnessValue * monitor.rawMaxBrightness), 1);
- setProc.command = isDdc ? ["ddcutil", "-b", busNum, "setvcp", "10", rawValueRounded] : ["brightnessctl", "--class", "backlight", "s", rawValueRounded, "--quiet"];
- setProc.startDetached();
+ const brightnessValue = Math.max(monitor.multipliedBrightness, 0);
+ if (isDdc) {
+ const rawValueRounded = Math.max(Math.floor(brightnessValue * monitor.rawMaxBrightness), 1);
+ setProc.command = ["ddcutil", "-b", busNum, "setvcp", "10", rawValueRounded];
+ setProc.startDetached();
+ } else {
+ const valuePercentNumber = Math.floor(brightnessValue * 100);
+ let valuePercent = `${valuePercentNumber}%`;
+ if (valuePercentNumber == 0) valuePercent = "1"; // Prevent fully black
+ setProc.command = ["brightnessctl", "--class", "backlight", "s", valuePercent, "--quiet"];
+ setProc.startDetached();
+ }
}
function setBrightness(value: real): void {
diff --git a/dots/.config/quickshell/ii/services/EasyEffects.qml b/dots/.config/quickshell/ii/services/EasyEffects.qml
index 4117e50c4..e21a0a67f 100644
--- a/dots/.config/quickshell/ii/services/EasyEffects.qml
+++ b/dots/.config/quickshell/ii/services/EasyEffects.qml
@@ -30,7 +30,7 @@ Singleton {
function enable() {
root.active = true
- Quickshell.execDetached(["bash", "-c", "easyeffects --gapplication-service || flatpak run com.github.wwmm.easyeffects --gapplication-service"])
+ Quickshell.execDetached(["bash", "-c", "easyeffects --hide-window --service-mode || flatpak run com.github.wwmm.easyeffects --hide-window --service-mode"])
}
function toggle() {
diff --git a/dots/.config/quickshell/ii/services/SystemInfo.qml b/dots/.config/quickshell/ii/services/SystemInfo.qml
index 1d5c0bf6e..2b519a229 100644
--- a/dots/.config/quickshell/ii/services/SystemInfo.qml
+++ b/dots/.config/quickshell/ii/services/SystemInfo.qml
@@ -58,6 +58,7 @@ Singleton {
// Update the distroIcon property based on distroId
switch (distroId) {
+ case "artix":
case "arch": distroIcon = "arch-symbolic"; break;
case "endeavouros": distroIcon = "endeavouros-symbolic"; break;
case "cachyos": distroIcon = "cachyos-symbolic"; break;
diff --git a/dots/.config/quickshell/ii/services/TaskbarApps.qml b/dots/.config/quickshell/ii/services/TaskbarApps.qml
index 0b5818b71..052abcaec 100644
--- a/dots/.config/quickshell/ii/services/TaskbarApps.qml
+++ b/dots/.config/quickshell/ii/services/TaskbarApps.qml
@@ -8,6 +8,14 @@ import Quickshell.Wayland
Singleton {
id: root
+ function togglePin(appId) {
+ if (Config.options.dock.pinnedApps.indexOf(appId) !== -1) {
+ Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.filter(id => id !== appId)
+ } else {
+ Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.concat([appId])
+ }
+ }
+
property list apps: {
var map = new Map();
diff --git a/dots/.config/quickshell/ii/services/TrayService.qml b/dots/.config/quickshell/ii/services/TrayService.qml
new file mode 100644
index 000000000..a874c6c11
--- /dev/null
+++ b/dots/.config/quickshell/ii/services/TrayService.qml
@@ -0,0 +1,45 @@
+pragma Singleton
+
+import qs.modules.common
+import QtQuick
+import Quickshell
+import Quickshell.Services.SystemTray
+
+Singleton {
+ id: root
+
+ property bool smartTray: Config.options.tray.filterPassive
+ property list itemsInUserList: SystemTray.items.values.filter(i => (Config.options.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive)))
+ property list itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive)))
+
+ property bool invertPins: Config.options.tray.invertPinnedItems
+ property list pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList
+ property list unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList
+
+ function getTooltipForItem(item) {
+ var result = item.tooltipTitle.length > 0 ? item.tooltipTitle
+ : (item.title.length > 0 ? item.title : item.id);
+ if (item.tooltipDescription.length > 0) result += " • " + item.tooltipDescription;
+ if (Config.options.tray.showItemId) result += "\n[" + item.id + "]";
+ return result;
+ }
+
+ // Pinning
+ function pin(itemId) {
+ var pins = Config.options.tray.pinnedItems;
+ if (pins.includes(itemId)) return;
+ Config.options.tray.pinnedItems.push(itemId);
+ }
+ function unpin(itemId) {
+ Config.options.tray.pinnedItems = Config.options.tray.pinnedItems.filter(id => id !== itemId);
+ }
+ function togglePin(itemId) {
+ var pins = Config.options.tray.pinnedItems;
+ if (pins.includes(itemId)) {
+ unpin(itemId)
+ } else {
+ pin(itemId)
+ }
+ }
+
+}
diff --git a/dots/.config/quickshell/ii/services/Updates.qml b/dots/.config/quickshell/ii/services/Updates.qml
new file mode 100644
index 000000000..58b8be892
--- /dev/null
+++ b/dots/.config/quickshell/ii/services/Updates.qml
@@ -0,0 +1,57 @@
+pragma Singleton
+
+import qs.modules.common
+import qs.modules.common.functions
+import QtQuick
+import Quickshell
+import Quickshell.Io
+
+/*
+ * System updates service. Currently only supports Arch.
+ */
+Singleton {
+ id: root
+
+ property bool available: false
+ property int count: 0
+
+ readonly property bool updateAdvised: available && count > Config.options.updates.adviseUpdateThreshold
+ readonly property bool updateStronglyAdvised: available && count > Config.options.updates.stronglyAdviseUpdateThreshold
+
+ function load() {}
+ function refresh() {
+ if (!available) return;
+ print("[Updates] Checking for system updates")
+ checkUpdatesProc.running = true;
+ }
+
+ Timer {
+ interval: Config.options.updates.checkInterval * 60 * 1000
+ repeat: true
+ running: Config.ready
+ onTriggered: {
+ print("[Updates] Periodic update check due")
+ root.refresh();
+ }
+ }
+
+ Process {
+ id: checkAvailabilityProc
+ running: true
+ command: ["which", "checkupdates"]
+ onExited: (exitCode, exitStatus) => {
+ root.available = (exitCode === 0);
+ root.refresh();
+ }
+ }
+
+ Process {
+ id: checkUpdatesProc
+ command: ["bash", "-c", "checkupdates | wc -l"]
+ stdout: StdioCollector {
+ onStreamFinished: {
+ root.count = parseInt(text.trim());
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml
index ea100fdda..766728cf5 100644
--- a/dots/.config/quickshell/ii/shell.qml
+++ b/dots/.config/quickshell/ii/shell.qml
@@ -28,6 +28,7 @@ import qs.modules.ii.overlay
import qs.modules.ii.verticalBar
import qs.modules.ii.wallpaperSelector
+import qs.modules.waffle.actionCenter
import qs.modules.waffle.background
import qs.modules.waffle.bar
@@ -49,6 +50,7 @@ ShellRoot {
ConflictKiller.load()
Cliphist.refresh()
Wallpapers.load()
+ Updates.load()
}
// Load enabled stuff
@@ -74,6 +76,7 @@ ShellRoot {
PanelLoader { identifier: "iiSidebarRight"; component: SidebarRight {} }
PanelLoader { identifier: "iiVerticalBar"; extraCondition: Config.options.bar.vertical; component: VerticalBar {} }
PanelLoader { identifier: "iiWallpaperSelector"; component: WallpaperSelector {} }
+ PanelLoader { identifier: "wActionCenter"; component: WaffleActionCenter {} }
PanelLoader { identifier: "wBar"; component: WaffleBar {} }
PanelLoader { identifier: "wBackground"; component: WaffleBackground {} }
@@ -87,7 +90,7 @@ ShellRoot {
property list families: ["ii", "waffle"]
property var panelFamilies: ({
"ii": ["iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"],
- "waffle": ["wBar", "wBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiWallpaperSelector"],
+ "waffle": ["wBar", "wBackground", "wActionCenter", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiSessionScreen", "iiSidebarRight", "iiWallpaperSelector"],
})
function cyclePanelFamily() {
const currentIndex = families.indexOf(Config.options.panelFamily)
diff --git a/sdata/deps-info.md b/sdata/deps-info.md
index 475639b6e..a7e0f9f14 100644
--- a/sdata/deps-info.md
+++ b/sdata/deps-info.md
@@ -211,6 +211,7 @@ Extra dependencies.
- `qt6-translations`
- `qt6-virtualkeyboard`
- `qt6-wayland`
+- `kirigami`
- `kdialog`
- `syntax-highlighting`
diff --git a/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD b/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD
index 806f2272e..690b73123 100644
--- a/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD
+++ b/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD
@@ -9,7 +9,7 @@ conflicts=("quickshell-git")
_pkgname=quickshell
pkgname="$_prefix-$_pkgname-git"
pkgver=0.1.0.r1
-pkgrel=5
+pkgrel=6
pkgdesc="$_pkgname-git pinned commit and extra deps for $_prefix"
arch=(x86_64 aarch64)
url='https://git.outfoxxed.me/quickshell/quickshell'
@@ -39,6 +39,7 @@ depends=(
qt6-translations
qt6-virtualkeyboard
qt6-wayland
+ kirigami
kdialog
syntax-highlighting
)
diff --git a/sdata/dist-fedora/SPECS/Bibata-Modern-Classic.spec b/sdata/dist-fedora/SPECS/Bibata-Modern-Classic.spec
deleted file mode 100644
index 1522ae851..000000000
--- a/sdata/dist-fedora/SPECS/Bibata-Modern-Classic.spec
+++ /dev/null
@@ -1,36 +0,0 @@
-Name: Bibata-Modern-Classic
-Version: 2.0.7
-Release: %autorelease
-Summary: Open source, compact, and material designed cursor set.
-
-License: GPL-3.0
-URL: https://github.com/ful1e5/Bibata_Cursor
-Source0: %{name}.tar.xz
-
-BuildArch: noarch
-
-%description
-Open source, compact, and material designed cursor set.
-
-%prep
-wget --content-disposition -q -N -P %{_sourcedir} %{url}/releases/download/v%{version}/Bibata-Modern-Classic.tar.xz
-wget -q -O %{_buildrootdir}/LICENSE %{url}/raw/refs/heads/main/LICENSE
-%setup -q -n %{name}
-
-%build
-:
-
-%install
-install -d -m 0755 %{buildroot}%{_iconsdir}/Bibata-Modern-Classic
-cp -r * %{buildroot}%{_iconsdir}/Bibata-Modern-Classic
-
-install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
-install -m 0644 %{_buildrootdir}/LICENSE %{buildroot}%{_licensedir}/%{name}/
-
-%files
-%{_iconsdir}/Bibata-Modern-Classic
-%license %{_licensedir}/%{name}/LICENSE
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/SPECS/JetBrainsMonoNerdFont-Regular.spec b/sdata/dist-fedora/SPECS/JetBrainsMonoNerdFont-Regular.spec
deleted file mode 100644
index 01f1e0e08..000000000
--- a/sdata/dist-fedora/SPECS/JetBrainsMonoNerdFont-Regular.spec
+++ /dev/null
@@ -1,42 +0,0 @@
-Name: JetBrainsMonoNerdFont-Regular
-Version: 1.2
-Release: %autorelease
-Summary: JetBrainsMonoNerdFonts (TrueType Outlines) (Regulear)
-
-License: MIT
-URL: https://github.com/Zhaopudark/JetBrainsMonoNerdFonts
-Source0: %{name}
-
-BuildRequires: fonts-rpm-macros
-BuildArch: noarch
-
-%description
-An auto-updated compiling version of JetBrains Mono that has been patched with Nerd Fonts.
-
-%prep
-wget --content-disposition -q -N -P %{_sourcedir} %{url}/releases/download/v%{version}/JetBrainsMonoNerdFont-Regular-v%{version}.ttf
-wget -q -P %{_sourcedir} %{url}/raw/refs/heads/main/LICENSE
-
-%build
-:
-
-%install
-install -d -m 0755 %{buildroot}%{_fontdir}
-install -m 0644 %{_sourcedir}/JetBrainsMonoNerdFont*ttf %{buildroot}%{_fontdir}
-
-install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
-install -m 0644 %{_sourcedir}/LICENSE %{buildroot}%{_licensedir}/%{name}/
-
-%post
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%postun
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%files
-%{_fontdir}/JetBrainsMonoNerdFont*ttf
-%license %{_licensedir}/%{name}/LICENSE
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/SPECS/MicroTeX.spec b/sdata/dist-fedora/SPECS/MicroTeX.spec
deleted file mode 100644
index ec8ae436f..000000000
--- a/sdata/dist-fedora/SPECS/MicroTeX.spec
+++ /dev/null
@@ -1,50 +0,0 @@
-%global commit0 0e3707f6dafebb121d98b53c64364d16fefe481d
-%global shortcommit0 %(c=%{commit0}; echo ${c:0:7})
-%global bumpver 100
-
-Name: MicroTeX
-Version: 0.0.1%{?bumpver:^%{bumpver}.git%{shortcommit0}}
-Release: %autorelease
-Summary: A dynamic, cross-platform, and embeddable LaTeX rendering library
-
-License: MIT
-URL: https://github.com/NanoMichael/MicroTeX
-Source0: %{name}-%{shortcommit0}.tar.gz
-
-BuildRequires: gcc-c++ cmake
-BuildRequires: pkgconfig(tinyxml2)
-BuildRequires: gtkmm3.0-devel gtksourceviewmm3-devel cairomm-devel
-
-%description
-MicroTeX is a library for rendering LaTeX mathematical formulas, supporting multiple backends
-such as GTK+, Qt, and Skia. It provides both library components and demo applications for
-testing LaTeX rendering.
-
-%prep
-curl -fsSL --retry 3 \
- https://codeload.github.com/NanoMichael/MicroTeX/tar.gz/%{shortcommit0} \
- -o %{_sourcedir}/%{name}-%{shortcommit0}.tar.gz
-%setup -q -n %{name}-%{shortcommit0}
-
-%build
-mkdir -p build
-cd build
-cmake ..
-make -j$(nproc)
-
-%install
-mkdir -p %{buildroot}/opt/MicroTeX
-cp build/LaTeX %{buildroot}/opt/MicroTeX/
-cp -r build/res %{buildroot}/opt/MicroTeX/
-
-install -Dpm 0644 LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE
-install -Dpm 0644 res/greek/LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE-greek
-install -Dpm 0644 res/cyrillic/LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE-cyrillic
-
-%files
-/opt/MicroTeX/
-%license %{_licensedir}/%{name}/
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/SPECS/breeze-plus.spec b/sdata/dist-fedora/SPECS/breeze-plus.spec
deleted file mode 100644
index d37ff8e41..000000000
--- a/sdata/dist-fedora/SPECS/breeze-plus.spec
+++ /dev/null
@@ -1,38 +0,0 @@
-Name: breeze-plus
-Version: 6.19.0
-Release: %autorelease
-Summary: Breeze theme with additional icons
-
-License: LGPL-2.1
-URL: https://github.com/mjkim0727/breeze-plus
-Source0: %{name}-%{version}.tar.gz
-
-BuildArch: noarch
-
-%description
-Breeze icon theme with additional icons for applications not covered by the
-official Breeze theme. Includes icons for Wine, third-party apps, and more.
-
-%prep
-wget --content-disposition -q -N -P %{_sourcedir} %{url}/archive/refs/tags/%{version}.tar.gz
-%setup -q
-
-%build
-:
-
-%install
-install -d -m 0755 %{buildroot}%{_iconsdir}/breeze-plus
-cp -r src/breeze-plus %{buildroot}%{_iconsdir}/
-cp -r src/breeze-plus-dark %{buildroot}%{_iconsdir}/
-
-install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
-install -m 0644 LICENSE %{buildroot}%{_licensedir}/%{name}/
-
-%files
-%{_iconsdir}/breeze-plus/
-%{_iconsdir}/breeze-plus-dark/
-%license %{_licensedir}/%{name}/LICENSE
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/SPECS/hyprland-qt-support.spec b/sdata/dist-fedora/SPECS/hyprland-qt-support.spec
index c4f8bf057..4cae243ae 100644
--- a/sdata/dist-fedora/SPECS/hyprland-qt-support.spec
+++ b/sdata/dist-fedora/SPECS/hyprland-qt-support.spec
@@ -25,7 +25,6 @@ BuildRequires: pkgconfig(hyprlang)
%{summary}.
%prep
-wget --content-disposition -q -N -P %{_sourcedir} %{url}/archive/v%{version}/%{name}-%{version}.tar.gz
%autosetup -p1
%build
diff --git a/sdata/dist-fedora/SPECS/otf-SpaceGrotesk.spec b/sdata/dist-fedora/SPECS/otf-SpaceGrotesk.spec
deleted file mode 100644
index e42e4bc8e..000000000
--- a/sdata/dist-fedora/SPECS/otf-SpaceGrotesk.spec
+++ /dev/null
@@ -1,44 +0,0 @@
-Name: otf-SpaceGrotesk
-Version: 2.0.0
-Release: %autorelease
-Summary: Space Grotesk: a proportional variant of the original fixed-width Space Mono family
-
-License: OFL-1.1
-URL: https://github.com/floriankarsten/space-grotesk
-Source0: %{name}-%{version}
-
-BuildRequires: fonts-rpm-macros
-BuildArch: noarch
-
-%description
-Space Grotesk is a proportional sans-serif typeface variant based on Colophon Foundry's fixed-width Space Mono family (2016).
-Originally designed by Florian Karsten in 2018,
-Space Grotesk retains the monospace's idiosyncratic details while optimizing for improved readability at non-display sizes.
-
-%prep
-wget --content-disposition -q -N -P %{_sourcedir} %{url}/releases/download/%{version}/SpaceGrotesk-%{version}.zip
-unzip %{_sourcedir}/SpaceGrotesk-%{version}.zip
-
-%build
-:
-
-%install
-install -d -m 0755 %{buildroot}%{_fontdir}
-install -m 0644 %{_buildrootdir}/SpaceGrotesk-%{version}/otf/SpaceGrotesk*otf %{buildroot}%{_fontdir}
-
-install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
-install -m 0644 %{_buildrootdir}/SpaceGrotesk-%{version}/OFL.txt %{buildroot}%{_licensedir}/%{name}/
-
-%post
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%postun
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%files
-%{_fontdir}/SpaceGrotesk*otf
-%license %{_licensedir}/%{name}/OFL.txt
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/SPECS/quickshell-git.spec b/sdata/dist-fedora/SPECS/quickshell-git.spec
index a0b23bfd8..e90bdebe2 100644
--- a/sdata/dist-fedora/SPECS/quickshell-git.spec
+++ b/sdata/dist-fedora/SPECS/quickshell-git.spec
@@ -3,18 +3,19 @@
%bcond_with asan
%global commit db1777c20b936a86528c1095cbcb1ebd92801402
+%global shortcommit %(c=%{commit}; echo ${c:0:7})
%global commits 699
%global snapdate 20251030
%global tag 0.2.1
Name: quickshell-git
-Version: %{tag}^%{commits}.git%(c=%{commit}; echo ${c:0:7})
+Version: %{tag}^%{commits}.git%{shortcommit}
Release: 0%{?dist}
Summary: Flexible QtQuick based desktop shell toolkit
License: LGPL-3.0-only AND GPL-3.0-only
URL: https://github.com/quickshell-mirror/quickshell
-Source0: %{url}/archive/%{commit}/quickshell-%{commit}.tar.gz
+Source0: %{url}/archive/%{commit}/quickshell-%{shortcommit}.tar.gz
Conflicts: quickshell <= %{tag}
@@ -53,7 +54,6 @@ Flexible toolkit for making desktop shells with QtQuick, targeting
Wayland and X11.
%prep
-wget --content-disposition -q -N -P %{_sourcedir} %{url}/archive/%{commit}/quickshell-%{commit}.tar.gz
%autosetup -n quickshell-%{commit} -p1
%build
diff --git a/sdata/dist-fedora/SPECS/ttf-gabarito.spec b/sdata/dist-fedora/SPECS/ttf-gabarito.spec
deleted file mode 100644
index a46341bf9..000000000
--- a/sdata/dist-fedora/SPECS/ttf-gabarito.spec
+++ /dev/null
@@ -1,46 +0,0 @@
-%global commit0 1f3fb39d6449eefa880543f109f33ede0cd4064f
-%global shortcommit0 %(c=%{commit0}; echo ${c:0:7})
-%global bumpver 100
-
-Name: ttf-gabarito
-Version: 1.000%{?bumpver:^%{bumpver}.git%{shortcommit0}}
-Release: %autorelease
-Summary: Gabarito Font
-
-License: OFL-1.1
-URL: https://github.com/naipefoundry/gabarito
-Source0: gabarito-%{shortcommit0}.tar.gz
-
-BuildRequires: fonts-rpm-macros
-BuildArch: noarch
-
-%description
-Gabarito is a light-hearted geometric sans typeface with 6 weights ranging from Regular to Black originally designed for an online learning platform in Brazil.
-
-%prep
-wget --content-disposition -q -N -P %{_sourcedir} https://codeload.github.com/naipefoundry/gabarito/tar.gz/%{shortcommit0}
-%setup -q -n gabarito-%{shortcommit0}
-
-%build
-:
-
-%install
-install -d -m 0755 %{buildroot}%{_fontdir}
-install -m 0644 fonts/ttf/Gabarito*.ttf %{buildroot}%{_fontdir}
-
-install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
-install -m 0644 OFL.txt %{buildroot}%{_licensedir}/%{name}/
-
-%post
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%postun
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%files
-%{_fontdir}/Gabarito*ttf
-%license %{_licensedir}/%{name}/OFL.txt
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/SPECS/ttf-material-symbols-variable.spec b/sdata/dist-fedora/SPECS/ttf-material-symbols-variable.spec
deleted file mode 100644
index 989540ec3..000000000
--- a/sdata/dist-fedora/SPECS/ttf-material-symbols-variable.spec
+++ /dev/null
@@ -1,42 +0,0 @@
-Name: ttf-material-symbols-variable
-Version: 4.0.0
-Release: %autorelease
-Summary: Material Design icons by Google (Material Symbols)
-
-License: Apache-2.0
-URL: https://github.com/google/material-design-icons
-Source0: %{name}-%{version}
-
-BuildRequires: fonts-rpm-macros
-BuildArch: noarch
-
-%description
-Google Material Symbols Rounded
-
-%prep
-wget --content-disposition -q -N -P %{_sourcedir} %{url}/raw/refs/heads/master/variablefont/MaterialSymbolsRounded%5BFILL,GRAD,opsz,wght%5D.ttf
-wget -q -N -P %{_sourcedir} %{url}/raw/refs/heads/master/LICENSE
-
-%build
-:
-
-%install
-install -d -m 0755 %{buildroot}%{_fontdir}/variable-fonts
-install -m 0644 %{_sourcedir}/MaterialSymbolsRounded*ttf %{buildroot}%{_fontdir}/variable-fonts/
-
-install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
-install -m 0644 %{_sourcedir}/LICENSE %{buildroot}%{_licensedir}/%{name}/
-
-%post
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%postun
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%files
-%{_fontdir}/variable-fonts/MaterialSymbolsRounded*ttf
-%license %{_licensedir}/%{name}/LICENSE
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/SPECS/ttf-roboto-flex.spec b/sdata/dist-fedora/SPECS/ttf-roboto-flex.spec
deleted file mode 100644
index e95917bf1..000000000
--- a/sdata/dist-fedora/SPECS/ttf-roboto-flex.spec
+++ /dev/null
@@ -1,42 +0,0 @@
-Name: ttf-roboto-flex
-Version: 3.200
-Release: %autorelease
-Summary: Roboto Flex
-
-License: OFL-1.1
-URL: https://github.com/googlefonts/roboto-flex
-Source0: %{name}
-
-BuildRequires: fonts-rpm-macros
-BuildArch: noarch
-
-%description
-:
-
-%prep
-wget --content-disposition -q -N -P %{_sourcedir} %{url}/raw/refs/heads/main/fonts/RobotoFlex%5BGRAD,XOPQ,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght%5D.ttf
-wget -q -O %{_sourcedir}/OFL.txt %{url}/raw/refs/heads/main/OFL.txt
-
-%build
-:
-
-%install
-install -d -m 0755 %{buildroot}%{_fontdir}
-install -m 0644 %{_sourcedir}/RobotoFlex*ttf %{buildroot}%{_fontdir}
-
-install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
-install -m 0644 %{_sourcedir}/OFL.txt %{buildroot}%{_licensedir}/%{name}/
-
-%post
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%postun
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%files
-%{_fontdir}/RobotoFlex*ttf
-%license %{_licensedir}/%{name}/OFL.txt
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/SPECS/ttf-rubik-variable.spec b/sdata/dist-fedora/SPECS/ttf-rubik-variable.spec
deleted file mode 100644
index ec276be74..000000000
--- a/sdata/dist-fedora/SPECS/ttf-rubik-variable.spec
+++ /dev/null
@@ -1,46 +0,0 @@
-%global commit0 e337a5f69a9bea30e58d05bd40184d79cc099628
-%global shortcommit0 %(c=%{commit0}; echo ${c:0:7})
-%global bumpver 100
-
-Name: ttf-rubik-variable
-Version: 1.0%{?bumpver:^%{bumpver}.git%{shortcommit0}}
-Release: %autorelease
-Summary: Rubik fonts variable
-
-License: OFL-1.1
-URL: https://github.com/googlefonts/rubik
-Source0: rubik-%{shortcommit0}.tar.gz
-
-BuildRequires: fonts-rpm-macros
-BuildArch: noarch
-
-%description
-:
-
-%prep
-wget --content-disposition -q -N -P %{_sourcedir} https://codeload.github.com/googlefonts/rubik/tar.gz/%{shortcommit0}
-%setup -q -n rubik-%{shortcommit0}
-
-%build
-:
-
-%install
-install -d -m 0755 %{buildroot}%{_fontdir}/variable-fonts
-install -m 0644 fonts/variable/Rubik*ttf %{buildroot}%{_fontdir}/variable-fonts/
-
-install -d -m 0755 %{buildroot}%{_licensedir}/%{name}
-install -m 0644 OFL.txt %{buildroot}%{_licensedir}/%{name}/
-
-%post
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%postun
-/usr/bin/fc-cache -fv >/dev/null 2>&1 || :
-
-%files
-%{_fontdir}/variable-fonts/Rubik*ttf
-%license %{_licensedir}/%{name}/OFL.txt
-
-%changelog
-%autochangelog
-
diff --git a/sdata/dist-fedora/install-deps.sh b/sdata/dist-fedora/install-deps.sh
index 6374d5e7e..624fba6ca 100644
--- a/sdata/dist-fedora/install-deps.sh
+++ b/sdata/dist-fedora/install-deps.sh
@@ -8,8 +8,8 @@ fi
# Update System
case $SKIP_SYSUPDATE in
- true) sleep 0;;
- *) v sudo dnf upgrade --refresh -y;;
+ true) sleep 0 ;;
+ *) v sudo dnf upgrade --refresh -y ;;
esac
# Remove version lock
@@ -19,9 +19,8 @@ v sudo dnf versionlock delete quickshell-git 2>/dev/null
v sudo dnf install @development-tools fedora-packager rpmdevtools fonts-rpm-macros qt6-rpm-macros -y
# COPR repositories
+v sudo dnf copr enable ririko66z/dots-hyprland -y
v sudo dnf copr enable solopasha/hyprland -y
-v sudo dnf copr enable errornointernet/quickshell -y
-v sudo dnf copr enable errornointernet/packages -y
v sudo dnf copr enable deltacopy/darkly -y
v sudo dnf copr enable alternateved/eza -y
v sudo dnf copr enable atim/starship -y
@@ -35,15 +34,19 @@ v sudo dnf install geoclue2 brightnessctl ddcutil -y
# Basic
v sudo dnf install bc coreutils cliphist cmake curl wget2 ripgrep jq xdg-utils rsync yq -y
+# Cursor themes
+v sudo dnf install bibata-cursor-theme -y
+
# Fonts & Themes
themes_deps=(
- adw-gtk3-theme breeze-cursor-theme grub2-breeze-theme breeze-icon-theme{,-fedora}
- kf6-breeze-icons sddm-breeze darkly eza fish fontconfig kitty matugen starship
- jetbrains-mono-nl-fonts material-icons-fonts twitter-twemoji-fonts
+ adw-gtk3-theme breeze-cursor-theme grub2-breeze-theme breeze-icon-theme{,-fedora} kf6-breeze-icons
+ sddm-breeze breeze-plus-icon-theme darkly eza fish fontconfig kitty matugen florian-karsten-space-grotesk-fonts
+ starship gabarito-fonts jetbrains-mono-nerd-fonts google-material-symbols-vf-rounded-fonts material-icons-fonts
+ readex-pro-fonts-all google-roboto-flex-fonts google-rubik-vf-fonts twitter-twemoji-fonts
)
v sudo dnf install ${themes_deps[@]} -y
-# Hyprland
+# Hyprland
hyprland_deps=(
hyprland
hyprsunset
@@ -56,8 +59,8 @@ v sudo dnf install hyprlang-devel -y
# KDE
v sudo dnf install bluedevil gnome-keyring NetworkManager plasma-nm polkit-kde dolphin plasma-systemsettings -y
-# Microtex-git
-v sudo dnf install --setopt="install_weak_deps=False" tinyxml2-devel gtkmm3.0-devel gtksourceviewmm3-devel cairomm-devel -y
+# MicroTeX-git
+v sudo dnf install microtex -y
# Portal
v sudo dnf install xdg-desktop-portal{,-gtk,-kde,-hyprland} -y
@@ -69,14 +72,13 @@ v sudo dnf install python3{,.12}{,-devel} -y
# Quickshell-git
quickshell_deps=(
- qt6-qtdeclarative qt6-qtbase jemalloc qt6-qtsvg pipewire-libs
- libxcb wayland-devel qt6-qtwayland qt5-qtwayland libdrm breakpad
+ qt6-qtdeclarative qt6-qtbase jemalloc qt6-qtsvg pipewire-libs libxcb wayland-devel qt6-qtwayland
+ qt5-qtwayland libdrm breakpad
)
# NOTE: Below are custom dependencies of illogical-impulse
quickshell_custom_deps=(
- qt6-qt5compat qt6-qtimageformats qt6-qtpositioning
- qt6-qtquicktimeline qt6-qtsensors qt6-qttools qt6-qttranslations
- qt6-qtvirtualkeyboard qt6-qtwayland kdialog kf6-syntax-highlighting
+ qt6-qt5compat qt6-qtimageformats qt6-qtpositioning qt6-qtquicktimeline qt6-qtsensors qt6-qttools
+ qt6-qttranslations qt6-qtvirtualkeyboard qt6-qtwayland kdialog kf6-syntax-highlighting kf6-kirigami
)
quickshell_build_deps=(
breakpad-static breakpad-devel gcc-c++ ninja-build mesa-libgbm-devel cli11-devel glib2-devel
@@ -102,24 +104,24 @@ v sudo dnf install --setopt="install_weak_deps=False" mpvpaper plasma-systemmoni
# Start building the missing RPM package locally.
install_RPMS() {
- rpmbuildroot=${REPO_ROOT}/cache/rpmbuild
- x mkdir -p $rpmbuildroot/{BUILD,RPMS,SOURCES}
- x cp -r ${REPO_ROOT}/sdata/dist-fedora/SPECS $rpmbuildroot/
- x cd $rpmbuildroot/SPECS
- mapfile -t -d '' local_specs < <(find "$rpmbuildroot/SPECS" -maxdepth 1 -type f -name "*.spec" -print0)
- for spec_file in ${local_specs[@]}; do
- x rpmbuild -bb --define "_topdir $rpmbuildroot" $spec_file
- done
- mapfile -t -d '' local_rpms < <(find "$rpmbuildroot/RPMS" -maxdepth 2 -type f -name '*.rpm' -not -name '*debug*' -print0)
- echo -e "${STY_BLUE}Next command:${STY_RST} sudo dnf install ${local_rpms[@]} -y"
- x sudo dnf install "${local_rpms[@]}" -y
- x cd ${REPO_ROOT}
+ rpmbuildroot=${REPO_ROOT}/cache/rpmbuild
+ x mkdir -p $rpmbuildroot/{BUILD,RPMS,SOURCES}
+ x cp -r ${REPO_ROOT}/sdata/dist-fedora/SPECS $rpmbuildroot/
+ x cd $rpmbuildroot/SPECS
+ mapfile -t -d '' local_specs < <(find "$rpmbuildroot/SPECS" -maxdepth 1 -type f -name "*.spec" -print0)
+ for spec_file in ${local_specs[@]}; do
+ x spectool -g -C "$rpmbuildroot/SOURCES" $spec_file
+ x rpmbuild -bb --define "_topdir $rpmbuildroot" $spec_file
+ done
+ mapfile -t -d '' local_rpms < <(find "$rpmbuildroot/RPMS" -maxdepth 2 -type f -name '*.rpm' -not -name '*debug*' -print0)
+ echo -e "${STY_BLUE}Next command:${STY_RST} sudo dnf install ${local_rpms[@]} -y"
+ x sudo dnf install "${local_rpms[@]}" -y
+ x cd ${REPO_ROOT}
}
showfun install_RPMS
v install_RPMS
-
# hyprland-qtutils depends on hyprland-qt-support
v sudo dnf install hyprland-qtutils -y
diff --git a/sdata/dist-nix/home-manager/quickshell.nix b/sdata/dist-nix/home-manager/quickshell.nix
index 823797082..0fb7b57fe 100644
--- a/sdata/dist-nix/home-manager/quickshell.nix
+++ b/sdata/dist-nix/home-manager/quickshell.nix
@@ -40,6 +40,7 @@ in pkgs.stdenv.mkDerivation {
qt6.qttranslations #qt6-translations
qt6.qtvirtualkeyboard #qt6-virtualkeyboard
qt6.qtwayland #qt6-wayland
+ kdePackages.kirigami #kirigami
kdePackages.kdialog #kdialog
kdePackages.syntax-highlighting #syntax-highlighting
];
diff --git a/sdata/lib/dist-determine.sh b/sdata/lib/dist-determine.sh
index 46f9afdd8..78f548ac1 100644
--- a/sdata/lib/dist-determine.sh
+++ b/sdata/lib/dist-determine.sh
@@ -25,7 +25,9 @@ function print_os_group_id_unofficial(){
printf "The support for your distro is provided by the community.\n"
printf "It is not officially supported by github:end-4/dots-hyprland .\n"
printf "${STY_BOLD}"
- printf "If you find out any problems about it, PR is welcomed if you are able to address it. Or, create a discussion about it, but please do not submit issue, because the developers do not use this distro, therefore they cannot help.${STY_RST}\n"
+ printf "If you find out any problems about it, PR is welcomed if you are able to address it.\n"
+ printf "Or, create a discussion about it, but please do not submit issue, \n"
+ printf "because the developers do not use this distro, therefore they cannot help.${STY_RST}\n"
printf "${STY_PURPLE}"
printf "Proceed only at your own risk.\n"
printf "============\n\n"
diff --git a/sdata/subcmd-install/1.deps-router.sh b/sdata/subcmd-install/1.deps-router.sh
index 1287e4c6f..dd6712518 100644
--- a/sdata/subcmd-install/1.deps-router.sh
+++ b/sdata/subcmd-install/1.deps-router.sh
@@ -64,26 +64,42 @@ elif [[ "$OS_GROUP_ID" =~ ^(arch|gentoo|fedora)$ ]]; then
if [[ "${tmp_update_status}" =~ ^(OUTDATED|EMPTY_TARGET|EMPTY_SOURCE|FORCE_OUTDATED|WIP)$ ]]; then
printf "${STY_RED}${STY_BOLD}===URGENT===${STY_RST}\n"
printf "${STY_RED}"
- printf "The community provided ./sdata/dist-${TARGET_ID}/ is outdated (status: ${tmp_update_status}),\n"
+ printf "Status code: ${tmp_update_status}\n"
+ printf "The community provided ./sdata/dist-${TARGET_ID}/ seems to be outdated,\n"
printf "which means it probably does not reflect all latest changes of ./sdata/dist-arch/ .\n"
+ printf "In such case it may work unexpectedly.${STY_RST}\n"
printf "\n"
- printf "According to the actual changes, it may still works, but it can also work unexpectedly.\n"
- printf "It's highly recommended to check the following links before continue:${STY_RST}\n"
- printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/2140${STY_RST}\n"
- printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-arch${STY_RST}\n"
- printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-${TARGET_ID}${STY_RST}\n"
+ printf "${STY_RED}It's highly recommended to check the following links before continue.${STY_RST}\n"
+ printf "${STY_RED}1. Normally just check discussion#2140 to see if there's any valid update notice.${STY_RST}\n"
+ printf " ${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/2140${STY_RST}\n"
+ printf " ${STY_RED}Note that the timeliness relies on manual maintenance.${STY_RST}\n"
+ printf "${STY_RED}2. For details please compare the two lists of commit history:${STY_RST}\n"
+ printf " ${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-arch${STY_RST}\n"
+ printf " ${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-${TARGET_ID}${STY_RST}\n"
printf "\n"
- printf "${STY_PURPLE}${STY_INVERT}PR on ./sdata/dist-${TARGET_ID}/ to properly reflect the latest changes of ./sdata/dist-arch is welcomed.${STY_RST}\n"
+ printf "${STY_PURPLE}PR on ./sdata/dist-${TARGET_ID}/ to properly reflect the latest changes of ./sdata/dist-arch is welcomed.${STY_RST}\n"
+ printf "${STY_PURPLE}${STY_BOLD}Again, do not create any issue,${STY_RST}\n"
+ printf "${STY_PURPLE}but you can create a discussion under \"Extra Distros\" category: ${STY_RST}\n"
+ printf "${STY_PURPLE}${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/new?category=extra-distros${STY_RST}\n"
printf "\n"
- if [ "$ask" = "false" ]; then
- echo "Urgent problem encountered, aborting...";exit 1
- else
- printf "${STY_RED}Still proceed?${STY_RST}\n"
- read -p "[y/N]: " p
- case "$p" in
- [yY])sleep 0;;
- *)echo "Aborting...";exit 1;;
- esac
+ if [[ "${tmp_update_status}" = "OUTDATED" ]]; then
+ printf "${STY_RED}NOTE: The conclusion above is determined automatically by comparing latest Git commit time,\n"
+ printf "however sometimes the changes on \"dist-arch\" are actually not needed for \"dist-${TARGET_ID}\",\n"
+ printf "in such case you should just ignore it and continue.\n"
+ printf "${STY_RST}\n"
+ fi
+ printf "\n"
+ if ! [[ "$IGNORE_OUTDATE_CHECK" = "true" ]]; then
+ if [ "$ask" = "false" ]; then
+ printf "${STY_RED}Urgent problem encountered, aborting...${STY_RST}\n";exit 1
+ else
+ printf "${STY_RED}Still proceed?${STY_RST}\n"
+ read -p "[y/N]: " p
+ case "$p" in
+ [yY])sleep 0;;
+ *)echo "Aborting...";exit 1;;
+ esac
+ fi
fi
fi
fi
diff --git a/sdata/subcmd-install/2.setups.sh b/sdata/subcmd-install/2.setups.sh
index 2e585832c..c321bd752 100644
--- a/sdata/subcmd-install/2.setups.sh
+++ b/sdata/subcmd-install/2.setups.sh
@@ -2,19 +2,22 @@
# It's not for directly running.
function prepare_systemd_user_service(){
- if [[ ! -d "${XDG_CONFIG_HOME}/systemd/user" ]]; then
- x mkdir -p "${XDG_CONFIG_HOME}/systemd/user"
- fi
- if [[ ! -e "${XDG_CONFIG_HOME}/systemd/user/ydotool.service" ]]; then
- x ln -s /usr/lib/systemd/system/ydotool.service "${XDG_CONFIG_HOME}/systemd/user/ydotool.service"
+ if [[ ! -e "/usr/lib/systemd/user/ydotool.service" ]]; then
+ x sudo ln -s /usr/lib/systemd/{system,user}/ydotool.service
fi
}
function setup_user_group(){
- if [[ -z $(getent group i2c) ]]; then
+ if [[ -z $(getent group i2c) ]] && [[ "$OS_GROUP_ID" != "fedora" ]]; then
+ # On Fedora this is not needed. Tested with desktop computer with NVIDIA video card.
x sudo groupadd i2c
fi
- x sudo usermod -aG video,i2c,input "$(whoami)"
+
+ if [[ "$OS_GROUP_ID" == "fedora" ]]; then
+ x sudo usermod -aG video,input "$(whoami)"
+ else
+ x sudo usermod -aG video,i2c,input "$(whoami)"
+ fi
}
#####################################################################################
# These python packages are installed using uv into the venv (virtual environment). Once the folder of the venv gets deleted, they are all gone cleanly. So it's considered as setups, not dependencies.
@@ -25,8 +28,7 @@ showfun setup_user_group
v setup_user_group
if [[ ! -z $(systemctl --version) ]]; then
- # TODO: Why fedora does not add i2c-dev?
- # TODO: Why fedora add uinput and udev rules?
+ # For Fedora, uinput is required for the virtual keyboard to function, and udev rules enable input group users to utilize it.
if [[ "$OS_GROUP_ID" == "fedora" ]]; then
v bash -c "echo uinput | sudo tee /etc/modules-load.d/uinput.conf"
v bash -c 'echo SUBSYSTEM==\"misc\", KERNEL==\"uinput\", MODE=\"0660\", GROUP=\"input\" | sudo tee /etc/udev/rules.d/99-uinput.rules'
diff --git a/sdata/subcmd-install/options.sh b/sdata/subcmd-install/options.sh
index 992010cfb..727a3c13b 100644
--- a/sdata/subcmd-install/options.sh
+++ b/sdata/subcmd-install/options.sh
@@ -14,6 +14,7 @@ Options for install:
--skip-alldeps Skip the whole process installing dependency
--skip-allsetups Skip the whole process setting up permissions/services etc
--skip-allfiles Skip the whole process copying configuration files
+ --ignore-outdate Ignore outdate checking for community supported \"dist-*\".
-s, --skip-sysupdate Skip system package upgrade e.g. \"sudo pacman -Syu\"
--skip-plasmaintg Skip installing plasma-browser-integration
--skip-backup Skip backup conflicting files
@@ -45,7 +46,7 @@ cleancache(){
# `man getopt` to see more
para=$(getopt \
-o hfFk:cs \
- -l help,force,firstrun,fontset:,clean,skip-allgreeting,skip-alldeps,skip-allsetups,skip-allfiles,skip-sysupdate,skip-plasmaintg,skip-backup,skip-quickshell,skip-fish,skip-hyprland,skip-fontconfig,skip-miscconf,core,exp-files,via-nix \
+ -l help,force,firstrun,fontset:,clean,skip-allgreeting,skip-alldeps,skip-allsetups,skip-allfiles,ignore-outdate,skip-sysupdate,skip-plasmaintg,skip-backup,skip-quickshell,skip-fish,skip-hyprland,skip-fontconfig,skip-miscconf,core,exp-files,via-nix \
-n "$0" -- "$@")
[ $? != 0 ] && echo "$0: Error when getopt, please recheck parameters." && exit 1
#####################################################################################
@@ -76,6 +77,7 @@ while true ; do
--skip-allsetups) SKIP_ALLSETUPS=true;shift;;
--skip-allfiles) SKIP_ALLFILES=true;shift;;
-s|--skip-sysupdate) SKIP_SYSUPDATE=true;shift;;
+ --ignore-outdate) IGNORE_OUTDATE_CHECK=true;shift;;
--skip-plasmaintg) SKIP_PLASMAINTG=true;shift;;
--skip-backup) SKIP_BACKUP=true;shift;;
--skip-hyprland) SKIP_HYPRLAND=true;shift;;