From 8a9f105e75d4c080ccaf4202c99d9cb6ea55812e Mon Sep 17 00:00:00 2001 From: Perdixky <3293789706@qq.com> Date: Wed, 3 Dec 2025 10:17:42 +0800 Subject: [PATCH 1/9] Eliminate repeated sudo password prompts during installation --- sdata/lib/functions.sh | 50 ++++++++++++++++++++++++++++++++++++++++++ setup | 10 +++++++++ 2 files changed, 60 insertions(+) diff --git a/sdata/lib/functions.sh b/sdata/lib/functions.sh index b6dcae99d..ecaf1fcc1 100644 --- a/sdata/lib/functions.sh +++ b/sdata/lib/functions.sh @@ -80,6 +80,56 @@ function prevent_sudo_or_root(){ root) echo -e "${STY_RED}[$0]: This script is NOT to be executed with sudo or as root. Aborting...${STY_RST}";exit 1;; esac } + +# Initialize sudo session and keep it alive in background +# Store PID in a global variable that can be accessed by trap +declare -g SUDO_KEEPALIVE_PID="" + +function sudo_init_keepalive(){ + # Check if sudo is available + if ! command -v sudo >/dev/null 2>&1; then + return 0 + fi + + # Only initialize for install-related commands that need sudo + case "${SUBCMD_NAME}" in + install|install-deps|install-setups) ;; + *) return 0 ;; + esac + + # Skip if already initialized + if [[ -n "$SUDO_KEEPALIVE_PID" ]] && kill -0 "$SUDO_KEEPALIVE_PID" 2>/dev/null; then + return 0 + fi + + # Prompt for sudo password once at the beginning + echo -e "${STY_CYAN}[$0]: Requesting sudo privileges for installation...${STY_RST}" + if ! sudo -v; then + echo -e "${STY_RED}[$0]: Failed to obtain sudo privileges. Aborting...${STY_RST}" + exit 1 + fi + + # Start background process to keep sudo session alive + # This updates the sudo timestamp every 60 seconds + ( + while true; do + sleep 60 + sudo -v 2>/dev/null || exit 0 + done + ) & + SUDO_KEEPALIVE_PID=$! + + echo -e "${STY_GREEN}[$0]: Sudo session initialized and will be kept alive (PID: $SUDO_KEEPALIVE_PID)${STY_RST}" +} + +# Stop the sudo keepalive background process +function sudo_stop_keepalive(){ + if [[ -n "$SUDO_KEEPALIVE_PID" ]] && kill -0 "$SUDO_KEEPALIVE_PID" 2>/dev/null; then + kill "$SUDO_KEEPALIVE_PID" 2>/dev/null + wait "$SUDO_KEEPALIVE_PID" 2>/dev/null + SUDO_KEEPALIVE_PID="" + fi +} function git_auto_unshallow(){ # We need this function for latest_commit_hash to work properly if [[ -f "$(git rev-parse --git-dir)/shallow" ]]; then diff --git a/setup b/setup index 8a6e2d82f..226a1ba85 100755 --- a/setup +++ b/setup @@ -8,6 +8,10 @@ source ./sdata/lib/package-installers.sh source ./sdata/lib/dist-determine.sh prevent_sudo_or_root + +# Trap to ensure sudo keepalive is stopped on exit +trap sudo_stop_keepalive EXIT INT TERM + set -e ##################################################################################### @@ -71,6 +75,8 @@ case ${SUBCMD_NAME} in $function done pause + # Initialize sudo keepalive for the entire install process + sudo_init_keepalive if [[ "${SKIP_ALLGREETING}" != true ]]; then source ${SUBCMD_DIR}/0.greeting.sh fi @@ -89,6 +95,8 @@ case ${SUBCMD_NAME} in $function done pause + # Initialize sudo keepalive for dependency installation + sudo_init_keepalive if [[ "${SKIP_ALLDEPS}" != true ]]; then source ${SUBCMD_DIR}/1.deps-router.sh fi @@ -98,6 +106,8 @@ case ${SUBCMD_NAME} in $function done pause + # Initialize sudo keepalive for setup steps + sudo_init_keepalive if [[ "${SKIP_ALLSETUPS}" != true ]]; then source ${SUBCMD_DIR}/2.setups.sh fi From d3c1ae14b859d345d0446a7a240b72075dbca518 Mon Sep 17 00:00:00 2001 From: Perdixky <3293789706@qq.com> Date: Wed, 3 Dec 2025 20:58:45 +0800 Subject: [PATCH 2/9] Move trap to each needed subcommand --- setup | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/setup b/setup index 226a1ba85..9174eeb93 100755 --- a/setup +++ b/setup @@ -8,10 +8,6 @@ source ./sdata/lib/package-installers.sh source ./sdata/lib/dist-determine.sh prevent_sudo_or_root - -# Trap to ensure sudo keepalive is stopped on exit -trap sudo_stop_keepalive EXIT INT TERM - set -e ##################################################################################### @@ -77,6 +73,8 @@ case ${SUBCMD_NAME} in pause # Initialize sudo keepalive for the entire install process sudo_init_keepalive + # Set trap to cleanup when this subcommand exits + trap sudo_stop_keepalive EXIT INT TERM if [[ "${SKIP_ALLGREETING}" != true ]]; then source ${SUBCMD_DIR}/0.greeting.sh fi @@ -97,6 +95,8 @@ case ${SUBCMD_NAME} in pause # Initialize sudo keepalive for dependency installation sudo_init_keepalive + # Set trap to cleanup when this subcommand exits + trap sudo_stop_keepalive EXIT INT TERM if [[ "${SKIP_ALLDEPS}" != true ]]; then source ${SUBCMD_DIR}/1.deps-router.sh fi @@ -108,6 +108,8 @@ case ${SUBCMD_NAME} in pause # Initialize sudo keepalive for setup steps sudo_init_keepalive + # Set trap to cleanup when this subcommand exits + trap sudo_stop_keepalive EXIT INT TERM if [[ "${SKIP_ALLSETUPS}" != true ]]; then source ${SUBCMD_DIR}/2.setups.sh fi From ed9e510c32fd7f0f656878350ffed7fc0b41d349 Mon Sep 17 00:00:00 2001 From: "Celestial.y" Date: Wed, 3 Dec 2025 21:35:36 +0800 Subject: [PATCH 3/9] Remove determine subcommand install* --- sdata/lib/functions.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sdata/lib/functions.sh b/sdata/lib/functions.sh index ecaf1fcc1..0fe24f0ed 100644 --- a/sdata/lib/functions.sh +++ b/sdata/lib/functions.sh @@ -91,12 +91,6 @@ function sudo_init_keepalive(){ return 0 fi - # Only initialize for install-related commands that need sudo - case "${SUBCMD_NAME}" in - install|install-deps|install-setups) ;; - *) return 0 ;; - esac - # Skip if already initialized if [[ -n "$SUDO_KEEPALIVE_PID" ]] && kill -0 "$SUDO_KEEPALIVE_PID" 2>/dev/null; then return 0 From 20d60a11f7ad1f803a05903e1b4cff12fa71d2ca Mon Sep 17 00:00:00 2001 From: tmcnulty387 Date: Wed, 3 Dec 2025 13:23:41 -0500 Subject: [PATCH 4/9] Set PACMAN_AUTH to prevent repeated sudo password prompts --- sdata/dist-arch/install-deps.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdata/dist-arch/install-deps.sh b/sdata/dist-arch/install-deps.sh index 3cd43d6ba..ecbb3b907 100644 --- a/sdata/dist-arch/install-deps.sh +++ b/sdata/dist-arch/install-deps.sh @@ -43,6 +43,11 @@ if ! command -v pacman >/dev/null 2>&1; then exit 1 fi +# Keep makepkg from resetting sudo credentials +if [[ -z "${PACMAN_AUTH:-}" ]]; then + export PACMAN_AUTH="sudo" +fi + showfun remove_deprecated_dependencies v remove_deprecated_dependencies From 05aae36e82c0f0f1b581abc1da39429fec3edcdd Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 3 Dec 2025 22:05:55 +0100 Subject: [PATCH 5/9] overviewwidget: fix undefined warning --- .../quickshell/ii/modules/ii/overview/OverviewWidget.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overview/OverviewWidget.qml b/dots/.config/quickshell/ii/modules/ii/overview/OverviewWidget.qml index 18501b082..f0e40d56e 100644 --- a/dots/.config/quickshell/ii/modules/ii/overview/OverviewWidget.qml +++ b/dots/.config/quickshell/ii/modules/ii/overview/OverviewWidget.qml @@ -278,7 +278,7 @@ Item { StyledToolTip { extraVisibleCondition: false alternativeVisibleCondition: dragArea.containsMouse && !window.Drag.active - text: `${windowData.title}\n[${windowData.class}] ${windowData.xwayland ? "[XWayland] " : ""}` + text: `${windowData?.title}\n[${windowData?.class}] ${windowData?.xwayland ? "[XWayland] " : ""}` } } } From 4055ad48fa776608521cf52dddaf78e5feb8e3e8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 3 Dec 2025 22:07:06 +0100 Subject: [PATCH 6/9] launcher search service: use proper type instead of json clumps --- .../quickshell/ii/modules/common/Config.qml | 3 +- .../common/models/LauncherSearchResult.qml | 29 ++++ .../ii/modules/ii/overview/SearchItem.qml | 55 ++++--- .../ii/modules/ii/overview/SearchWidget.qml | 6 - .../quickshell/ii/services/LauncherSearch.qml | 150 +++++++++++------- 5 files changed, 161 insertions(+), 82 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/common/models/LauncherSearchResult.qml diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index d26f04d65..b0b767a44 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -590,8 +590,9 @@ Singleton { // false will make (some) stuff also be like that for accuracy. // Example: the right-click menu of the Start button property JsonObject tweaks: JsonObject { - property bool smootherMenuAnimations: true property bool switchHandlePositionFix: true + property bool smootherMenuAnimations: true + property bool smootherSearchBar: true } property JsonObject bar: JsonObject { property bool bottom: true diff --git a/dots/.config/quickshell/ii/modules/common/models/LauncherSearchResult.qml b/dots/.config/quickshell/ii/modules/common/models/LauncherSearchResult.qml new file mode 100644 index 000000000..15beef12e --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/LauncherSearchResult.qml @@ -0,0 +1,29 @@ +import QtQuick +import Quickshell + +QtObject { + enum IconType { Material, Text, System, None } + enum FontType { Normal, Monospace } + + // General stuff + property string type: "" + property var fontType: LauncherSearchResult.FontType.Normal + property string name: "" + property string rawValue: "" + property string iconName: "" + property var iconType: LauncherSearchResult.IconType.None + property string verb: "" + property bool blurImage: false + property var execute: () => { + print("Not implemented"); + } + property var actions: [] + + // Stuff needed for DesktopEntry objects + property bool shown: true + property string comment: "" + property bool runInTerminal: false + property string genericName: "" + property list keywords: [] + +} diff --git a/dots/.config/quickshell/ii/modules/ii/overview/SearchItem.qml b/dots/.config/quickshell/ii/modules/ii/overview/SearchItem.qml index 8f72db56a..a0f9b248d 100644 --- a/dots/.config/quickshell/ii/modules/ii/overview/SearchItem.qml +++ b/dots/.config/quickshell/ii/modules/ii/overview/SearchItem.qml @@ -2,6 +2,7 @@ import qs import qs.services import qs.modules.common +import qs.modules.common.models import qs.modules.common.widgets import qs.modules.common.functions import QtQuick @@ -12,20 +13,27 @@ import Quickshell.Hyprland RippleButton { id: root - property var entry + property LauncherSearchResult entry property string query property bool entryShown: entry?.shown ?? true property string itemType: entry?.type ?? Translation.tr("App") property string itemName: entry?.name ?? "" - property string itemIcon: entry?.icon ?? "" + property var iconType: entry?.iconType + property string iconName: entry?.iconName ?? "" property var itemExecute: entry?.execute - property string fontType: entry?.fontType ?? "main" - property string itemClickActionName: entry?.clickActionName ?? "Open" - property string bigText: entry?.bigText ?? "" - property string materialSymbol: entry?.materialSymbol ?? "" - property string cliphistRawString: entry?.cliphistRawString ?? "" + property var fontType: switch(entry?.fontType) { + case LauncherSearchResult.FontType.Monospace: + return "monospace" + case LauncherSearchResult.FontType.Normal: + return "main" + default: + return "main" + } + property string itemClickActionName: entry?.verb ?? "Open" + property string bigText: entry?.iconType === LauncherSearchResult.IconType.Text ? entry?.iconName ?? "" : "" + property string materialSymbol: entry.iconType === LauncherSearchResult.IconType.Material ? entry?.iconName ?? "" : "" + property string cliphistRawString: entry?.rawValue ?? "" property bool blurImage: entry?.blurImage ?? false - property string blurImageText: entry?.blurImageText ?? "Image hidden" visible: root.entryShown property int horizontalMargin: 10 @@ -97,7 +105,7 @@ RippleButton { } Keys.onPressed: (event) => { if (event.key === Qt.Key_Delete && event.modifiers === Qt.ShiftModifier) { - const deleteAction = root.entry.actions.find(action => action.name == "Delete"); + const deleteAction = root.entry.actions.find(action => action.name == Translation.tr("Delete")); if (deleteAction) { deleteAction.execute() @@ -126,16 +134,24 @@ RippleButton { Loader { id: iconLoader active: true - sourceComponent: root.materialSymbol !== "" ? materialSymbolComponent : - root.bigText ? bigTextComponent : - root.itemIcon !== "" ? iconImageComponent : - null + sourceComponent: switch(root.iconType) { + case LauncherSearchResult.IconType.Material: + return materialSymbolComponent + case LauncherSearchResult.IconType.Text: + return bigTextComponent + case LauncherSearchResult.IconType.System: + return iconImageComponent + case LauncherSearchResult.IconType.None: + return null + default: + return null + } } Component { id: iconImageComponent IconImage { - source: Quickshell.iconPath(root.itemIcon, "image-missing") + source: Quickshell.iconPath(root.iconName, "image-missing") width: 35 height: 35 } @@ -217,7 +233,6 @@ RippleButton { maxWidth: contentColumn.width maxHeight: 140 blur: root.blurImage - blurText: root.blurImageText } } } @@ -243,8 +258,8 @@ RippleButton { delegate: RippleButton { id: actionButton required property var modelData - property string iconName: modelData.icon ?? "" - property string materialIconName: modelData.materialIcon ?? "" + property var iconType: modelData.iconType + property string iconName: modelData.iconName ?? "" implicitHeight: 34 implicitWidth: 34 @@ -256,16 +271,16 @@ RippleButton { anchors.centerIn: parent Loader { anchors.centerIn: parent - active: !(actionButton.iconName !== "") || actionButton.materialIconName + active: actionButton.iconType === LauncherSearchResult.IconType.Material || actionButton.iconName === "" sourceComponent: MaterialSymbol { - text: actionButton.materialIconName || "video_settings" + text: actionButton.iconName || "video_settings" font.pixelSize: Appearance.font.pixelSize.hugeass color: Appearance.m3colors.m3onSurface } } Loader { anchors.centerIn: parent - active: actionButton.materialIconName.length == 0 && actionButton.iconName && actionButton.iconName !== "" + active: actionButton.iconType === LauncherSearchResult.IconType.System && actionButton.iconName !== "" sourceComponent: IconImage { source: Quickshell.iconPath(actionButton.iconName) implicitSize: 20 diff --git a/dots/.config/quickshell/ii/modules/ii/overview/SearchWidget.qml b/dots/.config/quickshell/ii/modules/ii/overview/SearchWidget.qml index c0ca28d62..6b982c4d2 100644 --- a/dots/.config/quickshell/ii/modules/ii/overview/SearchWidget.qml +++ b/dots/.config/quickshell/ii/modules/ii/overview/SearchWidget.qml @@ -42,12 +42,6 @@ Item { // Wrapper LauncherSearch.query = text; } - function containsUnsafeLink(entry) { - if (entry == undefined) return false; - const unsafeKeywords = Config.options.workSafety.triggerCondition.linkKeywords; - return StringUtils.stringListContainsSubstring(entry.toLowerCase(), unsafeKeywords); - } - Keys.onPressed: event => { // Prevent Esc and Backspace from registering if (event.key === Qt.Key_Escape) diff --git a/dots/.config/quickshell/ii/services/LauncherSearch.qml b/dots/.config/quickshell/ii/services/LauncherSearch.qml index bf23c1c48..89d9e0056 100644 --- a/dots/.config/quickshell/ii/services/LauncherSearch.qml +++ b/dots/.config/quickshell/ii/services/LauncherSearch.qml @@ -4,7 +4,6 @@ import qs.modules.common import qs.modules.common.models import qs.modules.common.functions import QtQuick -import QtQuick.Controls import Quickshell import Quickshell.Io @@ -12,6 +11,15 @@ Singleton { id: root property string query: "" + + function ensurePrefix(prefix) { + if ([Config.options.search.prefix.action, Config.options.search.prefix.app, Config.options.search.prefix.clipboard, Config.options.search.prefix.emojis, Config.options.search.prefix.math, Config.options.search.prefix.shellCommand, Config.options.search.prefix.webSearch,].some(i => root.query.startsWith(i))) { + root.query = prefix + root.query.slice(1); + } else { + root.query = prefix + root.query; + } + } + property var searchActions: [ { action: "accentcolor", @@ -74,12 +82,13 @@ Singleton { property string mathResult: "" property bool clipboardWorkSafetyActive: { const enabled = Config.options.workSafety.enable.clipboard; - const sensitiveNetwork = (StringUtils.stringListContainsSubstring(Network.networkName.toLowerCase(), Config.options.workSafety.triggerCondition.networkNameKeywords)) + const sensitiveNetwork = (StringUtils.stringListContainsSubstring(Network.networkName.toLowerCase(), Config.options.workSafety.triggerCondition.networkNameKeywords)); return enabled && sensitiveNetwork; } function containsUnsafeLink(entry) { - if (entry == undefined) return false; + if (entry == undefined) + return false; const unsafeKeywords = Config.options.workSafety.triggerCondition.linkKeywords; return StringUtils.stringListContainsSubstring(entry.toLowerCase(), unsafeKeywords); } @@ -128,95 +137,121 @@ Singleton { shouldBlurImage = shouldBlurImage && (root.containsUnsafeLink(array[index - 1]) || root.containsUnsafeLink(array[index + 1])); } const type = `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`; - return { - key: type, - cliphistRawString: entry, + return resultComp.createObject(null, { + rawValue: entry, name: StringUtils.cleanCliphistEntry(entry), - clickActionName: "", + verb: "", type: type, execute: () => { Cliphist.copy(entry); }, - actions: [ - { - name: "Copy", - materialIcon: "content_copy", + actions: [resultComp.createObject(null, { + name: Translation.tr("Copy"), + iconName: "content_copy", + iconType: LauncherSearchResult.IconType.Material, execute: () => { Cliphist.copy(entry); } - }, - { - name: "Delete", - materialIcon: "delete", + }), resultComp.createObject(null, { + name: Translation.tr("Delete"), + iconName: "delete", + iconType: LauncherSearchResult.IconType.Material, execute: () => { Cliphist.deleteEntry(entry); } - } - ], - blurImage: shouldBlurImage, - blurImageText: Translation.tr("Work safety") - }; + })], + blurImage: shouldBlurImage + }); }).filter(Boolean); } else if (root.query.startsWith(Config.options.search.prefix.emojis)) { // Clipboard const searchString = StringUtils.cleanPrefix(root.query, Config.options.search.prefix.emojis); return Emojis.fuzzyQuery(searchString).map(entry => { const emoji = entry.match(/^\s*(\S+)/)?.[1] || ""; - return { - key: emoji, - cliphistRawString: entry, - bigText: emoji, + return resultComp.createObject(null, { + rawValue: entry, name: entry.replace(/^\s*\S+\s+/, ""), - clickActionName: "", - type: "Emoji", + iconName: emoji, + iconType: LauncherSearchResult.IconType.Text, + verb: Translation.tr("Copy"), + type: Translation.tr("Emoji"), execute: () => { Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1]; } - }; + }); }).filter(Boolean); } ////////////////// Init /////////////////// nonAppResultsTimer.restart(); - const mathResultObject = { - key: `Math result: ${root.mathResult}`, + const mathResultObject = resultComp.createObject(null, { name: root.mathResult, - clickActionName: Translation.tr("Copy"), + verb: Translation.tr("Copy"), type: Translation.tr("Math result"), - fontType: "monospace", - materialSymbol: 'calculate', + fontType: LauncherSearchResult.FontType.Monospace, + iconName: 'calculate', + iconType: LauncherSearchResult.IconType.Material, execute: () => { Quickshell.clipboardText = root.mathResult; } - }; - const appResultObjects = AppSearch.fuzzyQuery(StringUtils.cleanPrefix(root.query, Config.options.search.prefix.app)).map(entry => { - entry.clickActionName = Translation.tr("Launch"); - entry.type = Translation.tr("App"); - entry.key = entry.execute; - return entry; }); - const commandResultObject = { - key: `cmd ${root.query}`, + const appResultObjects = AppSearch.fuzzyQuery(StringUtils.cleanPrefix(root.query, Config.options.search.prefix.app)).map(entry => { + return resultComp.createObject(null, { + type: Translation.tr("App"), + name: entry.name, + iconName: entry.icon, + iconType: LauncherSearchResult.IconType.System, + verb: Translation.tr("Launch"), + execute: () => { + if (!entry.runInTerminal) + entry.execute(); + else { + // Probably needs more proper escaping, but this will do for now + Quickshell.execDetached(["bash", '-c', `${Config.options.apps.terminal} -e '${StringUtils.shellSingleQuoteEscape(entry.command.join(' '))}'`]); + } + }, + comment: entry.comment, + runInTerminal: entry.runInTerminal, + genericName: entry.genericName, + keywords: entry.keywords, + actions: entry.actions.map(action => { + return resultComp.createObject(null, { + name: action.name, + iconName: action.icon, + iconType: LauncherSearchResult.IconType.System, + execute: () => { + if (!action.runInTerminal) + action.execute(); + else { + Quickshell.execDetached(["bash", '-c', `${Config.options.apps.terminal} -e '${StringUtils.shellSingleQuoteEscape(action.command.join(' '))}'`]); + } + } + }); + }) + }); + }); + const commandResultObject = resultComp.createObject(null, { name: StringUtils.cleanPrefix(root.query, Config.options.search.prefix.shellCommand).replace("file://", ""), - clickActionName: Translation.tr("Run"), + verb: Translation.tr("Run"), type: Translation.tr("Run command"), - fontType: "monospace", - materialSymbol: 'terminal', + fontType: LauncherSearchResult.FontType.Monospace, + iconName: 'terminal', + iconType: LauncherSearchResult.IconType.Material, execute: () => { let cleanedCommand = root.query.replace("file://", ""); cleanedCommand = StringUtils.cleanPrefix(cleanedCommand, Config.options.search.prefix.shellCommand); if (cleanedCommand.startsWith(Config.options.search.prefix.shellCommand)) { cleanedCommand = cleanedCommand.slice(Config.options.search.prefix.shellCommand.length); } - Quickshell.execDetached(["bash", "-c", searchingText.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${cleanedCommand}'` : cleanedCommand]); + Quickshell.execDetached(["bash", "-c", root.query.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${cleanedCommand}'` : cleanedCommand]); } - }; - const webSearchResultObject = { - key: `website ${root.query}`, + }); + const webSearchResultObject = resultComp.createObject(null, { name: StringUtils.cleanPrefix(root.query, Config.options.search.prefix.webSearch), - clickActionName: Translation.tr("Search"), + verb: Translation.tr("Search"), type: Translation.tr("Search the web"), - materialSymbol: 'travel_explore', + iconName: 'travel_explore', + iconType: LauncherSearchResult.IconType.Material, execute: () => { let query = StringUtils.cleanPrefix(root.query, Config.options.search.prefix.webSearch); let url = Config.options.search.engineBaseUrl + query; @@ -225,20 +260,20 @@ Singleton { } Qt.openUrlExternally(url); } - }; + }); const launcherActionObjects = root.searchActions.map(action => { const actionString = `${Config.options.search.prefix.action}${action.action}`; if (actionString.startsWith(root.query) || root.query.startsWith(actionString)) { - return { - key: `Action ${actionString}`, + return resultComp.createObject(null, { name: root.query.startsWith(actionString) ? root.query : actionString, - clickActionName: Translation.tr("Run"), + verb: Translation.tr("Run"), type: Translation.tr("Action"), - materialSymbol: 'settings_suggest', + iconName: 'settings_suggest', + iconType: LauncherSearchResult.IconType.Material, execute: () => { action.execute(root.query.split(" ").slice(1).join(" ")); } - }; + }); } return null; }).filter(Boolean); @@ -275,4 +310,9 @@ Singleton { return result; } + + Component { + id: resultComp + LauncherSearchResult {} + } } From 71c1fbe1dd3a8c01308fd4f920756ce118e48c36 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:23:08 +0100 Subject: [PATCH 7/9] waffles: start: more search progress --- .../ii/modules/waffle/looks/Looks.qml | 3 +- .../ii/modules/waffle/looks/WChoiceButton.qml | 1 + .../ii/modules/waffle/looks/WMenu.qml | 83 ++++++++++------- .../modules/waffle/looks/WPanelIconButton.qml | 13 ++- .../ii/modules/waffle/looks/WTextInput.qml | 1 + .../ii/modules/waffle/startMenu/SearchBar.qml | 24 +++-- .../waffle/startMenu/SearchPageContent.qml | 22 ++++- .../waffle/startMenu/SearchResults.qml | 60 ++++++++++++ .../waffle/startMenu/StartMenuContent.qml | 31 +++++-- .../waffle/startMenu/StartPageContent.qml | 2 +- .../ii/modules/waffle/startMenu/TagStrip.qml | 92 +++++++++++++++++++ .../waffle/startMenu/WSearchResultButton.qml | 81 ++++++++++++++++ 12 files changed, 356 insertions(+), 57 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/waffle/startMenu/SearchResults.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/startMenu/TagStrip.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/startMenu/WSearchResultButton.qml diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index 609c9877b..b9cbc00bd 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -64,7 +64,7 @@ Singleton { property color bg0: "#1C1C1C" property color bg0Border: "#404040" property color bg1Base: "#2C2C2C" - property color bg1: "#a8a8a8" + property color bg1: '#9f9f9f' property color bg1Hover: "#b3b3b3" property color bg1Active: '#727272' property color bg1Border: '#bebebe' @@ -125,6 +125,7 @@ Singleton { 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 + property color selectionFg: Appearance.colors.colOnPrimaryContainer } radius: QtObject { diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WChoiceButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WChoiceButton.qml index eff776601..14691c716 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WChoiceButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WChoiceButton.qml @@ -44,6 +44,7 @@ WButton { radius: Looks.radius.medium color: root.color Behavior on color { + enabled: root.animateChoiceHighlight animation: Looks.transition.color.createObject(this) } diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WMenu.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WMenu.qml index a208f355b..a18c59ec9 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WMenu.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WMenu.qml @@ -14,17 +14,18 @@ Menu { property bool downDirection: false property bool hasIcons: false // TODO: implement - implicitWidth: background.implicitWidth + root.padding * 2 - implicitHeight: background.implicitHeight + root.padding * 2 + implicitWidth: background.implicitWidth + margins * 2 + implicitHeight: background.implicitHeight + margins * 2 + margins: 10 padding: 3 property real sourceEdgeMargin: -implicitHeight clip: true - + enter: Transition { NumberAnimation { property: "sourceEdgeMargin" from: -root.implicitHeight - to: root.padding + to: root.margins duration: 200 easing.type: Easing.BezierSpline easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn @@ -33,7 +34,7 @@ Menu { exit: Transition { NumberAnimation { property: "sourceEdgeMargin" - from: root.padding + from: root.margins to: -root.implicitHeight duration: 150 easing.type: Easing.BezierSpline @@ -41,43 +42,55 @@ Menu { } } - background: WPane { - anchors { - left: parent.left - right: parent.right - top: root.downDirection ? parent.top : undefined - bottom: root.downDirection ? undefined : parent.bottom - margins: root.padding - topMargin: root.downDirection ? root.sourceEdgeMargin : root.padding - bottomMargin: root.downDirection ? root.padding : root.sourceEdgeMargin - } - contentItem: Rectangle { - color: Looks.colors.bg1Base - implicitWidth: menuListView.implicitWidth + root.padding * 2 - implicitHeight: root.contentItem.implicitHeight + root.padding * 2 + background: Item { + id: bgItem + implicitWidth: bgPane.implicitWidth + implicitHeight: bgPane.implicitHeight + WPane { + id: bgPane + anchors { + left: parent.left + right: parent.right + top: root.downDirection ? parent.top : undefined + bottom: root.downDirection ? undefined : parent.bottom + margins: root.margins + topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins + bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin + } + contentItem: Rectangle { + color: Looks.colors.bg1Base + implicitWidth: menuListView.implicitWidth + root.padding * 2 + implicitHeight: root.contentItem.implicitHeight + root.padding * 2 + } + } } - contentItem: ListView { - id: menuListView - anchors { - left: parent.left - right: parent.right - top: root.downDirection ? parent.top : undefined - bottom: root.downDirection ? undefined : parent.bottom - margins: root.padding * 2 - topMargin: root.downDirection ? root.sourceEdgeMargin : root.padding - bottomMargin: root.downDirection ? root.padding : root.sourceEdgeMargin - } - implicitHeight: contentHeight - implicitWidth: Array.from({ - length: count - }, (_, i) => itemAtIndex(i)?.implicitWidth ?? 0).reduce((a, b) => a > b ? a : b) + contentItem: Item { + implicitWidth: menuListView.implicitWidth + implicitHeight: menuListView.implicitHeight + ListView { + id: menuListView + anchors { + left: parent.left + right: parent.right + top: root.downDirection ? parent.top : undefined + bottom: root.downDirection ? undefined : parent.bottom + margins: root.margins // ???? + topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins + bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin + } + implicitHeight: contentHeight + implicitWidth: Array.from({ + length: count + }, (_, i) => itemAtIndex(i)?.implicitWidth ?? 0).reduce((a, b) => a > b ? a : b) - model: root.contentModel + model: root.contentModel + } } delegate: WMenuItem { id: menuItemDelegate + width: ListView.view?.width } } diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPanelIconButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPanelIconButton.qml index e0e966022..3cdb3abfd 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WPanelIconButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPanelIconButton.qml @@ -10,14 +10,17 @@ WButton { id: root property alias iconName: iconContent.icon + property alias iconSize: iconContent.implicitSize property alias monochrome: iconContent.monochrome implicitWidth: 40 implicitHeight: 40 - contentItem: FluentIcon { - id: iconContent - anchors.centerIn: parent - implicitSize: 18 - icon: root.iconName + contentItem: Item { + FluentIcon { + id: iconContent + anchors.centerIn: parent + implicitSize: 18 + icon: root.iconName + } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WTextInput.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WTextInput.qml index a3f3e8a40..84bed180d 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WTextInput.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WTextInput.qml @@ -15,4 +15,5 @@ TextInput { } selectionColor: Looks.colors.selection + selectedTextColor: Looks.colors.selectionFg } diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml index 6bd23ae9b..ce5652329 100644 --- a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml +++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml @@ -12,26 +12,36 @@ import qs.modules.waffle.looks FooterRectangle { id: root + property real horizontalPadding: 32 + property real verticalPadding: 16 property bool searching: text.length > 0 property alias text: searchInput.text + implicitHeight: outline.implicitHeight + verticalPadding * 2 Component.onCompleted: searchInput.forceActiveFocus() focus: true color: searching ? Looks.colors.bgPanelBody : Looks.colors.bgPanelFooter - implicitWidth: 832 // TODO: Make sizes naturally inferred - implicitHeight: 63 + Behavior on horizontalPadding { + enabled: Config.options.waffles.tweaks.smootherSearchBar + animation: Looks.transition.move.createObject(this) + } + Behavior on verticalPadding { + enabled: Config.options.waffles.tweaks.smootherSearchBar + animation: Looks.transition.move.createObject(this) + } Rectangle { id: outline anchors { - fill: parent - leftMargin: 32 - rightMargin: 32 - topMargin: 16 - bottomMargin: 15 + left: parent.left + right: parent.right + leftMargin: root.horizontalPadding + rightMargin: root.horizontalPadding + verticalCenter: parent.verticalCenter } + implicitHeight: 32 color: "transparent" radius: height / 2 border.width: 1 diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml index cdbb7d3b8..a294950fd 100644 --- a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml @@ -12,5 +12,25 @@ import qs.modules.waffle.looks BodyRectangle { id: root - + property string searchText: LauncherSearch.query + + ColumnLayout { + anchors { + fill: parent + topMargin: 2 + leftMargin: 24 + rightMargin: 24 + } + spacing: 12 + + TagStrip { + Layout.fillWidth: true + Layout.fillHeight: false + } + + SearchResults { + Layout.fillWidth: true + Layout.fillHeight: true + } + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchResults.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchResults.qml new file mode 100644 index 000000000..5f3d93411 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchResults.qml @@ -0,0 +1,60 @@ +import qs.modules.waffle.looks +import qs.modules.common.functions +import qs.modules.common +import qs.services +import qs +import Quickshell +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick +pragma ComponentBehavior: Bound + +RowLayout { + id: root + + function focusFirstItem() { + resultList.currentIndex = 0; + } + + ResultList { + id: resultList + Layout.fillHeight: true + Layout.fillWidth: true + } + ResultPreview { + Layout.preferredWidth: 386 + Layout.leftMargin: 1 + Layout.rightMargin: 1 + } + + component ResultList: ListView { + section { + criteria: ViewSection.FullString + property: "type" + } + clip: true + spacing: 4 + model: ScriptModel { + values: { + // TODO: categorize and have max per category + LauncherSearch.results.slice(0, 10) + } + onValuesChanged: { + root.focusFirstItem(); + } + } + delegate: WSearchResultButton { + required property int index + required property var modelData + entry: modelData + firstEntry: index === 0 + width: ListView.view?.width + } + } + + component ResultPreview: Rectangle { + Layout.fillHeight: true + color: Looks.colors.bg1 + radius: Looks.radius.large + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml index 6e97f88be..09de017ee 100644 --- a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml @@ -14,26 +14,43 @@ WBarAttachedPanelContent { id: root property bool searching: false - property string searchText: "" + property string searchText: LauncherSearch.query contentItem: WPane { contentItem: WPanelPageColumn { SearchBar { focus: true Layout.fillWidth: true + implicitWidth: 832 // TODO: Make sizes naturally inferred + horizontalPadding: root.searching ? 24 : 32 + // verticalPadding: root.searching ? 32 : 16 // TODO: make this not nuke the panel Synchronizer on searching { property alias target: root.searching } - Synchronizer on text { - property alias source: root.searchText + text: root.searchText + onTextChanged: { + LauncherSearch.query = text; } } - Loader { - id: pageContentLoader + Item { + implicitHeight: root.searching ? 736 : 736 // TODO: Make sizes naturally inferred Layout.fillWidth: true - source: root.searching ? "SearchPageContent.qml" : "StartPageContent.qml" + Loader { + id: pageContentLoader + anchors.fill: parent + sourceComponent: root.searching ? searchPageComp : startPageComp + } } } } - + + Component { + id: searchPageComp + SearchPageContent {} + } + + Component { + id: startPageComp + StartPageContent {} + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartPageContent.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartPageContent.qml index eb3c96a80..f2f863cd2 100644 --- a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartPageContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartPageContent.qml @@ -17,7 +17,7 @@ WPanelPageColumn { WPanelSeparator {} BodyRectangle { - implicitHeight: 736 // TODO: Make sizes naturally inferred + Layout.fillHeight: true } WPanelSeparator {} diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/TagStrip.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/TagStrip.qml new file mode 100644 index 000000000..10448b5cd --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/TagStrip.qml @@ -0,0 +1,92 @@ +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 + +RowLayout { + WPanelIconButton { + implicitWidth: 36 + implicitHeight: 36 + iconSize: 24 + iconName: "arrow-left" + onClicked: LauncherSearch.query = "" + } + ListView { + id: tagListView + Layout.fillWidth: true + Layout.fillHeight: true + orientation: Qt.Horizontal + spacing: 4 + model: [ + { + name: Translation.tr("All"), + prefix: "" + }, + { + name: Translation.tr("Apps"), + prefix: Config.options.search.prefix.app + }, + { + name: Translation.tr("Actions"), + prefix: Config.options.search.prefix.action + }, + { + name: Translation.tr("Clipboard"), + prefix: Config.options.search.prefix.clipboard + }, + { + name: Translation.tr("Emojis"), + prefix: Config.options.search.prefix.emojis + }, + { + name: Translation.tr("Math"), + prefix: Config.options.search.prefix.math + }, + { + name: Translation.tr("Commands"), + prefix: Config.options.search.prefix.shellCommand + }, + { + name: Translation.tr("Web"), + prefix: Config.options.search.prefix.webSearch + }, + ] + delegate: WBorderedButton { + id: tagButton + required property var modelData + border.width: 1 + radius: height / 2 + implicitWidth: tagButtonText.implicitWidth + 12 * 2 + implicitHeight: 32 + checked: { + if (modelData.prefix != "") { + return LauncherSearch.query.startsWith(modelData.prefix); + } else { + return !tagListView.model.some(i => (i.prefix != "" && LauncherSearch.query.startsWith(i.prefix))) + } + } + contentItem: Item { + WText { + id: tagButtonText + anchors.centerIn: parent + color: tagButton.fgColor + text: tagButton.modelData.name + font.pixelSize: Looks.font.pixelSize.large + } + } + onClicked: LauncherSearch.ensurePrefix(tagButton.modelData.prefix) + } + } + WPanelIconButton { + implicitWidth: 36 + implicitHeight: 36 + iconSize: 24 + iconName: "more-horizontal" + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/WSearchResultButton.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/WSearchResultButton.qml new file mode 100644 index 000000000..1aca104b0 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/WSearchResultButton.qml @@ -0,0 +1,81 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.models +import qs.modules.common.functions +import qs.modules.common.widgets +import qs.modules.waffle.looks + +WChoiceButton { + id: root + + required property LauncherSearchResult entry + property bool firstEntry: false + + checked: focus + animateChoiceHighlight: false + implicitWidth: contentLayout.implicitWidth + leftPadding + rightPadding + implicitHeight: contentLayout.implicitHeight + topPadding + bottomPadding + + onClicked: { + GlobalStates.searchOpen = false + root.entry.execute() + } + + contentItem: RowLayout { + id: contentLayout + spacing: 8 + + EntryIcon {} + EntryNameColumn { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + } + + component EntryIcon: Item { + implicitWidth: 24 + implicitHeight: 24 + Loader { + anchors.centerIn: parent + active: root.entry.iconType === LauncherSearchResult.IconType.System + sourceComponent: WAppIcon { + implicitSize: 24 + tryCustomIcon: false + iconName: root.entry.iconName + } + } + Loader { + anchors.centerIn: parent + active: root.entry.iconType === LauncherSearchResult.IconType.Text + sourceComponent: WText { + text: root.entry.iconName + font.pixelSize: 24 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + } + + component EntryNameColumn: ColumnLayout { + spacing: 4 + + WText { + Layout.fillWidth: true + wrapMode: Text.Wrap + text: root.entry.name + font.pixelSize: Looks.font.pixelSize.large + maximumLineCount: 2 + } + + WText { + Layout.fillWidth: true + visible: root.firstEntry + text: root.entry.type + color: Looks.colors.accentUnfocused + } + } +} From 8203115a24eea64790500e231bb17f8d2e6af148 Mon Sep 17 00:00:00 2001 From: LIghtJUNction Date: Thu, 4 Dec 2025 15:17:24 +0800 Subject: [PATCH 8/9] Move the comments from the default configuration to the custom configuration and add more comments. (#2621) --- dots/.config/hypr/custom/env.conf | 12 ++++++++++++ dots/.config/hypr/custom/general.conf | 6 +++++- dots/.config/hypr/custom/keybinds.conf | 13 +++++++++++++ dots/.config/hypr/custom/rules.conf | 8 ++++++++ dots/.config/hypr/hyprland/env.conf | 6 ------ dots/.config/hypr/hyprland/general.conf | 4 ---- dots/.config/hypr/hyprland/rules.conf | 6 +----- 7 files changed, 39 insertions(+), 16 deletions(-) diff --git a/dots/.config/hypr/custom/env.conf b/dots/.config/hypr/custom/env.conf index 3215877be..4e59a32c2 100644 --- a/dots/.config/hypr/custom/env.conf +++ b/dots/.config/hypr/custom/env.conf @@ -8,3 +8,15 @@ #env = SDL_IM_MODULE, fcitx #env = GLFW_IM_MODULE, ibus #env = INPUT_METHOD, fcitx + +# ######## Wayland ######### +# Tearing +# env = WLR_DRM_NO_ATOMIC, 1 +# ? +# env = WLR_NO_HARDWARE_CURSORS, 1 + +# ######## EDITOR ######### +#https://wiki.archlinux.org/title/Category:Text_editors +# for example: vi nano nvim ... + +#env = EDITOR, vim diff --git a/dots/.config/hypr/custom/general.conf b/dots/.config/hypr/custom/general.conf index ded706ae7..aa3fd4f83 100644 --- a/dots/.config/hypr/custom/general.conf +++ b/dots/.config/hypr/custom/general.conf @@ -1,2 +1,6 @@ # Put general config stuff here -# Here's a list of every variable: https://wiki.hyprland.org/Configuring/Variables/ \ No newline at end of file +# Here's a list of every variable: https://wiki.hyprland.org/Configuring/Variables/ + +# monitor=,addreserved, 0, 0, 0, 0 # Custom reserved area + +# HDMI port: mirror display. To see device name, use `hyprctl monitors` diff --git a/dots/.config/hypr/custom/keybinds.conf b/dots/.config/hypr/custom/keybinds.conf index f2a568394..8885a2175 100644 --- a/dots/.config/hypr/custom/keybinds.conf +++ b/dots/.config/hypr/custom/keybinds.conf @@ -4,6 +4,19 @@ bind = Ctrl+Super, Slash, exec, xdg-open ~/.config/illogical-impulse/config.json # Edit shell config bind = Ctrl+Super+Alt, Slash, exec, xdg-open ~/.config/hypr/custom/keybinds.conf # Edit extra keybinds +##! Apps +# bind = Super, Return, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "${TERMINAL}" "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # Terminal +# bind = Super, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "${TERMINAL}" "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] (terminal) (alt) +# bind = Ctrl+Alt, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "${TERMINAL}" "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] (terminal) (for Ubuntu people) +# bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" "${TERMINAL}" "kitty -1 fish -c yazi" # File manager +# bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" "librewolf" # Browser +# bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "cursor" "zed" "zedit" "zeditor" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" "command -v micro && kitty -1 micro" # Code editor +# bind = Ctrl+Super+Shift+Alt, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" "libreoffice" # Office software +# bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor +# bind = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer +# bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome ~/.config/hypr/hyprland/scripts/launch_first_available.sh "qs -p ~/.config/quickshell/$qsConfig/settings.qml" "systemsettings" "gnome-control-center" "better-control" # Settings app +# bind = Ctrl+Shift, Escape, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "gnome-system-monitor" "plasma-systemmonitor --page-name Processes" "command -v btop && kitty -1 fish -c btop" # Task manager + # Add stuff here # Use #! to add an extra column on the cheatsheet # Use ##! to add a section in that column diff --git a/dots/.config/hypr/custom/rules.conf b/dots/.config/hypr/custom/rules.conf index 159de0915..b253bc8d1 100644 --- a/dots/.config/hypr/custom/rules.conf +++ b/dots/.config/hypr/custom/rules.conf @@ -1,3 +1,11 @@ # You can put custom rules here # Window/layer rules: https://wiki.hyprland.org/Configuring/Window-Rules/ # Workspace rules: https://wiki.hyprland.org/Configuring/Workspace-Rules/ + +# ######## Window rules ######## + +# Uncomment to apply global transparency to all windows: +# windowrulev2 = opacity 0.89 override 0.89 override, class:.* + +# Disable blur for all xwayland apps +# windowrulev2 = noblur, xwayland:1 \ No newline at end of file diff --git a/dots/.config/hypr/hyprland/env.conf b/dots/.config/hypr/hyprland/env.conf index acc363cc6..affd1ca82 100644 --- a/dots/.config/hypr/hyprland/env.conf +++ b/dots/.config/hypr/hyprland/env.conf @@ -9,12 +9,6 @@ env = QT_QPA_PLATFORM, wayland env = QT_QPA_PLATFORMTHEME, kde env = XDG_MENU_PREFIX, plasma- -# ######## Wayland ######### -# Tearing -# env = WLR_DRM_NO_ATOMIC, 1 -# ? -# env = WLR_NO_HARDWARE_CURSORS, 1 - # ######## Virtual envrionment ######### env = ILLOGICAL_IMPULSE_VIRTUAL_ENV, ~/.local/state/quickshell/.venv diff --git a/dots/.config/hypr/hyprland/general.conf b/dots/.config/hypr/hyprland/general.conf index c4c54bc28..77580552d 100644 --- a/dots/.config/hypr/hyprland/general.conf +++ b/dots/.config/hypr/hyprland/general.conf @@ -1,9 +1,5 @@ # MONITOR CONFIG monitor=,preferred,auto,1 -# monitor=,addreserved, 0, 0, 0, 0 # Custom reserved area - -# HDMI port: mirror display. To see device name, use `hyprctl monitors` -# monitor=HDMI-A-1,1920x1080@60,1920x0,1,mirror,eDP-1 gesture = 3, swipe, move, gesture = 3, pinch, float diff --git a/dots/.config/hypr/hyprland/rules.conf b/dots/.config/hypr/hyprland/rules.conf index cfb1e3f7b..a6e4d4e48 100644 --- a/dots/.config/hypr/hyprland/rules.conf +++ b/dots/.config/hypr/hyprland/rules.conf @@ -1,12 +1,8 @@ # ######## Window rules ######## -# Uncomment to apply global transparency to all windows: -# windowrulev2 = opacity 0.89 override 0.89 override, class:.* - # Disable blur for xwayland context menus windowrulev2 = noblur,class:^()$,title:^()$ -# Disable blur for all xwayland apps -# windowrulev2 = noblur, xwayland:1 + # Disable blur for every window windowrulev2 = noblur, class:.* From 7d9a405146b6ad6a80ba022b1cd840bb2ac6fde9 Mon Sep 17 00:00:00 2001 From: Madjid Taha <1833954+madjidtaha@users.noreply.github.com> Date: Thu, 4 Dec 2025 08:20:21 +0100 Subject: [PATCH 9/9] Fix CPU frequency detection for non-English locales (#2629) * fix: ensure lscpu is using en_US locale for LANG * fix: use environment in Process --- dots/.config/quickshell/ii/services/ResourceUsage.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dots/.config/quickshell/ii/services/ResourceUsage.qml b/dots/.config/quickshell/ii/services/ResourceUsage.qml index df823adf7..c513b90ca 100644 --- a/dots/.config/quickshell/ii/services/ResourceUsage.qml +++ b/dots/.config/quickshell/ii/services/ResourceUsage.qml @@ -102,6 +102,10 @@ Singleton { Process { id: findCpuMaxFreqProc + environment: ({ + LANG: "C", + LC_ALL: "C" + }) command: ["bash", "-c", "lscpu | grep 'CPU max MHz' | awk '{print $4}'"] running: true stdout: StdioCollector {