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:.*
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/app-generic-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/app-generic-filled.svg
new file mode 100644
index 000000000..87c7b6c41
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/app-generic-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/app-generic.svg b/dots/.config/quickshell/ii/assets/icons/fluent/app-generic.svg
new file mode 100644
index 000000000..cd0c7b516
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/app-generic.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/arrow-enter-left-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/arrow-enter-left-filled.svg
new file mode 100644
index 000000000..f183cc835
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/arrow-enter-left-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/arrow-enter-left.svg b/dots/.config/quickshell/ii/assets/icons/fluent/arrow-enter-left.svg
new file mode 100644
index 000000000..c9ffd3eda
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/arrow-enter-left.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/calculator-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/calculator-filled.svg
new file mode 100644
index 000000000..92ad06215
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/calculator-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/calculator.svg b/dots/.config/quickshell/ii/assets/icons/fluent/calculator.svg
new file mode 100644
index 000000000..0dc9d3056
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/calculator.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/desktop-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/desktop-filled.svg
new file mode 100644
index 000000000..d09661aec
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/desktop-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/desktop.svg b/dots/.config/quickshell/ii/assets/icons/fluent/desktop.svg
new file mode 100644
index 000000000..979d35cc3
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/desktop.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/globe-search-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/globe-search-filled.svg
new file mode 100644
index 000000000..933c6282d
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/globe-search-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/globe-search.svg b/dots/.config/quickshell/ii/assets/icons/fluent/globe-search.svg
new file mode 100644
index 000000000..caa2c94ff
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/globe-search.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/image-copy-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/image-copy-filled.svg
new file mode 100644
index 000000000..f01cd9872
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/image-copy-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/image-copy.svg b/dots/.config/quickshell/ii/assets/icons/fluent/image-copy.svg
new file mode 100644
index 000000000..a40940693
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/image-copy.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/image-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/image-filled.svg
new file mode 100644
index 000000000..d35954106
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/image-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/image.svg b/dots/.config/quickshell/ii/assets/icons/fluent/image.svg
new file mode 100644
index 000000000..379a1cd14
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/image.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/library-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/library-filled.svg
new file mode 100644
index 000000000..7afac3d5e
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/library-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/library.svg b/dots/.config/quickshell/ii/assets/icons/fluent/library.svg
new file mode 100644
index 000000000..79432ebdd
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/library.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/news-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/news-filled.svg
new file mode 100644
index 000000000..1d07cf802
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/news-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/news.svg b/dots/.config/quickshell/ii/assets/icons/fluent/news.svg
new file mode 100644
index 000000000..9e0c3a2fe
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/news.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/open-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/open-filled.svg
new file mode 100644
index 000000000..95ae58d39
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/open-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/open.svg b/dots/.config/quickshell/ii/assets/icons/fluent/open.svg
new file mode 100644
index 000000000..561ed5ec2
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/open.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/people-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/people-filled.svg
new file mode 100644
index 000000000..96e98b863
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/people-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/people-settings-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/people-settings-filled.svg
new file mode 100644
index 000000000..0bcd7d12d
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/people-settings-filled.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/people-settings.svg b/dots/.config/quickshell/ii/assets/icons/fluent/people-settings.svg
new file mode 100644
index 000000000..8ff1df32a
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/people-settings.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/people-team-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/people-team-filled.svg
new file mode 100644
index 000000000..84364ec4e
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/people-team-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/people-team.svg b/dots/.config/quickshell/ii/assets/icons/fluent/people-team.svg
new file mode 100644
index 000000000..8507e971c
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/people-team.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/people.svg b/dots/.config/quickshell/ii/assets/icons/fluent/people.svg
new file mode 100644
index 000000000..967192214
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/people.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/record-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/record-filled.svg
new file mode 100644
index 000000000..164d37e87
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/record-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/record.svg b/dots/.config/quickshell/ii/assets/icons/fluent/record.svg
new file mode 100644
index 000000000..31e957588
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/record.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/server-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/server-filled.svg
new file mode 100644
index 000000000..2b0869653
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/server-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/server.svg b/dots/.config/quickshell/ii/assets/icons/fluent/server.svg
new file mode 100644
index 000000000..1b876a172
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/server.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/store-microsoft-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/store-microsoft-filled.svg
new file mode 100644
index 000000000..6673448f3
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/store-microsoft-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/store-microsoft.svg b/dots/.config/quickshell/ii/assets/icons/fluent/store-microsoft.svg
new file mode 100644
index 000000000..affc6cc6e
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/store-microsoft.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/wand-filled.svg b/dots/.config/quickshell/ii/assets/icons/fluent/wand-filled.svg
new file mode 100644
index 000000000..fffb70e7f
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/wand-filled.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/wand.svg b/dots/.config/quickshell/ii/assets/icons/fluent/wand.svg
new file mode 100644
index 000000000..a5033c274
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/wand.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/modules/common/models/LauncherSearchResult.qml b/dots/.config/quickshell/ii/modules/common/models/LauncherSearchResult.qml
index 15beef12e..c47fc4f39 100644
--- a/dots/.config/quickshell/ii/modules/common/models/LauncherSearchResult.qml
+++ b/dots/.config/quickshell/ii/modules/common/models/LauncherSearchResult.qml
@@ -19,11 +19,14 @@ QtObject {
}
property var actions: []
- // Stuff needed for DesktopEntry objects
+ // Stuff needed for DesktopEntry
+ property string id: ""
property bool shown: true
property string comment: ""
property bool runInTerminal: false
property string genericName: ""
property list keywords: []
+ // Extra stuff to allow for more flexibility
+ property string category: type
}
diff --git a/dots/.config/quickshell/ii/modules/common/widgets/StyledScrollBar.qml b/dots/.config/quickshell/ii/modules/common/widgets/StyledScrollBar.qml
index 7b677c426..f37203250 100644
--- a/dots/.config/quickshell/ii/modules/common/widgets/StyledScrollBar.qml
+++ b/dots/.config/quickshell/ii/modules/common/widgets/StyledScrollBar.qml
@@ -9,6 +9,7 @@ ScrollBar {
policy: ScrollBar.AsNeeded
topPadding: Appearance.rounding.normal
bottomPadding: Appearance.rounding.normal
+ active: hovered || pressed
contentItem: Rectangle {
implicitWidth: 4
diff --git a/dots/.config/quickshell/ii/modules/ii/lock/Lock.qml b/dots/.config/quickshell/ii/modules/ii/lock/Lock.qml
index e942f4fda..3d6506c54 100644
--- a/dots/.config/quickshell/ii/modules/ii/lock/Lock.qml
+++ b/dots/.config/quickshell/ii/modules/ii/lock/Lock.qml
@@ -72,7 +72,7 @@ Scope {
}
// Unlock the keyring if configured to do so
- if (Config.options.lock.security.unlockKeyring) root.unlockKeyring();
+ if (Config.options.lock.security.unlockKeyring) root.unlockKeyring(); // Async
// Unlock the screen before exiting, or the compositor will display a
// fallback lock you can't interact with.
@@ -83,6 +83,12 @@ Scope {
// Reset
lockContext.reset();
+
+ // Post-unlock actions
+ if (lockContext.alsoInhibitIdle) {
+ lockContext.alsoInhibitIdle = false;
+ Idle.toggleInhibit(true);
+ }
}
}
diff --git a/dots/.config/quickshell/ii/modules/ii/lock/LockContext.qml b/dots/.config/quickshell/ii/modules/ii/lock/LockContext.qml
index b242cdc05..e6454b476 100644
--- a/dots/.config/quickshell/ii/modules/ii/lock/LockContext.qml
+++ b/dots/.config/quickshell/ii/modules/ii/lock/LockContext.qml
@@ -21,6 +21,7 @@ Scope {
property bool showFailure: false
property bool fingerprintsConfigured: false
property var targetAction: LockContext.ActionEnum.Unlock
+ property bool alsoInhibitIdle: false
function resetTargetAction() {
root.targetAction = LockContext.ActionEnum.Unlock;
@@ -58,7 +59,8 @@ Scope {
passwordClearTimer.restart();
}
- function tryUnlock() {
+ function tryUnlock(alsoInhibitIdle = false) {
+ root.alsoInhibitIdle = alsoInhibitIdle;
root.unlockInProgress = true;
pam.start();
}
diff --git a/dots/.config/quickshell/ii/modules/ii/lock/LockSurface.qml b/dots/.config/quickshell/ii/modules/ii/lock/LockSurface.qml
index da3e17627..e44eecacb 100644
--- a/dots/.config/quickshell/ii/modules/ii/lock/LockSurface.qml
+++ b/dots/.config/quickshell/ii/modules/ii/lock/LockSurface.qml
@@ -59,10 +59,20 @@ MouseArea {
}
// Key presses
+ property bool ctrlHeld: false
Keys.onPressed: event => {
root.context.resetClearTimer();
+ if (event.key === Qt.Key_Control) {
+ root.ctrlHeld = true;
+ }
if (event.key === Qt.Key_Escape) { // Esc to clear
root.context.currentText = "";
+ }
+ forceFieldFocus();
+ }
+ Keys.onReleased: event => {
+ if (event.key === Qt.Key_Control) {
+ root.ctrlHeld = false;
}
forceFieldFocus();
}
@@ -133,7 +143,9 @@ MouseArea {
// Synchronizing (across monitors) and unlocking
onTextChanged: root.context.currentText = this.text
- onAccepted: root.context.tryUnlock()
+ onAccepted: {
+ root.context.tryUnlock(ctrlHeld);
+ }
Connections {
target: root.context
function onCurrentTextChanged() {
@@ -202,7 +214,7 @@ MouseArea {
iconSize: 24
text: {
if (root.context.targetAction === LockContext.ActionEnum.Unlock) {
- return "arrow_right_alt";
+ return root.ctrlHeld ? "emoji_food_beverage" : "arrow_right_alt";
} else if (root.context.targetAction === LockContext.ActionEnum.Poweroff) {
return "power_settings_new";
} else if (root.context.targetAction === LockContext.ActionEnum.Reboot) {
diff --git a/dots/.config/quickshell/ii/modules/ii/regionSelector/RegionSelection.qml b/dots/.config/quickshell/ii/modules/ii/regionSelector/RegionSelection.qml
index a52471ba6..8f484591b 100644
--- a/dots/.config/quickshell/ii/modules/ii/regionSelector/RegionSelection.qml
+++ b/dots/.config/quickshell/ii/modules/ii/regionSelector/RegionSelection.qml
@@ -26,7 +26,7 @@ PanelWindow {
bottom: true
}
- // TODO: Ask: sidebar AI; Ocr: tesseract
+ // TODO: Ask: sidebar AI
enum SnipAction { Copy, Edit, Search, CharRecognition, Record, RecordWithSound }
enum SelectionMode { RectCorners, Circle }
property var action: RegionSelection.SnipAction.Copy
diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml
index f7c2dc9f8..dab92df5f 100644
--- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml
+++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml
@@ -30,6 +30,12 @@ ColumnLayout {
required property var modelData
node: modelData
}
+ PagePlaceholder {
+ icon: "widgets"
+ title: Translation.tr("No applications")
+ shown: !root.hasApps
+ shape: MaterialShape.Shape.Cookie7Sided
+ }
}
StyledComboBox {
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
index b9cbc00bd..802add786 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
@@ -17,8 +17,8 @@ Singleton {
property string iconsPath: `${Directories.assetsPath}/icons/fluent`
property bool dark: Appearance.m3colors.darkmode
- property real backgroundTransparency: 0.13
- property real panelBackgroundTransparency: 0.12
+ property real backgroundTransparency: 0.16
+ property real panelBackgroundTransparency: 0.14
property real panelLayerTransparency: root.dark ? 0.9 : 0.7
property real contentTransparency: root.dark ? 0.87 : 0.5
function applyBackgroundTransparency(col) {
@@ -152,6 +152,7 @@ Singleton {
property real normal: 11
property real large: 13
property real larger: 15
+ property real xlarger: 17
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml
index 7fe121165..b804aa3d9 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml
@@ -48,7 +48,7 @@ Singleton {
}
property string batteryLevelIcon: {
- const discreteLevel = Math.ceil(Battery.percentage * 10)
+ const discreteLevel = Math.ceil(Battery.percentage * 10);
return `battery-${discreteLevel > 9 ? "full" : discreteLevel}`;
}
@@ -107,7 +107,8 @@ Singleton {
function audioAppIcon(node) {
let icon;
icon = AppSearch.guessIcon(node?.properties["application.icon-name"] ?? "");
- if (AppSearch.iconExists(icon)) return icon;
+ if (AppSearch.iconExists(icon))
+ return icon;
icon = AppSearch.guessIcon(node?.properties["node.name"] ?? "");
return icon;
}
@@ -127,4 +128,60 @@ Singleton {
return "bluetooth";
}
+ function fluentFromMaterial(icon) {
+ switch (icon) {
+ case "calculate":
+ return "calculator";
+ case "keyboard_return":
+ return "arrow-enter-left";
+ case "open_in_new":
+ return "open";
+ case "settings_suggest":
+ return "wand";
+ case "terminal":
+ return "app-generic";
+ case "travel_explore":
+ return "globe-search";
+ case "keep":
+ return "pin";
+ case "keep_off":
+ return "pin-off";
+ default:
+ return "apps";
+ }
+ }
+
+ function guessIconForName(name) {
+ const lowerName = name.toLowerCase();
+ if (lowerName.includes("app") || lowerName.includes("desktop"))
+ return "apps";
+ if (lowerName.includes("news"))
+ return "news";
+ if (lowerName.includes("new") || lowerName.includes("create") || lowerName.includes("add"))
+ return "add";
+ if (lowerName.includes("open"))
+ return "open";
+ if (lowerName.includes("friends") || lowerName.includes("contact") || lowerName.includes("family"))
+ return "people";
+ if (lowerName.includes("community"))
+ return "people-team";
+ if (lowerName.includes("library"))
+ return "library";
+ if (lowerName.includes("setting"))
+ return "settings";
+ if (lowerName.includes("gallery"))
+ return "image-copy";
+ if (lowerName.includes("server"))
+ return "server";
+ if (lowerName.includes("picture") || lowerName.includes("photo") || lowerName.includes("image"))
+ return "image";
+ if (lowerName.includes("store") || lowerName.includes("shop"))
+ return "store-microsoft";
+ if (lowerName.includes("record") || lowerName.includes("capture"))
+ return "record";
+ if (lowerName.includes("screen") || lowerName.includes("display") || lowerName.includes("monitor") || lowerName.includes("desktop"))
+ return "desktop";
+
+ return "apps";
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WListView.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WListView.qml
new file mode 100644
index 000000000..bc567762a
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WListView.qml
@@ -0,0 +1,10 @@
+import qs.modules.common
+import qs.modules.common.widgets
+import QtQuick
+import QtQuick.Controls
+
+ListView {
+ id: root
+
+ ScrollBar.vertical: WScrollBar {}
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WScrollBar.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WScrollBar.qml
new file mode 100644
index 000000000..bdc962806
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WScrollBar.qml
@@ -0,0 +1,25 @@
+import QtQuick
+import QtQuick.Controls
+import qs.modules.common
+import qs.modules.common.widgets
+import qs.modules.common.functions
+
+ScrollBar {
+ id: root
+
+ policy: ScrollBar.AsNeeded
+ active: hovered || pressed
+ property color color: Looks.colors.controlBg
+
+ contentItem: Rectangle {
+ implicitWidth: root.active ? 4 : 2
+ implicitHeight: root.visualSize
+ radius: 9999
+ color: root.color
+
+ opacity: root.policy === ScrollBar.AlwaysOn || (root.active && root.size < 1.0) ? 0.5 : 0
+ Behavior on opacity {
+ animation: Looks.transition.opacity.createObject(this)
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml
index ce5652329..d38bc8d98 100644
--- a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchBar.qml
@@ -15,10 +15,16 @@ FooterRectangle {
property real horizontalPadding: 32
property real verticalPadding: 16
property bool searching: text.length > 0
+ property alias searchInput: searchInput
property alias text: searchInput.text
implicitHeight: outline.implicitHeight + verticalPadding * 2
- Component.onCompleted: searchInput.forceActiveFocus()
+ signal accepted()
+
+ Component.onCompleted: forceFocus()
+ function forceFocus() {
+ searchInput.forceActiveFocus();
+ }
focus: true
color: searching ? Looks.colors.bgPanelBody : Looks.colors.bgPanelFooter
@@ -81,6 +87,10 @@ FooterRectangle {
visible: searchInput.text.length === 0
font.pixelSize: Looks.font.pixelSize.large
}
+
+ onAccepted: {
+ root.accepted();
+ }
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchEntryIcon.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchEntryIcon.qml
new file mode 100644
index 000000000..5f94870b7
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchEntryIcon.qml
@@ -0,0 +1,48 @@
+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
+
+Item {
+ id: root
+ required property LauncherSearchResult entry
+ property int iconSize: 24
+ implicitWidth: Math.max(iconSize, textIconLoader.implicitWidth)
+ implicitHeight: iconSize
+ Loader {
+ anchors.centerIn: parent
+ active: root.entry.iconType === LauncherSearchResult.IconType.System && root.entry.iconName !== ""
+ sourceComponent: WAppIcon {
+ implicitSize: root.iconSize
+ iconName: root.entry.iconName
+ tryCustomIcon: false
+ animated: false
+ }
+ }
+ Loader {
+ id: textIconLoader
+ anchors.centerIn: parent
+ active: root.entry.iconType === LauncherSearchResult.IconType.Text
+ sourceComponent: WText {
+ text: root.entry.iconName
+ font.pixelSize: root.iconSize
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ Loader {
+ anchors.centerIn: parent
+ active: root.entry.iconType === LauncherSearchResult.IconType.Material || root.entry.iconType === LauncherSearchResult.IconType.None || root.entry.iconName === ""
+ sourceComponent: FluentIcon {
+ icon: root.entry.iconName ? WIcons.fluentFromMaterial(root.entry.iconName) : WIcons.guessIconForName(root.entry.name)
+ implicitSize: root.iconSize
+ animated: false
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml
index a294950fd..b6f4a4e94 100644
--- a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchPageContent.qml
@@ -12,7 +12,9 @@ import qs.modules.waffle.looks
BodyRectangle {
id: root
+ property alias context: searchResults.context
property string searchText: LauncherSearch.query
+ property alias currentIndex: searchResults.currentIndex
ColumnLayout {
anchors {
@@ -24,11 +26,13 @@ BodyRectangle {
spacing: 12
TagStrip {
+ context: root.context
Layout.fillWidth: true
Layout.fillHeight: false
}
SearchResults {
+ id: 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
index 5f3d93411..a9e83929e 100644
--- a/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchResults.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/SearchResults.qml
@@ -1,19 +1,44 @@
+pragma ComponentBehavior: Bound
+import qs
+import qs.services
+import qs.modules.common
import qs.modules.waffle.looks
import qs.modules.common.functions
-import qs.modules.common
-import qs.services
-import qs
+import qs.modules.common.models
import Quickshell
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick
-pragma ComponentBehavior: Bound
RowLayout {
id: root
+ property int maxResultsPerCategory: 4
+ property StartMenuContext context
+ property int currentIndex: context.currentIndex
+ onCurrentIndexChanged: {
+ forceCurrentIndex(currentIndex);
+ }
function focusFirstItem() {
- resultList.currentIndex = 0;
+ forceCurrentIndex(0);
+ }
+ function forceCurrentIndex(index) {
+ context.currentIndex = index;
+ // Somehow this hack is needed
+ if (index === 0) {
+ resultList.incrementCurrentIndex();
+ resultList.decrementCurrentIndex();
+ } else {
+ resultList.decrementCurrentIndex();
+ resultList.incrementCurrentIndex();
+ }
+ }
+
+ Connections {
+ target: context
+ function onAccepted() {
+ resultList.currentItem?.execute();
+ }
}
ResultList {
@@ -25,23 +50,74 @@ RowLayout {
Layout.preferredWidth: 386
Layout.leftMargin: 1
Layout.rightMargin: 1
+ entry: resultList.model[resultList.currentIndex] ?? searchResultComp.createObject()
}
- component ResultList: ListView {
+ component ResultList: WListView {
+ id: resultListView
section {
criteria: ViewSection.FullString
- property: "type"
+ property: "category" // This is "type" with tweaks to make it match more closely
+ labelPositioning: ViewSection.InlineLabels
+ delegate: Item {
+ id: sectionButton
+ required property string section
+ implicitHeight: sectionChoiceButton.implicitHeight + resultListView.spacing
+ width: ListView.view?.width
+ WChoiceButton {
+ id: sectionChoiceButton
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: parent.top
+ }
+ implicitHeight: 38
+ contentItem: WText {
+ text: sectionButton.section
+ font.pixelSize: Looks.font.pixelSize.large
+ font.weight: Looks.font.weight.strong
+ }
+ onClicked: {
+ root.context.selectCategory(sectionButton.section);
+ }
+ }
+ }
}
clip: true
spacing: 4
- model: ScriptModel {
- values: {
- // TODO: categorize and have max per category
- LauncherSearch.results.slice(0, 10)
- }
- onValuesChanged: {
- root.focusFirstItem();
+ currentIndex: root.currentIndex
+
+ // We can't use a ScriptModel here because it would mess up sections
+ model: {
+ const allResults = LauncherSearch.results;
+ // Find categories
+ var categories = new Set();
+ for (let i = 0; i < allResults.length; i++) {
+ categories.add(allResults[i].type);
}
+
+ // Collect max 4 per category
+ var categorizedResults = [];
+ categories.forEach(category => {
+ let count = 0;
+ for (let i = 0; i < allResults.length; i++) {
+ if (allResults[i].type === category) {
+ const entry = allResults[i];
+ const tweakedEntry = searchResultComp.createObject(null, Object.assign({}, entry));
+ tweakedEntry.category = categorizedResults.length === 0 ? Translation.tr("Best match") : entry.type
+ categorizedResults.push(tweakedEntry); // Section header
+ count++;
+ if (count >= root.maxResultsPerCategory) {
+ break;
+ }
+ }
+ }
+ });
+ // print(JSON.stringify(categorizedResults, null, 2));
+ return categorizedResults;
+ }
+ onModelChanged: {
+ root.focusFirstItem();
}
delegate: WSearchResultButton {
required property int index
@@ -49,12 +125,120 @@ RowLayout {
entry: modelData
firstEntry: index === 0
width: ListView.view?.width
+ checked: resultListView.currentIndex === index
+ onRequestFocus: {
+ root.forceCurrentIndex(index);
+ }
}
}
component ResultPreview: Rectangle {
+ id: resultPreview
+
+ property LauncherSearchResult entry // LauncherSearchResult
+
Layout.fillHeight: true
color: Looks.colors.bg1
radius: Looks.radius.large
+
+ ColumnLayout {
+ anchors.fill: parent
+ anchors.margins: 22
+ spacing: 13
+
+ ColumnLayout {
+ id: mainInfoColumn
+ Layout.alignment: Qt.AlignHCenter
+ SearchEntryIcon {
+ Layout.alignment: Qt.AlignHCenter
+ Layout.topMargin: 10
+ Layout.bottomMargin: 12
+ entry: resultPreview.entry
+ iconSize: 64
+ }
+ WText {
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ elide: Text.ElideRight
+ wrapMode: Text.Wrap
+ maximumLineCount: 2
+ text: resultPreview.entry?.name || ""
+ font.pixelSize: Looks.font.pixelSize.xlarger
+ }
+ WText {
+ Layout.alignment: Qt.AlignHCenter
+ text: resultPreview.entry?.type || ""
+ color: Looks.colors.accentUnfocused
+ font.pixelSize: Looks.font.pixelSize.normal
+ }
+ }
+ Rectangle {
+ id: resultSeparator
+ implicitHeight: 2
+ Layout.topMargin: 16
+ Layout.fillWidth: true
+ color: Looks.colors.bg2Hover
+ }
+ WListView {
+ id: actionsColumn
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ clip: true
+ spacing: 2
+ model: {
+ const isAppEntry = resultPreview.entry.type === Translation.tr("App");
+ const appId = isAppEntry ? resultPreview.entry.id : "";
+ const pinned = isAppEntry ? (Config.options.dock.pinnedApps.includes(appId)) : false;
+ var result = [
+ searchResultComp.createObject(null, {
+ name: resultPreview.entry.verb,
+ iconName: isAppEntry ? "open_in_new" : "keyboard_return",
+ iconType: LauncherSearchResult.IconType.Material,
+ execute: () => {
+ resultPreview.entry.execute();
+ }
+ }),
+ ...(isAppEntry ? [
+ searchResultComp.createObject(null, {
+ name: pinned ? Translation.tr("Unpin from taskbar") : Translation.tr("Pin to taskbar"),
+ iconName: pinned ? "keep_off" : "keep",
+ iconType: LauncherSearchResult.IconType.Material,
+ execute: () => {
+ TaskbarApps.togglePin(appId);
+ }
+ })
+ ] : [])
+ ];
+ result = result.concat(resultPreview.entry.actions);
+ return result;
+ }
+ delegate: WButton {
+ id: actionButton
+ required property var modelData
+ width: ListView.view?.width
+ icon.name: modelData.iconName
+ text: modelData.name
+ onClicked: modelData.execute();
+
+ contentItem: RowLayout {
+ spacing: 11
+ SearchEntryIcon {
+ entry: actionButton.modelData
+ iconSize: 16
+ }
+ WText {
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignLeft
+ text: actionButton.text
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Component {
+ id: searchResultComp
+ LauncherSearchResult {}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml
index 09de017ee..2f76ca0ca 100644
--- a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContent.qml
@@ -16,10 +16,72 @@ WBarAttachedPanelContent {
property bool searching: false
property string searchText: LauncherSearch.query
+ StartMenuContext {
+ id: context
+ }
+
+ Keys.onPressed: event => {
+ // Prevent Esc and Backspace from registering
+ if (event.key === Qt.Key_Escape)
+ return;
+
+ // Handle Backspace: focus and delete character if not focused
+ if (event.key === Qt.Key_Backspace) {
+ searchBar.forceFocus();
+ if (event.modifiers & Qt.ControlModifier) {
+ // Delete word before cursor
+ let text = searchBar.text;
+ let pos = searchBar.searchInput.cursorPosition;
+ if (pos > 0) {
+ // Find the start of the previous word
+ let left = text.slice(0, pos);
+ let match = left.match(/(\s*\S+)\s*$/);
+ let deleteLen = match ? match[0].length : 1;
+ searchBar.text = text.slice(0, pos - deleteLen) + text.slice(pos);
+ searchBar.searchInput.cursorPosition = pos - deleteLen;
+ }
+ } else {
+ // Delete character before cursor if any
+ if (searchBar.searchInput.cursorPosition > 0) {
+ searchBar.text = searchBar.text.slice(0, searchBar.searchInput.cursorPosition - 1) + searchBar.text.slice(searchBar.searchInput.cursorPosition);
+ searchBar.searchInput.cursorPosition -= 1;
+ }
+ }
+ // Always move cursor to end after programmatic edit
+ searchBar.searchInput.cursorPosition = searchBar.text.length;
+ event.accepted = true;
+ // If already focused, let TextField handle it
+ return;
+ }
+
+ // Only handle visible printable characters (ignore control chars, arrows, etc.)
+ if (event.text && event.text.length === 1 && event.key !== Qt.Key_Enter && event.key !== Qt.Key_Return && event.key !== Qt.Key_Delete && event.text.charCodeAt(0) >= 0x20) // ignore control chars like Backspace, Tab, etc.
+ {
+ if (!searchBar.searchInput.activeFocus) {
+ searchBar.forceFocus();
+ // Insert the character at the cursor position
+ searchBar.text = searchBar.text.slice(0, searchBar.searchInput.cursorPosition) + event.text + searchBar.text.slice(searchBar.searchInput.cursorPosition);
+ searchBar.searchInput.cursorPosition += 1;
+ event.accepted = true;
+ context.setCurrentIndex(0);
+ }
+ }
+
+ // Arrow keys for item navigation
+ if (event.key === Qt.Key_Down) {
+ let maxIndex = Math.max(0, LauncherSearch.results.length - 1);
+ context.setCurrentIndex(Math.min(context.currentIndex + 1, maxIndex));
+ event.accepted = true;
+ } else if (event.key === Qt.Key_Up) {
+ context.setCurrentIndex(Math.max(context.currentIndex - 1, 0));
+ event.accepted = true;
+ }
+ }
+
contentItem: WPane {
contentItem: WPanelPageColumn {
SearchBar {
- focus: true
+ id: searchBar
Layout.fillWidth: true
implicitWidth: 832 // TODO: Make sizes naturally inferred
horizontalPadding: root.searching ? 24 : 32
@@ -27,10 +89,14 @@ WBarAttachedPanelContent {
Synchronizer on searching {
property alias target: root.searching
}
+ focus: true
text: root.searchText
onTextChanged: {
LauncherSearch.query = text;
}
+ onAccepted: {
+ context.accepted();
+ }
}
Item {
implicitHeight: root.searching ? 736 : 736 // TODO: Make sizes naturally inferred
@@ -46,7 +112,9 @@ WBarAttachedPanelContent {
Component {
id: searchPageComp
- SearchPageContent {}
+ SearchPageContent {
+ context: context
+ }
}
Component {
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContext.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContext.qml
new file mode 100644
index 000000000..ff2289da0
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/StartMenuContext.qml
@@ -0,0 +1,64 @@
+import QtQuick
+import Quickshell
+import Quickshell.Io
+import qs
+import qs.modules.common
+import qs.services
+
+Scope {
+ id: root
+
+ signal accepted
+
+ property int currentIndex: 0
+ function setCurrentIndex(index) {
+ if (index == currentIndex)
+ return;
+ currentIndex = index;
+ }
+
+ function selectCategory(category) {
+ for (let i = 0; i < root.categories.length; i++) {
+ const thisCategoryName = root.categories[i].name;
+ if (thisCategoryName.startsWith(category) || category.startsWith(thisCategoryName)) {
+ LauncherSearch.ensurePrefix(root.categories[i].prefix);
+ return;
+ }
+ }
+ }
+ property list categories: [
+ {
+ 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
+ },
+ ]
+
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/TagStrip.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/TagStrip.qml
index 10448b5cd..a1deb0027 100644
--- a/dots/.config/quickshell/ii/modules/waffle/startMenu/TagStrip.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/TagStrip.qml
@@ -10,6 +10,9 @@ import qs.modules.common.functions
import qs.modules.waffle.looks
RowLayout {
+ id: root
+ property StartMenuContext context
+
WPanelIconButton {
implicitWidth: 36
implicitHeight: 36
@@ -23,40 +26,8 @@ RowLayout {
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
- },
- ]
+ model: root.context.categories
+ clip: true
delegate: WBorderedButton {
id: tagButton
required property var modelData
@@ -68,7 +39,7 @@ RowLayout {
if (modelData.prefix != "") {
return LauncherSearch.query.startsWith(modelData.prefix);
} else {
- return !tagListView.model.some(i => (i.prefix != "" && LauncherSearch.query.startsWith(i.prefix)))
+ return !tagListView.model.some(i => (i.prefix != "" && LauncherSearch.query.startsWith(i.prefix)));
}
}
contentItem: Item {
@@ -84,9 +55,27 @@ RowLayout {
}
}
WPanelIconButton {
+ id: optionsButton
implicitWidth: 36
implicitHeight: 36
iconSize: 24
iconName: "more-horizontal"
+
+ onClicked: accountsMenu.open()
+
+ WMenu {
+ id: accountsMenu
+ x: -accountsMenu.implicitWidth + optionsButton.implicitWidth
+ y: optionsButton.height + 10
+ downDirection: true
+ Action {
+ icon.name: "people-settings"
+ text: Translation.tr("Manage accounts")
+ onTriggered: {
+ Quickshell.execDetached(["bash", "-c", Config.options.apps.manageUser])
+ GlobalStates.searchOpen = false;
+ }
+ }
+ }
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/WSearchResultButton.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/WSearchResultButton.qml
index 1aca104b0..b7fb1df14 100644
--- a/dots/.config/quickshell/ii/modules/waffle/startMenu/WSearchResultButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/WSearchResultButton.qml
@@ -11,51 +11,84 @@ import qs.modules.waffle.looks
WChoiceButton {
id: root
-
+
required property LauncherSearchResult entry
property bool firstEntry: false
+ signal requestFocus()
+
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
- }
+ execute();
}
- 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
+ function execute() {
+ GlobalStates.searchOpen = false;
+ root.entry.execute();
+ }
+
+ horizontalPadding: 0
+ verticalPadding: 0
+
+ contentItem: RowLayout {
+ id: contentLayout
+ spacing: 0
+
+ WButton {
+ id: launchButton
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ horizontalPadding: 10
+ verticalPadding: 11
+ implicitHeight: root.firstEntry ? 62 : 36
+ implicitWidth: entryContentRow.implicitWidth + leftPadding + rightPadding
+ topRightRadius: 0
+ bottomRightRadius: 0
+ onClicked: root.click()
+ contentItem: Item {
+ RowLayout {
+ id: entryContentRow
+ anchors {
+ left: parent.left
+ verticalCenter: parent.verticalCenter
+ }
+ spacing: 8
+
+ SearchEntryIcon {
+ entry: root.entry
+ iconSize: 24
+ }
+ EntryNameColumn {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignVCenter
+ }
+ }
}
}
- 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
+ Rectangle {
+ id: separator
+ opacity: (root.hovered && !root.checked) ? 1 : 0
+ Layout.fillHeight: true
+ implicitWidth: 1
+ color: ColorUtils.transparentize(Looks.colors.fg, 0.75)
+ }
+ WButton {
+ visible: !root.checked
+ Layout.fillHeight: true
+ implicitWidth: 47
+ topLeftRadius: 0
+ bottomLeftRadius: 0
+ onClicked: root.requestFocus()
+ contentItem: Item {
+ FluentIcon {
+ anchors.centerIn: parent
+ icon: "chevron-right"
+ implicitSize: 14
+ }
}
}
}
@@ -78,4 +111,11 @@ WChoiceButton {
color: Looks.colors.accentUnfocused
}
}
+
+ MouseArea {
+ anchors.fill: parent
+ // hoverEnabled: true
+ acceptedButtons: Qt.NoButton
+ cursorShape: Qt.PointingHandCursor
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/startMenu/WaffleStartMenu.qml b/dots/.config/quickshell/ii/modules/waffle/startMenu/WaffleStartMenu.qml
index 9b59fb0c8..15ffc6f43 100644
--- a/dots/.config/quickshell/ii/modules/waffle/startMenu/WaffleStartMenu.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/startMenu/WaffleStartMenu.qml
@@ -15,8 +15,10 @@ Scope {
target: GlobalStates
function onSearchOpenChanged() {
- if (GlobalStates.searchOpen)
+ if (GlobalStates.searchOpen) {
+ LauncherSearch.query = "";
panelLoader.active = true;
+ }
}
}
@@ -62,6 +64,7 @@ Scope {
onClosed: {
GlobalStates.searchOpen = false;
panelLoader.active = false;
+ LauncherSearch.query = "";
}
}
}
diff --git a/dots/.config/quickshell/ii/services/Audio.qml b/dots/.config/quickshell/ii/services/Audio.qml
index 4b45701a9..29b0a2f68 100644
--- a/dots/.config/quickshell/ii/services/Audio.qml
+++ b/dots/.config/quickshell/ii/services/Audio.qml
@@ -18,6 +18,7 @@ Singleton {
readonly property real hardMaxValue: 2.00 // People keep joking about setting volume to 5172% so...
property string audioTheme: Config.options.sounds.theme
property real value: sink?.audio.volume ?? 0
+
function friendlyDeviceName(node) {
return (node.nickname || node.description || Translation.tr("Unknown"));
}
@@ -105,9 +106,9 @@ Singleton {
if (newVolume - lastVolume > maxAllowedIncrease) {
sink.audio.volume = lastVolume;
root.sinkProtectionTriggered(Translation.tr("Illegal increment"));
- } else if (newVolume > maxAllowed || newVolume > root.hardMaxValue) {
+ } else if (Math.round(newVolume * 100) / 100 > maxAllowed || newVolume > root.hardMaxValue) {
root.sinkProtectionTriggered(Translation.tr("Exceeded max allowed"));
- sink.audio.volume = Math.min(lastVolume, maxAllowed);
+ sink.audio.volume = maxAllowed;
}
lastVolume = sink.audio.volume;
}
diff --git a/dots/.config/quickshell/ii/services/Idle.qml b/dots/.config/quickshell/ii/services/Idle.qml
index ad938f3c3..a2b804772 100644
--- a/dots/.config/quickshell/ii/services/Idle.qml
+++ b/dots/.config/quickshell/ii/services/Idle.qml
@@ -1,8 +1,8 @@
+pragma Singleton
import qs.modules.common
import QtQuick
import Quickshell
import Quickshell.Wayland
-pragma Singleton
/**
* A nice wrapper for date and time strings.
@@ -17,21 +17,26 @@ Singleton {
target: Persistent
function onReadyChanged() {
if (!Persistent.isNewHyprlandInstance) {
- root.inhibit = Persistent.states.idle.inhibit
+ root.inhibit = Persistent.states.idle.inhibit;
} else {
- Persistent.states.idle.inhibit = root.inhibit
+ Persistent.states.idle.inhibit = root.inhibit;
}
}
}
- function toggleInhibit() {
- root.inhibit = !root.inhibit
- Persistent.states.idle.inhibit = root.inhibit
+ function toggleInhibit(active = null) {
+ if (active !== null) {
+ root.inhibit = active;
+ } else {
+ root.inhibit = !root.inhibit;
+ }
+ Persistent.states.idle.inhibit = root.inhibit;
}
IdleInhibitor {
id: idleInhibitor
- window: PanelWindow { // Inhibitor requires a "visible" surface
+ window: PanelWindow {
+ // Inhibitor requires a "visible" surface
// Actually not lol
implicitWidth: 0
implicitHeight: 0
@@ -46,6 +51,5 @@ Singleton {
item: null
}
}
- }
-
+ }
}
diff --git a/dots/.config/quickshell/ii/services/LauncherSearch.qml b/dots/.config/quickshell/ii/services/LauncherSearch.qml
index 89d9e0056..49de2158e 100644
--- a/dots/.config/quickshell/ii/services/LauncherSearch.qml
+++ b/dots/.config/quickshell/ii/services/LauncherSearch.qml
@@ -198,10 +198,11 @@ Singleton {
const appResultObjects = AppSearch.fuzzyQuery(StringUtils.cleanPrefix(root.query, Config.options.search.prefix.app)).map(entry => {
return resultComp.createObject(null, {
type: Translation.tr("App"),
+ id: entry.id,
name: entry.name,
iconName: entry.icon,
iconType: LauncherSearchResult.IconType.System,
- verb: Translation.tr("Launch"),
+ verb: Translation.tr("Open"),
execute: () => {
if (!entry.runInTerminal)
entry.execute();
@@ -233,7 +234,7 @@ Singleton {
const commandResultObject = resultComp.createObject(null, {
name: StringUtils.cleanPrefix(root.query, Config.options.search.prefix.shellCommand).replace("file://", ""),
verb: Translation.tr("Run"),
- type: Translation.tr("Run command"),
+ type: Translation.tr("Command"),
fontType: LauncherSearchResult.FontType.Monospace,
iconName: 'terminal',
iconType: LauncherSearchResult.IconType.Material,
@@ -249,7 +250,7 @@ Singleton {
const webSearchResultObject = resultComp.createObject(null, {
name: StringUtils.cleanPrefix(root.query, Config.options.search.prefix.webSearch),
verb: Translation.tr("Search"),
- type: Translation.tr("Search the web"),
+ type: Translation.tr("Web search"),
iconName: 'travel_explore',
iconType: LauncherSearchResult.IconType.Material,
execute: () => {
diff --git a/dots/.config/quickshell/ii/services/Privacy.qml b/dots/.config/quickshell/ii/services/Privacy.qml
new file mode 100644
index 000000000..a14da7689
--- /dev/null
+++ b/dots/.config/quickshell/ii/services/Privacy.qml
@@ -0,0 +1,16 @@
+pragma Singleton
+pragma ComponentBehavior: Bound
+import qs.modules.common
+import QtQuick
+import Quickshell
+import Quickshell.Services.Pipewire
+
+/**
+ * Screensharing and mic activity.
+ */
+Singleton {
+ id: root
+
+ property bool screenSharing: Pipewire.linkGroups.values.filter(pwlg => pwlg.source.type === PwNodeType.VideoSource).map(pwlg => pwlg.target)
+ property bool micActive: Pipewire.linkGroups.values.filter(pwlg => pwlg.source.type === PwNodeType.AudioSource && pwlg.target.type === PwNodeType.AudioInStream).map(pwlg => pwlg.target)
+}
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 {
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