From b214993c161b995cc214d320bd8dc5cf51ae1c43 Mon Sep 17 00:00:00 2001 From: eren <98850034+EisregenHaha@users.noreply.github.com> Date: Fri, 28 Nov 2025 12:51:19 +0100 Subject: [PATCH 1/7] Add Qalculate as Dependency for Fedora fixes math --- sdata/dist-fedora/feddeps.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdata/dist-fedora/feddeps.toml b/sdata/dist-fedora/feddeps.toml index f21169a1b..2a1bf2df5 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,4 @@ packages = [ "plasma-systemmonitor", "unzip" ] -install_opts = ["--setopt=install_weak_deps=False"] \ No newline at end of file +install_opts = ["--setopt=install_weak_deps=False"] From 04f73e67c8eee60ccf1fdf553e46c246c6948c01 Mon Sep 17 00:00:00 2001 From: clsty Date: Fri, 28 Nov 2025 21:07:39 +0800 Subject: [PATCH 2/7] Add qalc dep for dist-arch and deps-info (#2591) --- sdata/deps-info.md | 3 +++ sdata/dist-arch/illogical-impulse-widgets/PKGBUILD | 3 ++- sdata/dist-fedora/feddeps.toml | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) 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 2a1bf2df5..367626ced 100644 --- a/sdata/dist-fedora/feddeps.toml +++ b/sdata/dist-fedora/feddeps.toml @@ -193,3 +193,4 @@ packages = [ "unzip" ] install_opts = ["--setopt=install_weak_deps=False"] + From b4038dafa900509e4784eb0980aa7e78878d06f4 Mon Sep 17 00:00:00 2001 From: clsty Date: Fri, 28 Nov 2025 22:42:47 +0800 Subject: [PATCH 3/7] Update dist-nix - Not use NixGL but let home-manager automatically handle it (since hm 25.11) - Add libqalculate --- sdata/dist-nix/README.md | 34 ++++++++++++++++++++-- sdata/dist-nix/home-manager/flake.nix | 19 +++++++----- sdata/dist-nix/home-manager/home.nix | 19 ++++++++---- sdata/dist-nix/home-manager/quickshell.nix | 10 +++++-- sdata/dist-nix/install-deps.sh | 5 ++-- 5 files changed, 67 insertions(+), 20 deletions(-) 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}" } From 6b90e37b0f16678bd90858e3339b03161996849a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 29 Nov 2025 00:23:19 +0100 Subject: [PATCH 4/7] waffles: expandable notifs --- .../ii/modules/waffle/bar/BarButton.qml | 29 +---- .../ii/modules/waffle/looks/AcrylicButton.qml | 42 +++++++ .../modules/waffle/looks/AcrylicRectangle.qml | 9 +- .../ii/modules/waffle/looks/Looks.qml | 3 + .../ii/modules/waffle/looks/WText.qml | 3 + .../NotificationHeaderButton.qml | 18 ++- .../SmallBorderedIconAndTextButton.qml | 11 +- .../notificationCenter/WNotificationGroup.qml | 14 ++- .../WSingleNotification.qml | 106 ++++++++++++++++-- 9 files changed, 185 insertions(+), 50 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/AcrylicButton.qml 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/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..a321fa98e 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -53,6 +53,7 @@ Singleton { property color controlBgHover: '#57575B' property color controlFg: "#FFFFFF" property color accentUnfocused: "#848484" + property color link: "#235CCF" } darkColors: QtObject { id: darkColors @@ -80,6 +81,7 @@ Singleton { property color controlBgHover: "#CFCED1" property color controlFg: "#454545" property color accentUnfocused: "#989898" + property color link: "#A7C9FC" } colors: QtObject { id: colors @@ -110,6 +112,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 link: root.dark ? root.darkColors.link : root.lightColors.link property color danger: "#C42B1C" property color dangerActive: "#B62D1F" property color warning: "#FF9900" 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/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..21ef2c544 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 === 0) 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..95780133c 100644 --- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml +++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml @@ -13,10 +13,17 @@ MouseArea { required property var notification property bool expanded: false + 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,32 +33,109 @@ 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 { Layout.fillWidth: true - WText { - text: NotificationUtils.getFriendlyNotifTimeString(root.notification?.time) + + 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); + }); + } } } ColumnLayout { Layout.fillWidth: true - WText { - Layout.fillWidth: true - elide: Text.ElideRight - text: root.notification.summary + spacing: 3 + + SummaryText {} + BodyText {} + } + + AcrylicButton { + id: groupExpandButton + visible: root.groupExpandControlMessage !== "" + Layout.bottomMargin: 2 + horizontalPadding: 10 + implicitHeight: 24 + implicitWidth: expandButtonText.implicitWidth + horizontalPadding * 2 + onClicked: root.groupExpandToggle() + contentItem: Item { + WText { + id: expandButtonText + anchors.centerIn: parent + text: root.groupExpandControlMessage + } } + } + } + } + + 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: root.notification?.body + color: Looks.colors.subfg + } + + 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 { - Layout.fillWidth: true - elide: Text.ElideRight - wrapMode: Text.Wrap - maximumLineCount: root.expanded ? 100 : 1 + 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) + } } } } From d2c019f8de66e1cbd268878e626c4d1f3a237241 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 29 Nov 2025 00:37:15 +0100 Subject: [PATCH 5/7] fix "+0 notifications" --- .../ii/modules/waffle/notificationCenter/WNotificationGroup.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WNotificationGroup.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WNotificationGroup.qml index 21ef2c544..122469771 100644 --- a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WNotificationGroup.qml +++ b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WNotificationGroup.qml @@ -44,7 +44,7 @@ MouseArea { width: ListView.view.width notification: modelData groupExpandControlMessage: { - if (root.notifications.length === 0) return ""; + 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 ""; From 677fa06b06934174109e00206b2661ed2d686468 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 29 Nov 2025 12:51:31 +0100 Subject: [PATCH 6/7] waffles: notifications: image support --- .../common/functions/NotificationUtils.qml | 24 +++ .../common/widgets/NotificationItem.qml | 31 +--- .../ii/modules/waffle/bar/StartButton.qml | 1 + .../NotificationCenterContent.qml | 19 ++- .../WSingleNotification.qml | 157 ++++++++++++++---- 5 files changed, 172 insertions(+), 60 deletions(-) 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/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml index f4a15cc00..5ec96eeb4 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml @@ -7,6 +7,7 @@ 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 diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/NotificationCenterContent.qml index 797cee28a..47ad2f92d 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,6 +67,7 @@ WBarAttachedPanelContent { } WPane { + id: calendarPane contentItem: ColumnLayout { id: calendarColumnLayout spacing: 0 diff --git a/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml b/dots/.config/quickshell/ii/modules/waffle/notificationCenter/WSingleNotification.qml index 95780133c..856ddb160 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 @@ -41,52 +42,115 @@ MouseArea { anchors.margins: contentItem.padding spacing: 19 - RowLayout { + // Header + SingleNotificationHeader { Layout.fillWidth: true + } - ExpandButton { - Layout.topMargin: -2 + // 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 + active: root.notification.image != "" + sourceComponent: StyledImage { + width: 48 + height: 48 + sourceSize.width: width + sourceSize.height: height + source: root.notification.image + } } - Item { - Layout.fillWidth: true - } + ColumnLayout { + id: contentColumn + anchors { + top: parent.top + left: parent.left + right: parent.right + } + spacing: 3 - NotificationHeaderButton { - Layout.rightMargin: 4 - opacity: root.containsMouse ? 1 : 0 - icon.name: "dismiss" - implicitSize: 12 - onClicked: { - Qt.callLater(() => { - Notifications.discardNotification(root.notification?.notificationId); - }); + 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 - spacing: 3 - - SummaryText {} - BodyText {} } - AcrylicButton { - id: groupExpandButton - visible: root.groupExpandControlMessage !== "" + // "+1 notifications" button + GroupExpandButton { Layout.bottomMargin: 2 - horizontalPadding: 10 - implicitHeight: 24 - implicitWidth: expandButtonText.implicitWidth + horizontalPadding * 2 - onClicked: root.groupExpandToggle() - contentItem: Item { - WText { - id: expandButtonText - anchors.centerIn: parent - text: root.groupExpandControlMessage - } + } + } + } + + 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 } } } @@ -106,8 +170,17 @@ MouseArea { verticalAlignment: Text.AlignTop wrapMode: Text.Wrap maximumLineCount: root.expanded ? 100 : 1 - text: root.notification?.body + 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 { @@ -140,4 +213,20 @@ MouseArea { } } } + + 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 + } + } + } } 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 7/7] 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)