diff --git a/dots/.config/hypr/hyprland/keybinds.conf b/dots/.config/hypr/hyprland/keybinds.conf
index 020fe582d..6032ab65a 100644
--- a/dots/.config/hypr/hyprland/keybinds.conf
+++ b/dots/.config/hypr/hyprland/keybinds.conf
@@ -4,27 +4,27 @@
#!
##! Shell
# These absolutely need to be on top, or they won't work consistently
-bindid = Super, Super_L, Toggle overview, global, quickshell:overviewToggleRelease # Toggle overview/launcher
-bindid = Super, Super_R, Toggle overview, global, quickshell:overviewToggleRelease # [hidden] Toggle overview/launcher
+bindid = Super, Super_L, Toggle search, global, quickshell:searchToggleRelease # Toggle search
+bindid = Super, Super_R, Toggle search, global, quickshell:searchToggleRelease # [hidden] Toggle search
bind = Super, Super_L, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill fuzzel || fuzzel # [hidden] Launcher (fallback)
bind = Super, Super_R, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill fuzzel || fuzzel # [hidden] Launcher (fallback)
-binditn = Super, catchall, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Ctrl, Super_L, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Ctrl, Super_R, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Super, mouse:272, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Super, mouse:273, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Super, mouse:274, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Super, mouse:275, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Super, mouse:276, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Super, mouse:277, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Super, mouse_up, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
-bind = Super, mouse_down,global, quickshell:overviewToggleReleaseInterrupt # [hidden]
+binditn = Super, catchall, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Ctrl, Super_L, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Ctrl, Super_R, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Super, mouse:272, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Super, mouse:273, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Super, mouse:274, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Super, mouse:275, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Super, mouse:276, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Super, mouse:277, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Super, mouse_up, global, quickshell:searchToggleReleaseInterrupt # [hidden]
+bind = Super, mouse_down,global, quickshell:searchToggleReleaseInterrupt # [hidden]
bindit = ,Super_L, global, quickshell:workspaceNumber # [hidden]
bindit = ,Super_R, global, quickshell:workspaceNumber # [hidden]
+bind = Super, Tab, global, quickshell:overviewWorkspacesToggle # Toggle overview
bindd = Super, V, Clipboard history >> clipboard, global, quickshell:overviewClipboardToggle # Clipboard history >> clipboard
bindd = Super, Period, Emoji >> clipboard, global, quickshell:overviewEmojiToggle # Emoji >> clipboard
-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]
@@ -218,8 +218,8 @@ submap = global
#!
# Testing
-bind = Super+Alt, f11, exec, bash -c 'RANDOM_IMAGE=$(find ~/Pictures -type f | grep -v -i "nipple" | grep -v -i "pussy" | shuf -n 1); ACTION=$(notify-send "Test notification with body image" "This notification should contain your user account image and Discord icon. Oh and here is a random image in your Pictures folder:
" -a "Hyprland keybind" -p -h "string:image-path:/var/lib/AccountsService/icons/$USER" -t 6000 -i "discord" -A "openImage=Open profile image" -A "action2=Open the random image" -A "action3=Useless button"); [[ $ACTION == *openImage ]] && xdg-open "/var/lib/AccountsService/icons/$USER"; [[ $ACTION == *action2 ]] && xdg-open \"$RANDOM_IMAGE\"' # [hidden]
-bind = Super+Alt, f12, exec, bash -c 'RANDOM_IMAGE=$(find ~/Pictures -type f | grep -v -i "nipple" | grep -v -i "pussy" | shuf -n 1); ACTION=$(notify-send "Test notification" "This notification should contain a random image in your Pictures folder and Discord icon.\nFlick right to dismiss!" -a "Discord (fake)" -p -h "string:image-path:$RANDOM_IMAGE" -t 6000 -i "discord" -A "openImage=Open profile image" -A "action2=Useless button" -A "action3=Cry more"); [[ $ACTION == *openImage ]] && xdg-open "/var/lib/AccountsService/icons/$USER"' # [hidden]
+bind = Super+Alt, f11, exec, bash -c 'RANDOM_IMAGE=$(find ~/Pictures -type f | grep -v -i "nipple" | grep -v -i "pussy" | shuf -n 1); ACTION=$(notify-send "Test notification with body image" "This notification should contain your user account image and Discord icon. Oh and here is a random image in your Pictures folder:
" -a "Hyprland keybind" -p -h "string:image-path:/var/lib/AccountsService/icons/$USER" -t 6000 -i "discord" -A "openImage=Profile image" -A "action2=Open the random image" -A "action3=Useless button"); [[ $ACTION == *openImage ]] && xdg-open "/var/lib/AccountsService/icons/$USER"; [[ $ACTION == *action2 ]] && xdg-open \"$RANDOM_IMAGE\"' # [hidden]
+bind = Super+Alt, f12, exec, bash -c 'RANDOM_IMAGE=$(find ~/Pictures -type f | grep -v -i "nipple" | grep -v -i "pussy" | shuf -n 1); ACTION=$(notify-send "Test notification" "This notification should contain a random image in your Pictures folder and Discord icon.\nFlick right to dismiss!" -a "Discord (fake)" -p -h "string:image-path:$RANDOM_IMAGE" -t 6000 -i "discord" -A "openImage=Profile image" -A "action2=Useless button"); [[ $ACTION == *openImage ]] && xdg-open "/var/lib/AccountsService/icons/$USER"' # [hidden]
bind = Super+Alt, Equal, exec, notify-send "Urgent notification" "Ah hell no" -u critical -a 'Hyprland keybind' # [hidden]
##! Session
diff --git a/dots/.config/quickshell/ii/GlobalStates.qml b/dots/.config/quickshell/ii/GlobalStates.qml
index 972495c64..85a0414d6 100644
--- a/dots/.config/quickshell/ii/GlobalStates.qml
+++ b/dots/.config/quickshell/ii/GlobalStates.qml
@@ -20,6 +20,7 @@ Singleton {
property bool overlayOpen: false
property bool overviewOpen: false
property bool regionSelectorOpen: false
+ property bool searchOpen: false
property bool screenLocked: false
property bool screenLockContainsCharacters: false
property bool screenUnlockFailed: false
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/power-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/power-filled.svg
new file mode 100644
index 000000000..2cfa6dba7
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/power-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/power.svg b/dots/.config/quickshell/ii/assets/icons/fluent/power.svg
new file mode 100644
index 000000000..5c28fe986
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/power.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
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
index af58d933f..84f42c500 100644
--- 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
@@ -26,8 +26,8 @@
inkscape:zoom="4.65625"
inkscape:cx="32"
inkscape:cy="32"
- inkscape:window-width="1197"
- inkscape:window-height="1020"
+ inkscape:window-width="1595"
+ inkscape:window-height="664"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
@@ -48,10 +48,10 @@
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
index 8d0e69fce..76af86e67 100644
--- 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
@@ -23,10 +23,10 @@
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="6.5849319"
- inkscape:cx="26.95548"
+ inkscape:cx="27.031411"
inkscape:cy="26.423963"
- inkscape:window-width="1257"
- inkscape:window-height="1020"
+ inkscape:window-width="1621"
+ inkscape:window-height="820"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
@@ -35,10 +35,10 @@
id="defs2">
diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml
index 56f647684..9afbed44b 100644
--- a/dots/.config/quickshell/ii/modules/common/Directories.qml
+++ b/dots/.config/quickshell/ii/modules/common/Directories.qml
@@ -1,6 +1,7 @@
pragma Singleton
pragma ComponentBehavior: Bound
+import qs.services
import qs.modules.common.functions
import QtCore
import QtQuick
@@ -46,6 +47,9 @@ Singleton {
property string aiChats: FileUtils.trimFileProtocol(`${Directories.state}/user/ai/chats`)
property string aiTranslationScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/ai/gemini-translate.sh`)
property string recordScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/videos/record.sh`)
+ property string userAvatarPathAccountsService: FileUtils.trimFileProtocol(`/var/lib/AccountsService/icons/${SystemInfo.username}`)
+ property string userAvatarPathRicersAndWeirdSystems: FileUtils.trimFileProtocol(`${Directories.home}.face`)
+ property string userAvatarPathRicersAndWeirdSystems2: FileUtils.trimFileProtocol(`${Directories.home}.face.icon`)
// Cleanup on init
Component.onCompleted: {
Quickshell.execDetached(["mkdir", "-p", `${shellConfig}`])
diff --git a/dots/.config/quickshell/ii/modules/common/functions/NotificationUtils.qml b/dots/.config/quickshell/ii/modules/common/functions/NotificationUtils.qml
index 8a336e8ad..d6adcc0f6 100644
--- a/dots/.config/quickshell/ii/modules/common/functions/NotificationUtils.qml
+++ b/dots/.config/quickshell/ii/modules/common/functions/NotificationUtils.qml
@@ -84,4 +84,28 @@ Singleton {
// Older dates
return Qt.formatDateTime(messageTime, "MMMM dd");
}
+
+ function processNotificationBody(body, appName) {
+ let processedBody = body
+
+ // Clean Chromium-based browsers notifications - remove first line
+ if (appName) {
+ const lowerApp = appName.toLowerCase()
+ const chromiumBrowsers = [
+ "brave", "chrome", "chromium", "vivaldi", "opera", "microsoft edge"
+ ]
+
+ if (chromiumBrowsers.some(name => lowerApp.includes(name))) {
+ const lines = body.split('\n\n')
+
+ if (lines.length > 1 && lines[0].startsWith(' lowerApp.includes(name))) {
- const lines = body.split('\n\n')
-
- if (lines.length > 1 && lines[0].startsWith('")
+ return NotificationUtils.processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
")
}
}
}
ColumnLayout { // Expanded content
+ id: expandedContentColumn
Layout.fillWidth: true
opacity: root.expanded ? 1 : 0
visible: opacity > 0
@@ -218,8 +197,8 @@ Item { // Notification item area
elide: Text.ElideRight
textFormat: Text.RichText
text: {
- return `` +
- `${processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
")}`
+ return `` +
+ `${NotificationUtils.processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
")}`
}
onLinkActivated: (link) => {
@@ -293,6 +272,8 @@ Item { // Notification item area
id: actionRepeater
model: notificationObject.actions
NotificationActionButton {
+ id: notifAction
+ required property var modelData
Layout.fillWidth: true
buttonText: modelData.text
urgency: notificationObject.urgency
diff --git a/dots/.config/quickshell/ii/modules/common/widgets/StyledImage.qml b/dots/.config/quickshell/ii/modules/common/widgets/StyledImage.qml
index c360b536c..17dfc56c4 100644
--- a/dots/.config/quickshell/ii/modules/common/widgets/StyledImage.qml
+++ b/dots/.config/quickshell/ii/modules/common/widgets/StyledImage.qml
@@ -12,4 +12,14 @@ Image {
Behavior on opacity {
animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
}
+
+ property list fallbacks: []
+ property int currentFallbackIndex: 0
+
+ onStatusChanged: {
+ if (status === Image.Error && currentFallbackIndex < fallbacks.length) {
+ source = fallbacks[currentFallbackIndex];
+ currentFallbackIndex += 1;
+ }
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml b/dots/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml
index 53797fb66..4688b29be 100644
--- a/dots/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml
+++ b/dots/.config/quickshell/ii/modules/common/widgets/StyledToolTip.qml
@@ -20,6 +20,7 @@ ToolTip {
hintingPreference: Font.PreferNoHinting // Prevent shaky text
}
+ delay: 0
visible: internalVisibleCondition
contentItem: StyledToolTipContent {
diff --git a/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml b/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml
index 248b46b56..c435f7f8a 100644
--- a/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml
+++ b/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml
@@ -162,7 +162,7 @@ Scope {
}
IpcHandler {
- target: "overview"
+ target: "search"
function toggle() {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
@@ -185,8 +185,8 @@ Scope {
}
GlobalShortcut {
- name: "overviewToggle"
- description: "Toggles overview on press"
+ name: "searchToggle"
+ description: "Toggles search on press"
onPressed: {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
@@ -201,16 +201,8 @@ Scope {
}
}
GlobalShortcut {
- name: "overviewClose"
- description: "Closes overview"
-
- onPressed: {
- GlobalStates.overviewOpen = false;
- }
- }
- GlobalShortcut {
- name: "overviewToggleRelease"
- description: "Toggles overview on release"
+ name: "searchToggleRelease"
+ description: "Toggles search on release"
onPressed: {
GlobalStates.superReleaseMightTrigger = true;
@@ -225,8 +217,8 @@ Scope {
}
}
GlobalShortcut {
- name: "overviewToggleReleaseInterrupt"
- description: "Interrupts possibility of overview being toggled on release. " + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything."
+ name: "searchToggleReleaseInterrupt"
+ description: "Interrupts possibility of search being toggled on release. " + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything."
onPressed: {
GlobalStates.superReleaseMightTrigger = false;
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
index 20af517fe..440695a2e 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
@@ -66,7 +66,7 @@ BarButton {
}
}
- AppIcon {
+ WAppIcon {
id: iconWidget
anchors.centerIn: parent
iconName: root.iconName
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
index 53a37cba0..4502b22f7 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
@@ -5,17 +5,12 @@ import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
-WButton {
+AcrylicButton {
id: root
property var altAction: () => {}
property var middleClickAction: () => {}
- colBackground: ColorUtils.transparentize(Looks.colors.bg1)
- colBackgroundHover: Looks.colors.bg1Hover
- colBackgroundActive: Looks.colors.bg1Active
- property color colBackgroundBorder
- property color color
Layout.fillHeight: true
topInset: 4
bottomInset: 4
@@ -23,16 +18,7 @@ WButton {
rightInset: 0
horizontalPadding: 8
- colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, (root.checked || root.hovered) ? Looks.backgroundTransparency : 1)
- color: {
- if (root.down) {
- return root.colBackgroundActive
- } else if ((root.hovered && !root.down) || root.checked) {
- return root.colBackgroundHover
- } else {
- return root.colBackground
- }
- }
+ colBackground: ColorUtils.transparentize(Looks.colors.bg1)
MouseArea {
anchors.fill: parent
@@ -50,15 +36,4 @@ WButton {
}
}
- background: AcrylicRectangle {
- shiny: ((root.hovered && !root.down) || root.checked)
- color: root.color
- radius: Looks.radius.medium
- border.width: 1
- border.color: root.colBackgroundBorder
-
- Behavior on border.color {
- animation: Looks.transition.color.createObject(this)
- }
- }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
index f4a15cc00..a92a85578 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
@@ -7,14 +7,16 @@ import qs.services
import qs.modules.common
import qs.modules.waffle.looks
+// TODO: Replace the icon with QMLized svg (with /usr/lib/qt6/bin/svgtoqml) for proper micro-animation
AppButton {
id: root
leftInset: Config.options.waffles.bar.leftAlignApps ? 12 : 0
iconName: down ? "start-here-pressed" : "start-here"
+ checked: GlobalStates.searchOpen
onClicked: {
- GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now...
+ GlobalStates.searchOpen = !GlobalStates.searchOpen;
}
BarToolTip {
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
index 51a3175bc..c1c16096b 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
@@ -42,7 +42,7 @@ AppButton {
}
spacing: 6
- AppIcon {
+ WAppIcon {
id: iconWidget
anchors.verticalCenter: parent.verticalCenter
iconName: root.iconName
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/WindowPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/WindowPreview.qml
index 2839a6747..9f114609f 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/WindowPreview.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/WindowPreview.qml
@@ -43,7 +43,7 @@ Button {
Layout.fillHeight: false
spacing: 8
- AppIcon {
+ WAppIcon {
id: appIcon
Layout.leftMargin: Looks.radius.large - root.padding + 2
Layout.alignment: Qt.AlignVCenter
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicButton.qml
new file mode 100644
index 000000000..ef5c0747a
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicButton.qml
@@ -0,0 +1,42 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+WButton {
+ id: root
+
+ colBackground: Looks.colors.bg1
+ colBackgroundHover: Looks.colors.bg1Hover
+ colBackgroundActive: Looks.colors.bg1Active
+ property color colBackgroundBorder
+ property color color
+ property alias border: background.border
+ property alias shinyColor: background.borderColor
+
+ colBackgroundBorder: ColorUtils.transparentize(color, (root.checked || root.hovered) ? Looks.backgroundTransparency : 0)
+ color: {
+ if (root.down) {
+ return root.colBackgroundActive
+ } else if ((root.hovered && !root.down) || root.checked) {
+ return root.colBackgroundHover
+ } else {
+ return root.colBackground
+ }
+ }
+
+ background: AcrylicRectangle {
+ id: background
+ shiny: ((root.hovered && !root.down) || root.checked)
+ color: root.color
+ radius: Looks.radius.medium
+ border.width: 1
+ border.color: root.colBackgroundBorder
+
+ Behavior on border.color {
+ animation: Looks.transition.color.createObject(this)
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicRectangle.qml b/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicRectangle.qml
index 7e041d111..7fecaa068 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicRectangle.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicRectangle.qml
@@ -9,16 +9,17 @@ Rectangle {
id: root
property bool shiny: true // Top border
- property color borderColor: ColorUtils.transparentize(Looks.colors.bg2Border, shiny ? 0.5 : 1)
+ property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Hover, 0.7)
+ property color internalBorderColor: ColorUtils.transparentize(borderColor, shiny ? 0.0 : 1)
color: Looks.colors.bg1Hover
radius: Looks.radius.medium
Behavior on color {
animation: Looks.transition.color.createObject(this)
}
- Behavior on borderColor {
+ Behavior on internalBorderColor {
animation: Looks.transition.color.createObject(this)
}
- onBorderColorChanged: {
+ onInternalBorderColorChanged: {
borderCanvas.requestPaint();
}
@@ -32,7 +33,7 @@ Rectangle {
var ctx = getContext("2d");
ctx.clearRect(0, 0, width, height);
- var borderColor = root.borderColor;
+ var borderColor = root.internalBorderColor;
var r = root.radius;
var fadeLength = Math.max(1, r);
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
index e55f840cb..609c9877b 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
@@ -53,6 +53,8 @@ Singleton {
property color controlBgHover: '#57575B'
property color controlFg: "#FFFFFF"
property color accentUnfocused: "#848484"
+ property color link: "#235CCF"
+ property color inputBg: ColorUtils.transparentize(bg0, 0.4)
}
darkColors: QtObject {
id: darkColors
@@ -70,7 +72,7 @@ Singleton {
property color bg2: '#8a8a8a'
property color bg2Hover: '#b1b1b1'
property color bg2Active: '#919191'
- property color bg2Border: '#c4c4c4'
+ property color bg2Border: '#bdbdbd'
property color subfg: "#CED1D7"
property color fg: "#FFFFFF"
property color fg1: "#D1D1D1"
@@ -80,6 +82,8 @@ Singleton {
property color controlBgHover: "#CFCED1"
property color controlFg: "#454545"
property color accentUnfocused: "#989898"
+ property color link: "#A7C9FC"
+ property color inputBg: ColorUtils.transparentize(darkColors.bg0, 0.5)
}
colors: QtObject {
id: colors
@@ -110,6 +114,8 @@ Singleton {
property color controlBg: root.dark ? root.darkColors.controlBg : root.lightColors.controlBg
property color controlBgHover: root.dark ? root.darkColors.controlBgHover : root.lightColors.controlBgHover
property color controlFg: root.dark ? root.darkColors.controlFg : root.lightColors.controlFg
+ property color inputBg: root.dark ? root.darkColors.inputBg : root.lightColors.inputBg
+ property color link: root.dark ? root.darkColors.link : root.lightColors.link
property color danger: "#C42B1C"
property color dangerActive: "#B62D1F"
property color warning: "#FF9900"
@@ -118,6 +124,7 @@ Singleton {
property color accentActive: Appearance.colors.colPrimaryActive
property color accentUnfocused: root.dark ? root.darkColors.accentUnfocused : root.lightColors.accentUnfocused
property color accentFg: ColorUtils.isDark(accent) ? "#FFFFFF" : "#000000"
+ property color selection: Appearance.colors.colPrimaryContainer
}
radius: QtObject {
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WAppIcon.qml
similarity index 94%
rename from dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
rename to dots/.config/quickshell/ii/modules/waffle/looks/WAppIcon.qml
index 48ff26104..6f71c65bb 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WAppIcon.qml
@@ -2,7 +2,6 @@ import QtQuick
import org.kde.kirigami as Kirigami
import qs.services
import qs.modules.common
-import qs.modules.waffle.looks
Kirigami.Icon {
id: root
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml
index 6b2bc4ecb..ceed470ba 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml
@@ -53,10 +53,11 @@ Button {
// Hover stuff
signal hoverTimedOut
property bool shouldShowTooltip: false
+ ToolTip.delay: 400
property Timer hoverTimer: Timer {
id: hoverTimer
running: root.hovered
- interval: 400
+ interval: root.ToolTip.delay
onTriggered: {
root.hoverTimedOut();
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WText.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WText.qml
index 240fd63be..0da156893 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/WText.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WText.qml
@@ -8,8 +8,11 @@ Text {
color: Looks.colors.fg
font {
+ hintingPreference: Font.PreferFullHinting
family: Looks.font.family.ui
pixelSize: Looks.font.pixelSize.normal
weight: Looks.font.weight.regular
}
+
+ linkColor: Looks.colors.link
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WTextInput.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WTextInput.qml
new file mode 100644
index 000000000..a3f3e8a40
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WTextInput.qml
@@ -0,0 +1,18 @@
+import QtQuick
+import QtQuick.Controls
+
+TextInput {
+ id: root
+ renderType: Text.NativeRendering
+ verticalAlignment: Text.AlignVCenter
+ color: Looks.colors.fg
+
+ font {
+ hintingPreference: Font.PreferFullHinting
+ family: Looks.font.family.ui
+ pixelSize: Looks.font.pixelSize.large
+ weight: Looks.font.weight.regular
+ }
+
+ selectionColor: Looks.colors.selection
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml
index 797cee28a..f49477988 100644
--- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml
@@ -20,6 +20,7 @@ WBarAttachedPanelContent {
property bool collapsed: false
contentItem: ColumnLayout {
+ id: contentLayout
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
@@ -41,9 +42,24 @@ WBarAttachedPanelContent {
}
contentItem: NotificationPaneContent {
implicitWidth: calendarColumnLayout.implicitWidth
- implicitHeight: Notifications.list.length > 0 ? (notificationArea.height - notificationPane.borderWidth * 2) : 230
+ implicitHeight: {
+ if (Notifications.list.length > 0) {
+ return ((contentLayout.height - calendarPane.height - contentLayout.spacing) - notificationPane.borderWidth * 2)
+ }
+ return 230;
+ }
+ Timer {
+ id: enableTimer
+ interval: Config.options.hacks.arbitraryRaceConditionDelay
+ onTriggered: heightBehavior.enabled = true;
+ }
Behavior on implicitHeight {
+ id: heightBehavior
+ enabled: false
+ Component.onCompleted: {
+ enableTimer.restart();
+ }
animation: Looks.transition.enter.createObject(this)
}
}
@@ -51,9 +67,9 @@ WBarAttachedPanelContent {
}
WPane {
- contentItem: ColumnLayout {
+ id: calendarPane
+ contentItem: WPanelPageColumn {
id: calendarColumnLayout
- spacing: 0
DateHeader {
Layout.fillWidth: true
Synchronizer on collapsed {
diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationHeaderButton.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationHeaderButton.qml
index 860451fc3..9aa20a690 100644
--- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationHeaderButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationHeaderButton.qml
@@ -8,18 +8,24 @@ import qs.modules.common.functions
import qs.modules.waffle.looks
WBorderlessButton {
- id: headerButton
+ id: root
Layout.fillWidth: false
- implicitWidth: 16
- implicitHeight: 16
+ property real implicitSize: 16
+ implicitWidth: implicitSize
+ implicitHeight: implicitSize
color: "transparent"
+ colForeground: root.hovered && !root.pressed ? Looks.colors.fg : Looks.colors.fg1
+
+ Behavior on colForeground {
+ animation: Looks.transition.color.createObject(this)
+ }
contentItem: Item {
FluentIcon {
anchors.centerIn: parent
- implicitSize: 16
- icon: headerButton.icon.name
- color: headerButton.hovered && !headerButton.pressed ? Looks.colors.fg : Looks.colors.fg1
+ implicitSize: root.implicitSize
+ icon: root.icon.name
+ color: root.colForeground
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/SmallBorderedIconAndTextButton.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/SmallBorderedIconAndTextButton.qml
index c4331a7dc..faab4d90d 100644
--- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/SmallBorderedIconAndTextButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/SmallBorderedIconAndTextButton.qml
@@ -2,18 +2,27 @@ import QtQuick
import qs
import qs.services
import qs.modules.common
+import qs.modules.common.functions
import qs.modules.waffle.looks
-SmallBorderedIconButton {
+AcrylicButton {
id: root
property bool iconVisible: true
property string iconName: ""
property bool iconFilled: true
+ colBackground: Looks.colors.bg2
+ colBackgroundHover: Looks.colors.bg2Hover
+ colBackgroundActive: Looks.colors.bg2Active
+ property color colBorder: Looks.colors.bg2Border
+ property color colBorderToggled: Looks.colors.accent
+ border.color: checked ? colBorderToggled : colBorder
+
leftPadding: 12
rightPadding: 12
implicitWidth: focusButtonContent.implicitWidth + leftPadding + rightPadding
+ implicitHeight: 24
contentItem: Row {
id: focusButtonContent
diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WNotificationGroup.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WNotificationGroup.qml
index 837c7c016..122469771 100644
--- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WNotificationGroup.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WNotificationGroup.qml
@@ -12,6 +12,7 @@ MouseArea {
required property var notificationGroup
readonly property var notifications: notificationGroup?.notifications ?? []
+ property bool expanded: false
implicitWidth: contentLayout.implicitWidth
implicitHeight: contentLayout.implicitHeight
@@ -34,12 +35,23 @@ MouseArea {
interactive: false
spacing: 4
model: ScriptModel {
- values: root.notifications.slice().reverse()
+ values: root.expanded ? root.notifications.slice().reverse() : root.notifications.slice(-1)
+ objectProp: "notificationId"
}
delegate: WSingleNotification {
+ required property int index
required property var modelData
width: ListView.view.width
notification: modelData
+ groupExpandControlMessage: {
+ if (root.notifications.length <= 1) return "";
+ if (!root.expanded) return Translation.tr("+%1 notifications").arg(root.notifications.length - 1);
+ if (index === root.notifications.length - 1) return Translation.tr("See fewer");
+ return "";
+ }
+ onGroupExpandToggle: {
+ root.expanded = !root.expanded;
+ }
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml
index 42a832adb..895ab6892 100644
--- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml
@@ -1,3 +1,4 @@
+pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
@@ -12,11 +13,18 @@ MouseArea {
id: root
required property var notification
- property bool expanded: false
+ property bool expanded: notification.actions.length > 0
+ property string groupExpandControlMessage: ""
+ signal groupExpandToggle
+ hoverEnabled: true
implicitHeight: contentItem.implicitHeight
implicitWidth: contentItem.implicitWidth
+ Behavior on implicitHeight {
+ animation: Looks.transition.enter.createObject(this)
+ }
+
Rectangle {
id: contentItem
anchors.fill: parent
@@ -26,34 +34,205 @@ MouseArea {
implicitHeight: notificationContent.implicitHeight + padding * 2
implicitWidth: notificationContent.implicitWidth + padding * 2
border.width: 1
- border.color: Looks.applyContentTransparency(Looks.colors.ambientShadow)
+ border.color: ColorUtils.applyAlpha(Looks.colors.ambientShadow, 0.1)
ColumnLayout {
id: notificationContent
anchors.fill: parent
anchors.margins: contentItem.padding
+ spacing: 19
- RowLayout {
+ // Header
+ SingleNotificationHeader {
Layout.fillWidth: true
- WText {
- text: NotificationUtils.getFriendlyNotifTimeString(root.notification?.time)
+ }
+
+ // Content
+ Item {
+ id: actualContent
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ property real spacing: 16
+ implicitHeight: Math.max(contentColumn.implicitHeight, imageLoader.height)
+ implicitWidth: contentColumn.implicitWidth
+
+ Loader {
+ id: imageLoader
+ anchors {
+ top: parent.top
+ left: parent.left
+ }
+ active: root.notification.image != ""
+ sourceComponent: StyledImage {
+ readonly property int size: 48
+ width: size
+ height: size
+ sourceSize.width: size
+ sourceSize.height: size
+ source: root.notification.image
+ fillMode: Image.PreserveAspectFit
+ }
+ }
+
+ ColumnLayout {
+ id: contentColumn
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ }
+ spacing: 3
+
+ SummaryText {
+ id: summaryText
+ Layout.leftMargin: imageLoader.active ? imageLoader.width + actualContent.spacing : 0
+ }
+ BodyText {
+ Layout.leftMargin: imageLoader.active ? imageLoader.width + actualContent.spacing : 0
+ // onLineLaidOut: (line) => {
+ // if (!imageLoader.active) return;
+ // const dodgeDistance = imageLoader.width + actualContent.spacing;
+ // // print(line.y, dodgeDistance)
+ // if (summaryText.height + line.y > dodgeDistance) {
+ // line.x -= dodgeDistance;
+ // line.width += dodgeDistance;
+ // }
+ // }
+ }
}
}
- ColumnLayout {
+ // Actions
+ ActionsRow {
Layout.fillWidth: true
- WText {
- Layout.fillWidth: true
- elide: Text.ElideRight
- text: root.notification.summary
- }
- WText {
- Layout.fillWidth: true
- elide: Text.ElideRight
+ }
+
+ // "+1 notifications" button
+ GroupExpandButton {
+ Layout.bottomMargin: 2
+ }
+ }
+ }
+
+ component SingleNotificationHeader: RowLayout {
+ ExpandButton {
+ Layout.topMargin: -2
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ NotificationHeaderButton {
+ Layout.rightMargin: 4
+ opacity: root.containsMouse ? 1 : 0
+ icon.name: "dismiss"
+ implicitSize: 12
+ onClicked: {
+ Qt.callLater(() => {
+ Notifications.discardNotification(root.notification?.notificationId);
+ });
+ }
+ }
+ }
+
+ component ActionsRow: RowLayout {
+ visible: root.expanded && root.notification.actions.length > 0
+ uniformCellSizes: true
+ Repeater {
+ id: actionRepeater
+ model: root.notification.actions
+ delegate: WBorderedButton {
+ id: actionButton
+ Layout.fillHeight: true
+ required property var modelData
+ Layout.fillWidth: true
+ verticalPadding: 16
+ horizontalPadding: 12
+ text: modelData.text
+ implicitHeight: actionButtonText.implicitHeight + verticalPadding * 2
+ contentItem: WText {
+ id: actionButtonText
+ text: actionButton.text
+ font.pixelSize: Looks.font.pixelSize.large
+ horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
- maximumLineCount: root.expanded ? 100 : 1
}
}
}
}
+
+ component SummaryText: WText {
+ Layout.fillWidth: true
+ elide: Text.ElideRight
+ text: root.notification?.summary
+ font.pixelSize: Looks.font.pixelSize.large
+ }
+
+ component BodyText: WText {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignTop
+ wrapMode: Text.Wrap
+ maximumLineCount: root.expanded ? 100 : 1
+ text: {
+ if (root.expanded)
+ return `` + `${NotificationUtils.processNotificationBody(root.notification.body, root.notification.appName || root.notification.summary).replace(/\n/g, "
")}`;
+ return NotificationUtils.processNotificationBody(root.notification.body, root.notification.appName || root.notification.summary).replace(/\n/g, "
");
+ }
+ color: Looks.colors.subfg
+ textFormat: root.expanded ? Text.RichText : Text.StyledText
+ onLinkActivated: link => {
+ Qt.openUrlExternally(link);
+ GlobalStates.sidebarRightOpen = false;
+ }
+ }
+
+ component ExpandButton: NotificationHeaderButton {
+ id: expandButton
+ implicitWidth: expandButtonContent.implicitWidth
+ onClicked: root.expanded = !root.expanded
+
+ contentItem: Item {
+ id: expandButtonContent
+ implicitWidth: expandButtonRow.implicitWidth
+ implicitHeight: expandButtonRow.implicitHeight
+ RowLayout {
+ id: expandButtonRow
+ anchors.centerIn: parent
+ spacing: 8
+ WText {
+ color: expandButton.colForeground
+ text: NotificationUtils.getFriendlyNotifTimeString(root.notification?.time)
+ }
+ FluentIcon {
+ Layout.rightMargin: 12
+ icon: "chevron-down"
+ implicitSize: 18
+ rotation: root.expanded ? -180 : 0
+ color: expandButton.colForeground
+ Behavior on rotation {
+ animation: Looks.transition.rotate.createObject(this)
+ }
+ }
+ }
+ }
+ }
+
+ component GroupExpandButton: AcrylicButton {
+ id: groupExpandButton
+ visible: root.groupExpandControlMessage !== ""
+ horizontalPadding: 10
+ implicitHeight: 24
+ implicitWidth: expandButtonText.implicitWidth + horizontalPadding * 2
+ onClicked: root.groupExpandToggle()
+ contentItem: Item {
+ WText {
+ id: expandButtonText
+ anchors.centerIn: parent
+ text: root.groupExpandControlMessage
+ }
+ }
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml
new file mode 100644
index 000000000..6bd23ae9b
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml
@@ -0,0 +1,84 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Quickshell
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+FooterRectangle {
+ id: root
+
+ property bool searching: text.length > 0
+ property alias text: searchInput.text
+
+ Component.onCompleted: searchInput.forceActiveFocus()
+
+ focus: true
+ color: searching ? Looks.colors.bgPanelBody : Looks.colors.bgPanelFooter
+
+ implicitWidth: 832 // TODO: Make sizes naturally inferred
+ implicitHeight: 63
+
+ Rectangle {
+ id: outline
+ anchors {
+ fill: parent
+ leftMargin: 32
+ rightMargin: 32
+ topMargin: 16
+ bottomMargin: 15
+ }
+ color: "transparent"
+ radius: height / 2
+ border.width: 1
+ border.color: Looks.colors.bg2Border
+ }
+
+ Rectangle {
+ id: searchInputBg
+ anchors.fill: outline
+ anchors.margins: 1
+ radius: height / 2
+ color: Looks.colors.inputBg
+
+ RowLayout {
+ anchors.fill: parent
+ spacing: 11
+
+ WAppIcon {
+ Layout.leftMargin: 14
+ iconName: "system-search-checked"
+ separateLightDark: true
+ implicitSize: 18
+ }
+
+ WTextInput {
+ id: searchInput
+ focus: true
+ Layout.fillWidth: true
+
+ WText {
+ anchors {
+ left: parent.left
+ verticalCenter: parent.verticalCenter
+ }
+ color: Looks.colors.accentUnfocused
+ text: Translation.tr("Search for apps") // should also have "", settings, and documents" but we don't have those
+ visible: searchInput.text.length === 0
+ font.pixelSize: Looks.font.pixelSize.large
+ }
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.IBeamCursor
+ acceptedButtons: Qt.NoButton
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml
new file mode 100644
index 000000000..cdbb7d3b8
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml
@@ -0,0 +1,16 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Quickshell
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+BodyRectangle {
+ id: root
+
+
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml
new file mode 100644
index 000000000..6e97f88be
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml
@@ -0,0 +1,39 @@
+pragma ComponentBehavior: Bound
+import Qt.labs.synchronizer
+import QtQuick
+import QtQuick.Controls
+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
+
+ property bool searching: false
+ property string searchText: ""
+
+ contentItem: WPane {
+ contentItem: WPanelPageColumn {
+ SearchBar {
+ focus: true
+ Layout.fillWidth: true
+ Synchronizer on searching {
+ property alias target: root.searching
+ }
+ Synchronizer on text {
+ property alias source: root.searchText
+ }
+ }
+ Loader {
+ id: pageContentLoader
+ Layout.fillWidth: true
+ source: root.searching ? "SearchPageContent.qml" : "StartPageContent.qml"
+ }
+ }
+ }
+
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartPageContent.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartPageContent.qml
new file mode 100644
index 000000000..36e605187
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartPageContent.qml
@@ -0,0 +1,98 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Qt5Compat.GraphicalEffects
+import Quickshell
+import org.kde.kirigami as Kirigami
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.common.widgets
+import qs.modules.waffle.looks
+
+WPanelPageColumn {
+ id: root
+
+ WPanelSeparator {}
+
+ BodyRectangle {
+ implicitHeight: 736 // TODO: Make sizes naturally inferred
+ }
+
+ WPanelSeparator {}
+
+ StartFooter {
+ Layout.fillWidth: true
+ }
+
+ component StartFooter: FooterRectangle {
+ implicitHeight: 63
+
+ UserButton {
+ anchors {
+ left: parent.left
+ leftMargin: 52
+ bottom: parent.bottom
+ bottomMargin: 12
+ }
+ }
+
+ PowerButton {
+ anchors {
+ right: parent.right
+ rightMargin: 52
+ bottom: parent.bottom
+ bottomMargin: 12
+ }
+ }
+ }
+
+ component UserButton: WBorderlessButton {
+ id: userButton
+ implicitWidth: userButtonRow.implicitWidth + 12 * 2
+ implicitHeight: 40
+
+ contentItem: Item {
+ RowLayout {
+ id: userButtonRow
+ anchors.centerIn: parent
+ spacing: 12
+
+ StyledImage {
+ id: avatar
+ // Use this for free fallback because I'm lazy
+ Layout.alignment: Qt.AlignTop
+ sourceSize: Qt.size(32, 32)
+ source: Directories.userAvatarPathAccountsService
+ fallbacks: [Directories.userAvatarPathRicersAndWeirdSystems, Directories.userAvatarPathRicersAndWeirdSystems2]
+
+ layer.enabled: true
+ layer.effect: OpacityMask {
+ maskSource: Circle {
+ diameter: avatar.height
+ }
+ }
+ }
+ WText {
+ Layout.alignment: Qt.AlignVCenter
+ text: SystemInfo.username
+ }
+ }
+ }
+ }
+
+ component PowerButton: WBorderlessButton {
+ implicitWidth: 40
+ implicitHeight: 40
+
+ contentItem: Item {
+ FluentIcon {
+ anchors.centerIn: parent
+ icon: "power"
+ implicitSize: 20
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/WaffleStartMenu.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/WaffleStartMenu.qml
new file mode 100644
index 000000000..9b59fb0c8
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/WaffleStartMenu.qml
@@ -0,0 +1,119 @@
+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 onSearchOpenChanged() {
+ if (GlobalStates.searchOpen)
+ panelLoader.active = true;
+ }
+ }
+
+ Loader {
+ id: panelLoader
+ active: GlobalStates.searchOpen
+ sourceComponent: PanelWindow {
+ id: panelWindow
+ exclusiveZone: 0
+ WlrLayershell.namespace: "quickshell:wStartMenu"
+ WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
+ color: "transparent"
+
+ anchors {
+ bottom: Config.options.waffles.bar.bottom
+ top: !Config.options.waffles.bar.bottom
+ left: Config.options.waffles.bar.leftAlignApps
+ }
+
+ implicitWidth: content.implicitWidth
+ implicitHeight: content.implicitHeight
+
+ HyprlandFocusGrab {
+ id: focusGrab
+ active: true
+ windows: [panelWindow]
+ onCleared: content.close()
+ }
+
+ Connections {
+ target: GlobalStates
+ function onSearchOpenChanged() {
+ if (!GlobalStates.searchOpen)
+ content.close();
+ }
+ }
+
+ StartMenuContent {
+ id: content
+ anchors.fill: parent
+ focus: true
+
+ onClosed: {
+ GlobalStates.searchOpen = false;
+ panelLoader.active = false;
+ }
+ }
+ }
+ }
+
+ IpcHandler {
+ target: "search"
+
+ function toggle() {
+ GlobalStates.searchOpen = !GlobalStates.searchOpen;
+ }
+ function close() {
+ GlobalStates.searchOpen = false;
+ }
+ function open() {
+ GlobalStates.searchOpen = true;
+ }
+ function toggleReleaseInterrupt() {
+ GlobalStates.superReleaseMightTrigger = false;
+ }
+ }
+
+ GlobalShortcut {
+ name: "searchToggle"
+ description: "Toggles search on press"
+
+ onPressed: {
+ GlobalStates.searchOpen = !GlobalStates.searchOpen;
+ }
+ }
+ GlobalShortcut {
+ name: "searchToggleRelease"
+ description: "Toggles search on release"
+
+ onPressed: {
+ GlobalStates.superReleaseMightTrigger = true;
+ }
+
+ onReleased: {
+ if (!GlobalStates.superReleaseMightTrigger) {
+ GlobalStates.superReleaseMightTrigger = true;
+ return;
+ }
+ GlobalStates.searchOpen = !GlobalStates.searchOpen;
+ }
+ }
+ GlobalShortcut {
+ name: "searchToggleReleaseInterrupt"
+ description: "Interrupts possibility of search being toggled on release. " + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything."
+
+ onPressed: {
+ GlobalStates.superReleaseMightTrigger = false;
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml
index 3f57c0c28..7bb565d11 100644
--- a/dots/.config/quickshell/ii/shell.qml
+++ b/dots/.config/quickshell/ii/shell.qml
@@ -33,6 +33,7 @@ import qs.modules.waffle.background
import qs.modules.waffle.bar
import qs.modules.waffle.notificationCenter
import qs.modules.waffle.onScreenDisplay
+import qs.modules.waffle.startMenu
import QtQuick
import QtQuick.Window
@@ -77,11 +78,13 @@ 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 {} }
PanelLoader { identifier: "wNotificationCenter"; component: WaffleNotificationCenter {} }
PanelLoader { identifier: "wOnScreenDisplay"; component: WaffleOSD {} }
+ PanelLoader { identifier: "wStartMenu"; component: WaffleStartMenu {} }
ReloadPopup {}
component PanelLoader: LazyLoader {
@@ -94,7 +97,7 @@ ShellRoot {
property list families: ["ii", "waffle"]
property var panelFamilies: ({
"ii": ["iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"],
- "waffle": ["wActionCenter", "wBar", "wBackground", "wNotificationCenter", "wOnScreenDisplay", "iiCheatsheet", "iiLock", "iiNotificationPopup", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiSessionScreen", "iiWallpaperSelector"],
+ "waffle": ["wActionCenter", "wBar", "wBackground", "wNotificationCenter", "wOnScreenDisplay", "wStartMenu", "iiCheatsheet", "iiLock", "iiNotificationPopup", "iiOnScreenKeyboard", "iiOverlay", "iiPolkit", "iiRegionSelector", "iiSessionScreen", "iiWallpaperSelector"],
})
function cyclePanelFamily() {
const currentIndex = families.indexOf(Config.options.panelFamily)
diff --git a/sdata/deps-info.md b/sdata/deps-info.md
index fc6f315a3..9a1e4e826 100644
--- a/sdata/deps-info.md
+++ b/sdata/deps-info.md
@@ -191,6 +191,9 @@ Tips:
- Used in Quickshell config.
- `wlogout`
- Used in Hyprland config.
+- `libqalculate`
+ - Used in Quickshell config, providing math ability in searchbar.
+ - Note that `qalc` is the needed executable. In Arch Linux [libqalculate](https://archlinux.org/packages/extra/x86_64/libqalculate) provides it, but in Fedora [qalculate](https://packages.fedoraproject.org/pkgs/libqalculate/qalculate/fedora-43.html#files) does and [libqalculate](https://packages.fedoraproject.org/pkgs/libqalculate/libqalculate/fedora-43.html#files) does not.
# Actual packages
diff --git a/sdata/dist-arch/illogical-impulse-widgets/PKGBUILD b/sdata/dist-arch/illogical-impulse-widgets/PKGBUILD
index 76f71d43f..fa9d4df02 100644
--- a/sdata/dist-arch/illogical-impulse-widgets/PKGBUILD
+++ b/sdata/dist-arch/illogical-impulse-widgets/PKGBUILD
@@ -1,6 +1,6 @@
pkgname=illogical-impulse-widgets
pkgver=1.0
-pkgrel=5
+pkgrel=6
pkgdesc='Illogical Impulse Widget Dependencies'
arch=(any)
license=(None)
@@ -14,4 +14,5 @@ depends=(
songrec
translate-shell
wlogout
+ libqalculate
)
diff --git a/sdata/dist-fedora/feddeps.toml b/sdata/dist-fedora/feddeps.toml
index f21169a1b..367626ced 100644
--- a/sdata/dist-fedora/feddeps.toml
+++ b/sdata/dist-fedora/feddeps.toml
@@ -181,6 +181,7 @@ packages = [
"hyprpicker",
"songrec",
"translate-shell",
+ "qalculate",
"wlogout"
]
@@ -191,4 +192,5 @@ packages = [
"plasma-systemmonitor",
"unzip"
]
-install_opts = ["--setopt=install_weak_deps=False"]
\ No newline at end of file
+install_opts = ["--setopt=install_weak_deps=False"]
+
diff --git a/sdata/dist-nix/README.md b/sdata/dist-nix/README.md
index 3a8120e04..9aca1d13f 100644
--- a/sdata/dist-nix/README.md
+++ b/sdata/dist-nix/README.md
@@ -37,8 +37,38 @@ As [commented](https://github.com/end-4/dots-hyprland/issues/1061#issuecomment-3
See also [caelestia-dots/shell#668](https://github.com/caelestia-dots/shell/issues/668).
-### NixGL
-On non-NixOS distros, packages installed via home-manager have problem accessing GPU, especially Hyprland because it requires GPU acceleration to launch. `nixGL` should be used to address the problem.
+### GPU
+On non-NixOS distros, packages installed via home-manager have problem accessing GPU, especially Hyprland because it requires GPU acceleration to launch.
+
+~~`nixGL` should be used to address the problem.~~
+
+Since home-manager 25.11, for non-NixOS just set the following:
+```nix
+targets.genericLinux.enable = true;
+```
+Then during building, home-manager will show a message to tell you running a command manually to configure GPU, like:
+```bash
+sudo /nix/store/-non-nixos-gpu/bin/non-nixos-gpu-setup
+```
+It runs a bash script with following content:
+```
+#!/nix/store/-bash-/bin/bash
+
+set -e
+
+# Install the systemd service file and ensure that the store path won't be
+# garbage-collected as long as it's installed.
+unit_path=/etc/systemd/system/non-nixos-gpu.service
+ln -sf /nix/store/-non-nixos-gpu/resources/non-nixos-gpu.service "$unit_path"
+ln -sf "$unit_path" "/nix/var/nix"/gcroots/non-nixos-gpu.service
+
+systemctl daemon-reload
+systemctl enable non-nixos-gpu.service
+systemctl restart non-nixos-gpu.service
+```
+_Note: it uses `systemctl`, maybe won't work for OpenRC..._
+
+See [gpu-non-nixos](https://nix-community.github.io/home-manager/index.xhtml#sec-usage-gpu-non-nixos).
# Handling dot files
## Status
diff --git a/sdata/dist-nix/home-manager/flake.nix b/sdata/dist-nix/home-manager/flake.nix
index d88daad6e..97a50c466 100644
--- a/sdata/dist-nix/home-manager/flake.nix
+++ b/sdata/dist-nix/home-manager/flake.nix
@@ -3,23 +3,24 @@
description = "illogical-impulse";
inputs = {
- # Qt 6.10 is not yet available from released version of nixpkgs.
- #nixpkgs.url = "nixpkgs/nixos-25.05";
- nixpkgs.url = "nixpkgs/nixos-unstable";
+ nixpkgs.url = "nixpkgs/nixos-25.11";
+ #nixpkgs.url = "nixpkgs/nixos-unstable";
home-manager = {
- #url = "github:nix-community/home-manager/release-25.05";
- url = "github:nix-community/home-manager/master";
+ url = "github:nix-community/home-manager/release-25.11";
+ #url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
- nixgl.url = "github:nix-community/nixGL";
+ #nixgl.url = "github:nix-community/nixGL";
quickshell = {
url = "github:quickshell-mirror/quickshell/db1777c20b936a86528c1095cbcb1ebd92801402";
inputs.nixpkgs.follows = "nixpkgs";
};
};
- outputs = { nixpkgs, home-manager, nixgl, quickshell, ... }:
+ outputs = { nixpkgs, home-manager,
+ #nixgl,
+ quickshell, ... }:
let
home_attrs = rec {
username = import ./username.nix;
@@ -36,7 +37,9 @@
homeConfigurations = {
illogical_impulse = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
- extraSpecialArgs = { inherit home_attrs nixgl quickshell; };
+ extraSpecialArgs = { inherit home_attrs
+ #nixgl
+ quickshell; };
modules = [
./home.nix
];
diff --git a/sdata/dist-nix/home-manager/home.nix b/sdata/dist-nix/home-manager/home.nix
index 596430395..b1381481d 100644
--- a/sdata/dist-nix/home-manager/home.nix
+++ b/sdata/dist-nix/home-manager/home.nix
@@ -1,8 +1,13 @@
-{ config, lib, pkgs, nixgl, quickshell, home_attrs, ... }:
+{ config, lib, pkgs,
+#nixgl,
+quickshell, home_attrs, ... }:
{
programs.home-manager.enable = true;
- nixGL.packages = nixgl.packages;
- nixGL.defaultWrapper = "mesa";
+
+ # Necessary for non-NixOS to handle GPU (since home-manager version 25.11)
+ targets.genericLinux.enable = true;
+ #nixGL.packages = nixgl.packages;
+ #nixGL.defaultWrapper = "mesa";
xdg.portal = {
enable = true;
@@ -27,7 +32,8 @@
systemd.enable = false; plugins = []; settings = {}; extraConfig = "";
enable = true;
## Use NixGL
- package = config.lib.nixGL.wrap pkgs.hyprland;
+ #package = config.lib.nixGL.wrap pkgs.hyprland;
+ package = pkgs.hyprland;
};
home = {
@@ -167,6 +173,7 @@
songrec #songrec
translate-shell #translate-shell
wlogout #wlogout
+ libqalculate #libqalculate
]
++ [
@@ -174,7 +181,9 @@
### illogical-impulse-quickshell-git
#(config.lib.nixGL.wrap quickshell.packages.x86_64-linux.default)
- (import ./quickshell.nix { inherit pkgs quickshell; nixGLWrap = config.lib.nixGL.wrap; })
+ (import ./quickshell.nix { inherit pkgs quickshell;
+ #nixGLWrap = config.lib.nixGL.wrap;
+ })
];
}//home_attrs;
}
diff --git a/sdata/dist-nix/home-manager/quickshell.nix b/sdata/dist-nix/home-manager/quickshell.nix
index 0fb7b57fe..fb81af848 100644
--- a/sdata/dist-nix/home-manager/quickshell.nix
+++ b/sdata/dist-nix/home-manager/quickshell.nix
@@ -1,10 +1,14 @@
-{ pkgs, quickshell, nixGLWrap, ... }:
+{ pkgs, quickshell,
+#nixGLWrap,
+... }:
let
- qs = nixGLWrap quickshell.packages.x86_64-linux.default;
+ #qs = nixGLWrap quickshell.packages.x86_64-linux.default;
+ qs = quickshell.packages.x86_64-linux.default;
in pkgs.stdenv.mkDerivation {
name = "illogical-impulse-quickshell-wrapper";
meta = with pkgs.lib; {
- description = "Quickshell wrapped with NixGL + bundled Qt deps for home-manager usage";
+ #description = "Quickshell wrapped with NixGL + bundled Qt deps for home-manager usage";
+ description = "Quickshell bundled Qt deps for home-manager usage";
license = licenses.gpl3Only;
};
diff --git a/sdata/dist-nix/install-deps.sh b/sdata/dist-nix/install-deps.sh
index 357bb498f..2049efb82 100644
--- a/sdata/dist-nix/install-deps.sh
+++ b/sdata/dist-nix/install-deps.sh
@@ -32,8 +32,8 @@ function install_home-manager(){
try source $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh
command -v $cmd && return
- x nix-channel --add https://nixos.org/channels/nixos-25.05 nixpkgs-home
- x nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.05.tar.gz home-manager
+ x nix-channel --add https://nixos.org/channels/nixos-25.11 nixpkgs-home
+ x nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager
x nix-channel --update
x env NIX_PATH="nixpkgs=$HOME/.nix-defexpr/channels/nixpkgs-home" nix-shell '' -A install
@@ -56,6 +56,7 @@ function hm_deps(){
x home-manager switch --flake .#illogical_impulse \
--extra-experimental-features nix-command \
--extra-experimental-features flakes
+ x sudo /nix/store/*-non-nixos-gpu/bin/non-nixos-gpu-setup
cd $REPO_ROOT
x git rm -f "${SETUP_USERNAME_NIXFILE}"
}