From 44422004791e8d651bf3094bfb6d51e7f1dee737 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 29 Nov 2025 23:23:58 +0100 Subject: [PATCH] waffles: start menu base --- dots/.config/hypr/hyprland/keybinds.conf | 32 ++--- dots/.config/quickshell/ii/GlobalStates.qml | 1 + .../ii/assets/icons/fluent/power-filled.svg | 4 + .../ii/assets/icons/fluent/power.svg | 4 + .../fluent/system-search-checked-dark.svg | 14 +-- .../fluent/system-search-checked-light.svg | 16 +-- .../ii/modules/common/Directories.qml | 4 + .../ii/modules/common/widgets/StyledImage.qml | 10 ++ .../modules/common/widgets/StyledToolTip.qml | 1 + .../ii/modules/ii/overview/Overview.qml | 22 ++-- .../ii/modules/waffle/bar/AppButton.qml | 2 +- .../ii/modules/waffle/bar/StartButton.qml | 3 +- .../ii/modules/waffle/bar/WidgetsButton.qml | 2 +- .../waffle/bar/tasks/WindowPreview.qml | 2 +- .../ii/modules/waffle/looks/Looks.qml | 6 +- .../{bar/AppIcon.qml => looks/WAppIcon.qml} | 1 - .../ii/modules/waffle/looks/WButton.qml | 3 +- .../ii/modules/waffle/looks/WTextInput.qml | 18 +++ .../NotificationCenterContent.qml | 3 +- .../WSingleNotification.qml | 16 ++- .../ii/modules/waffle/startMenu/SearchBar.qml | 84 +++++++++++++ .../waffle/startMenu/SearchPageContent.qml | 16 +++ .../waffle/startMenu/StartMenuContent.qml | 39 ++++++ .../waffle/startMenu/StartPageContent.qml | 98 +++++++++++++++ .../waffle/startMenu/WaffleStartMenu.qml | 119 ++++++++++++++++++ dots/.config/quickshell/ii/shell.qml | 5 +- 26 files changed, 464 insertions(+), 61 deletions(-) create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/power-filled.svg create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/power.svg rename dots/.config/quickshell/ii/modules/waffle/{bar/AppIcon.qml => looks/WAppIcon.qml} (94%) create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WTextInput.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/startMenu/StartPageContent.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/startMenu/WaffleStartMenu.qml 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: \"Testing" -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: \"Testing" -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/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/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml index 5ec96eeb4..a92a85578 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml @@ -14,8 +14,9 @@ AppButton { 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/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index a321fa98e..609c9877b 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -54,6 +54,7 @@ Singleton { property color controlFg: "#FFFFFF" property color accentUnfocused: "#848484" property color link: "#235CCF" + property color inputBg: ColorUtils.transparentize(bg0, 0.4) } darkColors: QtObject { id: darkColors @@ -71,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" @@ -82,6 +83,7 @@ Singleton { 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 @@ -112,6 +114,7 @@ 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" @@ -121,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/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 47ad2f92d..f49477988 100644 --- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml @@ -68,9 +68,8 @@ WBarAttachedPanelContent { WPane { id: calendarPane - contentItem: ColumnLayout { + contentItem: WPanelPageColumn { id: calendarColumnLayout - spacing: 0 DateHeader { Layout.fillWidth: true Synchronizer on collapsed { diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml index 856ddb160..895ab6892 100644 --- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml +++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml @@ -13,7 +13,7 @@ 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 @@ -58,13 +58,19 @@ MouseArea { Loader { id: imageLoader + anchors { + top: parent.top + left: parent.left + } active: root.notification.image != "" sourceComponent: StyledImage { - width: 48 - height: 48 - sourceSize.width: width - sourceSize.height: height + readonly property int size: 48 + width: size + height: size + sourceSize.width: size + sourceSize.height: size source: root.notification.image + fillMode: Image.PreserveAspectFit } } 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)