Merge remote-tracking branch 'upstream/main' into fix-dock-first-launch

This commit is contained in:
altrup
2026-03-04 15:01:36 -05:00
165 changed files with 5099 additions and 1437 deletions
@@ -10,7 +10,6 @@ exec-once = gnome-keyring-daemon --start --components=secrets
exec-once = hypridle exec-once = hypridle
exec-once = dbus-update-activation-environment --all exec-once = dbus-update-activation-environment --all
exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP # Some fix idk exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP # Some fix idk
exec-once = hyprpm reload
# Audio # Audio
exec-once = easyeffects --gapplication-service exec-once = easyeffects --gapplication-service
+1 -1
View File
@@ -1,5 +1,5 @@
# Auto start Hyprland on tty1 # Auto start Hyprland on tty1
if test -z "$DISPLAY" ;and test "$XDG_VTNR" -eq 1 if test -z "$DISPLAY" ;and test "$XDG_VTNR" -eq 1
mkdir -p ~/.cache mkdir -p ~/.cache
exec Hyprland > ~/.cache/hyprland.log 2>&1 exec start-hyprland > ~/.cache/hyprland.log 2>&1
end end
+4 -2
View File
@@ -18,9 +18,11 @@ if status is-interactive # Commands to run in interactive sessions can go here
end end
# Aliases # Aliases
alias pamcan pacman alias clear "printf '\033[2J\033[3J\033[1;1H'" # fix: kitty doesn't clear properly
alias celar "printf '\033[2J\033[3J\033[1;1H'"
alias claer "printf '\033[2J\033[3J\033[1;1H'"
alias ls 'eza --icons' alias ls 'eza --icons'
alias clear "printf '\033[2J\033[3J\033[1;1H'" alias pamcan pacman
alias q 'qs -c ii' alias q 'qs -c ii'
end end
+2 -2
View File
@@ -5,7 +5,7 @@
# ######## Window rules ######## # ######## Window rules ########
# Uncomment to apply global transparency to all windows: # Uncomment to apply global transparency to all windows:
# windowrulev2 = opacity 0.89 override 0.89 override, class:.* # windowrule = opacity 0.89 override 0.89 override, match:class .*
# Disable blur for all xwayland apps # Disable blur for all xwayland apps
# windowrulev2 = noblur, xwayland:1 # windowrule = no_blur on, match:xwayland 1
+4 -2
View File
@@ -5,8 +5,11 @@ $qsConfig = ii
exec = hyprctl dispatch submap global # DO NOT REMOVE THIS OR YOU WON'T BE ABLE TO USE ANY KEYBIND exec = hyprctl dispatch submap global # DO NOT REMOVE THIS OR YOU WON'T BE ABLE TO USE ANY KEYBIND
submap = global # This is required for catchall to work submap = global # This is required for catchall to work
# Defaults # Environment variables
source=hyprland/env.conf source=hyprland/env.conf
source=custom/env.conf
# Defaults
source=hyprland/execs.conf source=hyprland/execs.conf
source=hyprland/general.conf source=hyprland/general.conf
source=hyprland/rules.conf source=hyprland/rules.conf
@@ -14,7 +17,6 @@ source=hyprland/colors.conf
source=hyprland/keybinds.conf source=hyprland/keybinds.conf
# Custom # Custom
source=custom/env.conf
source=custom/execs.conf source=custom/execs.conf
source=custom/general.conf source=custom/general.conf
source=custom/rules.conf source=custom/rules.conf
+1 -1
View File
@@ -31,4 +31,4 @@ plugin {
} }
} }
windowrulev2 = bordercolor rgba(FFB2BCAA) rgba(FFB2BC77),pinned:1 windowrule = border_color rgba(FFB2BCAA) rgba(FFB2BC77), match:pin 1
+1 -1
View File
@@ -5,7 +5,7 @@ env = ELECTRON_OZONE_PLATFORM_HINT,auto
env = XDG_DATA_DIRS,$HOME/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share env = XDG_DATA_DIRS,$HOME/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
# ############ Themes ############# # ############ Themes #############
env = QT_QPA_PLATFORM, wayland env = QT_QPA_PLATFORM, wayland;xcb
env = QT_QPA_PLATFORMTHEME, kde env = QT_QPA_PLATFORMTHEME, kde
env = XDG_MENU_PREFIX, plasma- env = XDG_MENU_PREFIX, plasma-
-1
View File
@@ -8,7 +8,6 @@ exec-once = gnome-keyring-daemon --start --components=secrets
exec-once = hypridle exec-once = hypridle
exec-once = dbus-update-activation-environment --all exec-once = dbus-update-activation-environment --all
exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP # Some fix idk exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP # Some fix idk
exec-once = hyprpm reload
# Audio # Audio
exec-once = easyeffects --hide-window --service-mode exec-once = easyeffects --hide-window --service-mode
+20 -27
View File
@@ -4,8 +4,8 @@ monitor=,preferred,auto,1
gesture = 3, swipe, move, gesture = 3, swipe, move,
gesture = 3, pinch, float gesture = 3, pinch, float
gesture = 4, horizontal, workspace gesture = 4, horizontal, workspace
gesture = 4, up, dispatcher, global, quickshell:overviewToggle gesture = 4, up, dispatcher, global, quickshell:overviewWorkspacesToggle
gesture = 4, down, dispatcher, global, quickshell:overviewClose gesture = 4, down, dispatcher, global, quickshell:overviewWorkspacesClose
gestures { gestures {
workspace_swipe_distance = 700 workspace_swipe_distance = 700
workspace_swipe_cancel_ratio = 0.2 workspace_swipe_cancel_ratio = 0.2
@@ -22,7 +22,7 @@ general {
gaps_workspaces = 50 gaps_workspaces = 50
border_size = 1 border_size = 1
col.active_border = rgba(0DB7D4FF) col.active_border = rgba(0DB7D455)
col.inactive_border = rgba(31313600) col.inactive_border = rgba(31313600)
resize_on_border = true resize_on_border = true
@@ -31,10 +31,10 @@ general {
allow_tearing = true # This just allows the `immediate` window rule to work allow_tearing = true # This just allows the `immediate` window rule to work
snap { snap {
enabled = true enabled = true
window_gap = 4 window_gap = 4
monitor_gap = 5 monitor_gap = 5
respect_gaps = true respect_gaps = true
} }
} }
@@ -46,6 +46,9 @@ dwindle {
} }
decoration { decoration {
# 2 = circle, higher = squircle, 4 = very obvious squircle
# Clear squircles look really off; we use only extra .4 here to make the rounding feel more continuous
rounding_power = 2
rounding = 18 rounding = 18
blur { blur {
@@ -69,16 +72,16 @@ decoration {
shadow { shadow {
enabled = true enabled = true
ignore_window = true ignore_window = true
range = 30 range = 50
offset = 0 2 offset = 0 4
render_power = 4 render_power = 10
color = rgba(00000010) color = rgba(00000027)
} }
# Dim # Dim
dim_inactive = true dim_inactive = true
dim_strength = 0.025 dim_strength = 0.05
dim_special = 0.07 dim_special = 0.2
} }
animations { animations {
@@ -112,6 +115,8 @@ animations {
## specialWorkspace ## specialWorkspace
animation = specialWorkspaceIn, 1, 2.8, emphasizedDecel, slidevert animation = specialWorkspaceIn, 1, 2.8, emphasizedDecel, slidevert
animation = specialWorkspaceOut, 1, 1.2, emphasizedAccel, slidevert animation = specialWorkspaceOut, 1, 1.2, emphasizedAccel, slidevert
# zoom
animation = zoomFactor, 1, 3, standardDecel
} }
input { input {
@@ -142,7 +147,7 @@ misc {
animate_mouse_windowdragging = false animate_mouse_windowdragging = false
enable_swallow = false enable_swallow = false
swallow_regex = (foot|kitty|allacritty|Alacritty) swallow_regex = (foot|kitty|allacritty|Alacritty)
new_window_takes_over_fullscreen = 2 on_focus_under_fullscreen = 2
allow_session_lock_restore = true allow_session_lock_restore = true
session_lock_xray = true session_lock_xray = true
initial_workspace_tracking = false initial_workspace_tracking = false
@@ -157,19 +162,7 @@ binds {
cursor { cursor {
zoom_factor = 1 zoom_factor = 1
zoom_rigid = false zoom_rigid = false
zoom_disable_aa = true
hotspot_padding = 1 hotspot_padding = 1
} }
# Overview
plugin {
hyprexpo {
columns = 3
gap_size = 5
bg_col = rgb(000000)
workspace_method = first 1 # [center/first] [workspace] e.g. first 1 or center m+1
enable_gesture = false # laptop touchpad, 4 fingers
gesture_distance = 300 # how far is the "max"
gesture_positive = false
}
}
+7 -9
View File
@@ -53,7 +53,7 @@ bindd = Ctrl+Super, T, Toggle wallpaper selector, global, quickshell:wallpaperSe
bindd = Ctrl+Super+Alt, T, Select random wallpaper, global, quickshell:wallpaperSelectorRandom # Random wallpaper bindd = Ctrl+Super+Alt, T, Select random wallpaper, global, quickshell:wallpaperSelectorRandom # Random wallpaper
bindd = Ctrl+Super, T, Change wallpaper, exec, qs -c $qsConfig ipc call TEST_ALIVE || ~/.config/quickshell/$qsConfig/scripts/colors/switchwall.sh # [hidden] Change wallpaper (fallback) bindd = Ctrl+Super, T, Change wallpaper, exec, qs -c $qsConfig ipc call TEST_ALIVE || ~/.config/quickshell/$qsConfig/scripts/colors/switchwall.sh # [hidden] Change wallpaper (fallback)
bind = Ctrl+Super, R, exec, killall ags agsv1 gjs ydotool qs quickshell; qs -c $qsConfig & # Restart widgets bind = Ctrl+Super, R, exec, killall ags agsv1 gjs ydotool qs quickshell; qs -c $qsConfig & # Restart widgets
bind = Super+Alt, W, global, quickshell:panelFamilyCycle # Cycle panel family bind = Ctrl+Super, P, global, quickshell:panelFamilyCycle # Cycle panel family
##! Utilities ##! Utilities
# Screenshot, Record, OCR, Color picker, Clipboard history # Screenshot, Record, OCR, Color picker, Clipboard history
@@ -109,8 +109,8 @@ bind = Super+Shift+Alt, Q, exec, hyprctl kill # Forcefully zap a window
# Window split ratio # Window split ratio
#/# binde = Super, ;/',, # Adjust split ratio #/# binde = Super, ;/',, # Adjust split ratio
binde = Super, Semicolon, splitratio, -0.1 # [hidden] binde = Super, Semicolon, layoutmsg, splitratio -0.1 # [hidden]
binde = Super, Apostrophe, splitratio, +0.1 # [hidden] binde = Super, Apostrophe, layoutmsg, splitratio +0.1 # [hidden]
# Positioning mode # Positioning mode
bind = Super+Alt, Space, togglefloating, # Float/Tile bind = Super+Alt, Space, togglefloating, # Float/Tile
bind = Super, D, fullscreen, 1 # Maximize bind = Super, D, fullscreen, 1 # Maximize
@@ -230,10 +230,8 @@ bindd = Ctrl+Shift+Alt+Super, Delete, Shutdown, exec, systemctl poweroff || logi
##! Screen ##! Screen
# Zoom # Zoom
binde = Super, Minus, exec, qs -c $qsConfig ipc call zoom zoomOut # Zoom out binde = Super, Minus, exec, ~/.config/hypr/hyprland/scripts/zoom.sh decrease 0.3 # Zoom out
binde = Super, Equal, exec, qs -c $qsConfig ipc call zoom zoomIn # Zoom in binde = Super, Equal, exec, ~/.config/hypr/hyprland/scripts/zoom.sh increase 0.3 # Zoom in
binde = Super, Minus, exec, qs -c $qsConfig ipc call TEST_ALIVE || ~/.config/hypr/hyprland/scripts/zoom.sh decrease 0.1 # [hidden] Zoom out
binde = Super, Equal, exec, qs -c $qsConfig ipc call TEST_ALIVE || ~/.config/hypr/hyprland/scripts/zoom.sh increase 0.1 # [hidden] Zoom in
# Zoom with keypad # Zoom with keypad
binde = Super, code:82, exec, qs -c $qsConfig ipc call zoom zoomOut # [hidden] Zoom out binde = Super, code:82, exec, qs -c $qsConfig ipc call zoom zoomOut # [hidden] Zoom out
binde = Super, code:86, exec, qs -c $qsConfig ipc call zoom zoomIn # [hidden] Zoom in binde = Super, code:86, exec, qs -c $qsConfig ipc call zoom zoomIn # [hidden] Zoom in
@@ -253,11 +251,11 @@ bindl= ,XF86AudioPause, exec, playerctl play-pause # [hidden]
##! Apps ##! 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, 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 = 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 = 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, 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, 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 = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "antigravity" "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 = 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 = 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 = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer
+135 -132
View File
@@ -1,165 +1,168 @@
# ######## Window rules ######## # ######## Window rules ########
# Disable blur for xwayland context menus # Disable blur for xwayland context menus
windowrulev2 = noblur,class:^()$,title:^()$ windowrule = match:class ^()$, match:title ^()$, no_blur on
# Disable blur for every window # Disable blur for every window
windowrulev2 = noblur, class:.* windowrule = match:class .*, no_blur on
# Floating # Floating
windowrulev2 = center, title:^(Open File)(.*)$ windowrule = match:title ^(Open File)(.*)$, center on
windowrulev2 = float, title:^(Open File)(.*)$ windowrule = match:title ^(Open File)(.*)$, float on
windowrulev2 = center, title:^(Select a File)(.*)$ windowrule = match:title ^(Select a File)(.*)$, center on
windowrulev2 = float, title:^(Select a File)(.*)$ windowrule = match:title ^(Select a File)(.*)$, float on
windowrulev2 = center, title:^(Choose wallpaper)(.*)$ windowrule = match:title ^(Choose wallpaper)(.*)$, center on
windowrulev2 = float, title:^(Choose wallpaper)(.*)$ windowrule = match:title ^(Choose wallpaper)(.*)$, float on
windowrulev2 = size 60% 65%, title:^(Choose wallpaper)(.*)$ windowrule = match:title ^(Choose wallpaper)(.*)$, size (monitor_w*.60) (monitor_h*.65)
windowrulev2 = center, title:^(Open Folder)(.*)$ windowrule = match:title ^(Open Folder)(.*)$, center on
windowrulev2 = float, title:^(Open Folder)(.*)$ windowrule = match:title ^(Open Folder)(.*)$, float on
windowrulev2 = center, title:^(Save As)(.*)$ windowrule = match:title ^(Save As)(.*)$, center on
windowrulev2 = float, title:^(Save As)(.*)$ windowrule = match:title ^(Save As)(.*)$, float on
windowrulev2 = center, title:^(Library)(.*)$ windowrule = match:title ^(Library)(.*)$, center on
windowrulev2 = float, title:^(Library)(.*)$ windowrule = match:title ^(Library)(.*)$, float on
windowrulev2 = center, title:^(File Upload)(.*)$ windowrule = match:title ^(File Upload)(.*)$, center on
windowrulev2 = float, title:^(File Upload)(.*)$ windowrule = match:title ^(File Upload)(.*)$, float on
windowrulev2 = center, title:^(.*)(wants to save)$ windowrule = match:title ^(.*)(wants to save)$, center on
windowrulev2 = float, title:^(.*)(wants to save)$ windowrule = match:title ^(.*)(wants to save)$, float on
windowrulev2 = center, title:^(.*)(wants to open)$ windowrule = match:title ^(.*)(wants to open)$, center on
windowrulev2 = float, title:^(.*)(wants to open)$ windowrule = match:title ^(.*)(wants to open)$, float on
windowrulev2 = float, class:^(blueberry\.py)$ windowrule = match:class ^(blueberry\.py)$, float on
windowrulev2 = float, class:^(guifetch)$ # FlafyDev/guifetch windowrule = match:class ^(guifetch)$ , float on # FlafyDev/guifetch
windowrulev2 = float, class:^(pavucontrol)$ windowrule = match:class ^(pavucontrol)$, float on
windowrulev2 = size 45%, class:^(pavucontrol)$ windowrule = match:class ^(pavucontrol)$, size (monitor_w*.45) (monitor_h*.45)
windowrulev2 = center, class:^(pavucontrol)$ windowrule = match:class ^(pavucontrol)$, center on
windowrulev2 = float, class:^(org.pulseaudio.pavucontrol)$ windowrule = match:class ^(org.pulseaudio.pavucontrol)$, float on
windowrulev2 = size 45%, class:^(org.pulseaudio.pavucontrol)$ windowrule = match:class ^(org.pulseaudio.pavucontrol)$, size (monitor_w*.45) (monitor_h*.45)
windowrulev2 = center, class:^(org.pulseaudio.pavucontrol)$ windowrule = match:class ^(org.pulseaudio.pavucontrol)$, center on
windowrulev2 = float, class:^(nm-connection-editor)$ windowrule = match:class ^(nm-connection-editor)$, float on
windowrulev2 = size 45%, class:^(nm-connection-editor)$ windowrule = match:class ^(nm-connection-editor)$, size (monitor_w*.45) (monitor_h*.45)
windowrulev2 = center, class:^(nm-connection-editor)$ windowrule = match:class ^(nm-connection-editor)$, center on
windowrulev2 = float, class:.*plasmawindowed.* windowrule = match:class .*plasmawindowed.*, float on
windowrulev2 = float, class:kcm_.* windowrule = match:class kcm_.*, float on
windowrulev2 = float, class:.*bluedevilwizard windowrule = match:class .*bluedevilwizard, float on
windowrulev2 = float, title:.*Welcome windowrule = match:title .*Welcome, float on
windowrulev2 = float, title:^(illogical-impulse Settings)$ windowrule = match:title ^(illogical-impulse Settings)$, float on
windowrulev2 = float, title:.*Shell conflicts.* windowrule = match:title .*Shell conflicts.*, float on
windowrulev2 = float, class:org.freedesktop.impl.portal.desktop.kde windowrule = match:class org.freedesktop.impl.portal.desktop.kde, float on
windowrulev2 = size 60% 65%, class:org.freedesktop.impl.portal.desktop.kde windowrule = match:class org.freedesktop.impl.portal.desktop.kde, size (monitor_w*.60) (monitor_h*.65)
windowrulev2 = float, class:^(Zotero)$ windowrule = match:class ^(Zotero)$, float on
windowrulev2 = size 45%, class:^(Zotero)$ windowrule = match:class ^(Zotero)$, size (monitor_w*.45) (monitor_h*.45)
# Move # Move
# kde-material-you-colors spawns a window when changing dark/light theme. This is to make sure it doesn't interfere at all. # kde-material-you-colors spawns a window when changing dark/light theme. This is to make sure it doesn't interfere at all.
windowrulev2 = float, class:^(plasma-changeicons)$ windowrule = match:class ^(plasma-changeicons)$, float on
windowrulev2 = noinitialfocus, class:^(plasma-changeicons)$ windowrule = match:class ^(plasma-changeicons)$, no_initial_focus on
windowrulev2 = move 999999 999999, class:^(plasma-changeicons)$ windowrule = match:class ^(plasma-changeicons)$, move 999999 999999
# stupid dolphin copy # stupid dolphin copy
windowrulev2 = move 40 80, title:^(Copying — Dolphin)$ windowrule = match:title ^(Copying — Dolphin)$, move 40 80
# Tiling # Tiling
windowrulev2 = tile, class:^dev\.warp\.Warp$ windowrule = match:class ^dev\.warp\.Warp$, tile on
# Picture-in-Picture # Picture-in-Picture
windowrulev2 = float, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ windowrule = match:title ^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$, float on
windowrulev2 = keepaspectratio, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ windowrule = match:title ^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$, keep_aspect_ratio on
windowrulev2 = move 73% 72%, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ windowrule = match:title ^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$, move (monitor_w*.73) (monitor_h*.72)
windowrulev2 = size 25%, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ windowrule = match:title ^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$, size (monitor_w*.25) (monitor_h*.25)
windowrulev2 = float, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ windowrule = match:title ^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$, float on
windowrulev2 = pin, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ windowrule = match:title ^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$, pin on
# --- Tearing --- # --- Tearing ---
windowrulev2 = immediate, title:.*\.exe windowrule = match:title .*\.exe, immediate on
windowrulev2 = immediate, title:.*minecraft.* windowrule = match:title .*minecraft.*, immediate on
windowrulev2 = immediate, class:^(steam_app).* windowrule = match:class ^(steam_app).*, immediate on
# Fix Jetbrain IDEs focus/rerendering problem # Fix Jetbrain IDEs focus/rerendering problem
windowrulev2=noinitialfocus,class:^jetbrains-.*$,floating:1,title:^$|^\s$|^win\d+$ windowrule = match:class ^jetbrains-.*$, match:float 1, match:title ^$|^\s$|^win\d+$, no_initial_focus on
# No shadow for tiled windows (matches windows that are not floating). # No shadow for tiled windows (matches windows that are not floating).
windowrulev2 = noshadow, floating:0 windowrule = match:float 0, no_shadow on
# ######## Workspace rules ######## # ######## Workspace rules ########
workspace = special:special, gapsout:30 workspace = special:special, gapsout:30
# ######## Layer rules ######## # ######## Layer rules ########
layerrule = xray 1, .* layerrule = match:namespace .*, xray on
# layerrule = noanim, .* # layerrule = match:namespace .*, no_anim on
layerrule = noanim, walker layerrule = match:namespace walker, no_anim on
layerrule = noanim, selection layerrule = match:namespace selection, no_anim on
layerrule = noanim, overview layerrule = match:namespace overview, no_anim on
layerrule = noanim, anyrun layerrule = match:namespace anyrun, no_anim on
layerrule = noanim, indicator.* layerrule = match:namespace indicator.*, no_anim on
layerrule = noanim, osk layerrule = match:namespace osk, no_anim on
layerrule = noanim, hyprpicker layerrule = match:namespace hyprpicker, no_anim on
layerrule = noanim, noanim layerrule = match:namespace noanim, no_anim on
layerrule = blur, gtk-layer-shell layerrule = match:namespace gtk-layer-shell, blur on
layerrule = ignorezero, gtk-layer-shell layerrule = match:namespace gtk-layer-shell, ignore_alpha 0
layerrule = blur, launcher layerrule = match:namespace launcher, blur on
layerrule = ignorealpha 0.5, launcher layerrule = match:namespace launcher, ignore_alpha 0.5
layerrule = blur, notifications layerrule = match:namespace notifications, blur on
layerrule = ignorealpha 0.69, notifications layerrule = match:namespace notifications, ignore_alpha 0.69
layerrule = blur, logout_dialog # wlogout layerrule = match:namespace logout_dialog # wlogout, blur on
# ags # ags
layerrule = animation slide left, sideleft.* layerrule = match:namespace sideleft.*, animation slide left
layerrule = animation slide right, sideright.* layerrule = match:namespace sideright.*, animation slide right
layerrule = blur, session[0-9]* layerrule = match:namespace session[0-9]*, blur on
layerrule = blur, bar[0-9]* layerrule = match:namespace bar[0-9]*, blur on
layerrule = ignorealpha 0.6, bar[0-9]* layerrule = match:namespace bar[0-9]*, ignore_alpha 0.6
layerrule = blur, barcorner.* layerrule = match:namespace barcorner.*, blur on
layerrule = ignorealpha 0.6, barcorner.* layerrule = match:namespace barcorner.*, ignore_alpha 0.6
layerrule = blur, dock[0-9]* layerrule = match:namespace dock[0-9]*, blur on
layerrule = ignorealpha 0.6, dock[0-9]* layerrule = match:namespace dock[0-9]*, ignore_alpha 0.6
layerrule = blur, indicator.* layerrule = match:namespace indicator.*, blur on
layerrule = ignorealpha 0.6, indicator.* layerrule = match:namespace indicator.*, ignore_alpha 0.6
layerrule = blur, overview[0-9]* layerrule = match:namespace overview[0-9]*, blur on
layerrule = ignorealpha 0.6, overview[0-9]* layerrule = match:namespace overview[0-9]*, ignore_alpha 0.6
layerrule = blur, cheatsheet[0-9]* layerrule = match:namespace cheatsheet[0-9]*, blur on
layerrule = ignorealpha 0.6, cheatsheet[0-9]* layerrule = match:namespace cheatsheet[0-9]*, ignore_alpha 0.6
layerrule = blur, sideright[0-9]* layerrule = match:namespace sideright[0-9]*, blur on
layerrule = ignorealpha 0.6, sideright[0-9]* layerrule = match:namespace sideright[0-9]*, ignore_alpha 0.6
layerrule = blur, sideleft[0-9]* layerrule = match:namespace sideleft[0-9]*, blur on
layerrule = ignorealpha 0.6, sideleft[0-9]* layerrule = match:namespace sideleft[0-9]*, ignore_alpha 0.6
layerrule = blur, indicator.* layerrule = match:namespace indicator.*, blur on
layerrule = ignorealpha 0.6, indicator.* layerrule = match:namespace indicator.*, ignore_alpha 0.6
layerrule = blur, osk[0-9]* layerrule = match:namespace osk[0-9]*, blur on
layerrule = ignorealpha 0.6, osk[0-9]* layerrule = match:namespace osk[0-9]*, ignore_alpha 0.6
# Quickshell # Quickshell
layerrule = blurpopups, quickshell:.* # Quickshell: illogical-impulse
layerrule = blur, quickshell:.* layerrule = match:namespace quickshell:.*, blur_popups on
layerrule = ignorealpha 0.79, quickshell:.* layerrule = match:namespace quickshell:.*, blur on
layerrule = animation slide, quickshell:bar layerrule = match:namespace quickshell:.*, ignore_alpha 0.79
layerrule = noanim, quickshell:actionCenter layerrule = match:namespace quickshell:bar, animation slide
layerrule = animation slide bottom, quickshell:cheatsheet layerrule = match:namespace quickshell:actionCenter, no_anim on
layerrule = animation slide bottom, quickshell:dock layerrule = match:namespace quickshell:cheatsheet, animation slide bottom
layerrule = animation popin 120%, quickshell:screenCorners layerrule = match:namespace quickshell:dock, animation slide bottom
layerrule = noanim, quickshell:lockWindowPusher layerrule = match:namespace quickshell:screenCorners, animation popin 120%
layerrule = animation fade, quickshell:notificationPopup layerrule = match:namespace quickshell:lockWindowPusher, no_anim on
layerrule = noanim, quickshell:overlay layerrule = match:namespace quickshell:notificationPopup, animation fade
layerrule = ignorealpha 1, quickshell:overlay layerrule = match:namespace quickshell:overlay, no_anim on
layerrule = noanim, quickshell:overview layerrule = match:namespace quickshell:overlay, ignore_alpha 1
layerrule = animation slide bottom, quickshell:osk layerrule = match:namespace quickshell:overview, no_anim on
layerrule = noanim, quickshell:polkit layerrule = match:namespace quickshell:osk, animation slide bottom
layerrule = xray 0, quickshell:popup # No weird color for bar tooltips (this in theory should suffice) layerrule = match:namespace quickshell:polkit, no_anim on
layerrule = ignorealpha 1, quickshell:popup # No weird color for bar tooltips (but somehow this is necessary) layerrule = match:namespace quickshell:popup, xray off # No weird color for bar tooltips (this in theory should suffice)
layerrule = ignorealpha 1, quickshell:mediaControls # Same as above layerrule = match:namespace quickshell:popup, ignore_alpha 1 # No weird color for bar tooltips (but somehow this is necessary)
layerrule = animation slide, quickshell:reloadPopup layerrule = match:namespace quickshell:mediaControls, ignore_alpha 1 # Same as above
layerrule = noanim, quickshell:regionSelector layerrule = match:namespace quickshell:reloadPopup, animation slide
layerrule = noanim, quickshell:screenshot layerrule = match:namespace quickshell:regionSelector, no_anim on
layerrule = blur, quickshell:session layerrule = match:namespace quickshell:screenshot, no_anim on
layerrule = noanim, quickshell:session layerrule = match:namespace quickshell:session, blur on
layerrule = ignorealpha 0, quickshell:session layerrule = match:namespace quickshell:session, no_anim on
layerrule = animation slide right, quickshell:sidebarRight layerrule = match:namespace quickshell:session, ignore_alpha 0
layerrule = animation slide left, quickshell:sidebarLeft layerrule = match:namespace quickshell:sidebarRight, animation slide right
layerrule = animation slide, quickshell:verticalBar layerrule = match:namespace quickshell:sidebarLeft, animation slide left
layerrule = animation slide top, quickshell:wallpaperSelector layerrule = match:namespace quickshell:verticalBar, animation slide
layerrule = noanim, quickshell:wNotificationCenter layerrule = match:namespace quickshell:osk, order -1
layerrule = noanim, quickshell:wOnScreenDisplay # Quickshell: waffles
layerrule = noanim, quickshell:wStartMenu layerrule = match:namespace quickshell:wallpaperSelector, animation slide top
layerrule = ignorealpha 0, quickshell:wTaskView layerrule = match:namespace quickshell:wNotificationCenter, no_anim on
layerrule = noanim, quickshell:wTaskView layerrule = match:namespace quickshell:wOnScreenDisplay, no_anim on
layerrule = match:namespace quickshell:wStartMenu, no_anim on
layerrule = match:namespace quickshell:wTaskView, ignore_alpha 0
layerrule = match:namespace quickshell:wTaskView, no_anim on
# Launchers need to be FAST # Launchers need to be FAST
layerrule = noanim, gtk4-layer-shell layerrule = match:namespace gtk4-layer-shell, no_anim on
+28 -12
View File
@@ -1,22 +1,38 @@
/* /*
* GTK Colors * GTK colors generated with Matugen
* Generated with Matugen * The source template is here: ~/.config/matugen/templates/gtk-3.0/gtk.css
*/ */
/* Accents */
@define-color accent_color {{colors.primary.default.hex}}; @define-color accent_color {{colors.primary.default.hex}};
@define-color accent_fg_color {{colors.on_primary.default.hex}}; @define-color accent_fg_color {{colors.on_primary.default.hex}};
@define-color accent_bg_color {{colors.primary.default.hex}}; @define-color accent_bg_color {{colors.primary.default.hex}};
@define-color destructive_bg_color {{colors.error_container.default.hex}};
@define-color destructive_fg_color {{colors.on_error_container.default.hex}};
@define-color destructive_color {{colors.error.default.hex}};
@define-color success_bg_color #374B3E;
@define-color success_fg_color #D1E9D6;
@define-color success_color #B5CCBA;
/* Base surfaces */
@define-color window_bg_color {{colors.background.default.hex}}; @define-color window_bg_color {{colors.background.default.hex}};
@define-color window_fg_color {{colors.on_background.default.hex}}; @define-color window_fg_color {{colors.on_background.default.hex}};
@define-color headerbar_bg_color {{colors.surface_dim.default.hex}}; @define-color headerbar_bg_color {{colors.surface_container.default.hex}};
@define-color headerbar_backdrop_color {{colors.surface_container.default.hex}};
@define-color headerbar_fg_color {{colors.on_surface.default.hex}}; @define-color headerbar_fg_color {{colors.on_surface.default.hex}};
@define-color popover_bg_color {{colors.surface_dim.default.hex}}; @define-color card_bg_color {{colors.surface_container.default.hex}};
@define-color popover_fg_color {{colors.on_surface.default.hex}};
@define-color view_bg_color {{colors.surface.default.hex}};
@define-color view_fg_color {{colors.on_surface.default.hex}};
@define-color card_bg_color {{colors.surface.default.hex}};
@define-color card_fg_color {{colors.on_surface.default.hex}}; @define-color card_fg_color {{colors.on_surface.default.hex}};
@define-color sidebar_bg_color @window_bg_color; @define-color sidebar_bg_color {{colors.surface_container.default.hex}};
@define-color sidebar_fg_color @window_fg_color; @define-color sidebar_fg_color {{colors.on_surface.default.hex}};
@define-color sidebar_border_color @window_bg_color; @define-color secondary_sidebar_bg_color {{colors.surface_container_low.default.hex}};
@define-color sidebar_backdrop_color @window_bg_color; @define-color secondary_sidebar_fg_color {{colors.on_surface.default.hex}};
@define-color sidebar_border_color @sidebar_bg_color;
@define-color sidebar_backdrop_color @sidebar_bg_color;
@define-color view_bg_color {{colors.surface_container_lowest.default.hex}};
@define-color view_fg_color {{colors.on_surface.default.hex}};
@define-color overview_bg_color {{colors.surface_container_lowest.default.hex}};
@define-color overview_fg_color {{colors.on_surface.default.hex}};
/* Popups */
@define-color popover_bg_color {{colors.surface_container_highest.default.hex}};
@define-color popover_fg_color {{colors.on_surface.default.hex}};
@define-color dialog_bg_color {{colors.surface_container_high.default.hex}};
@define-color dialog_fg_color {{colors.on_surface.default.hex}};
+61 -22
View File
@@ -1,44 +1,83 @@
/* /*
* GTK Colors * GTK colors generated with Matugen
* Generated with Matugen * The source template is here: ~/.config/matugen/templates/gtk-4.0/gtk.css
*/ */
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
/* Accents */
@define-color accent_color {{colors.primary.light.hex}}; @define-color accent_color {{colors.primary.light.hex}};
@define-color accent_fg_color {{colors.on_primary.light.hex}}; @define-color accent_fg_color {{colors.on_primary.light.hex}};
@define-color accent_bg_color {{colors.primary.light.hex}}; @define-color accent_bg_color {{colors.primary.light.hex}};
@define-color destructive_bg_color {{colors.error_container.light.hex}};
@define-color destructive_fg_color {{colors.on_error_container.light.hex}};
@define-color destructive_color {{colors.error.light.hex}};
@define-color success_bg_color #B5CCBA;
@define-color success_fg_color #213528;
@define-color success_color #374B3E;
/* Base surfaces */
@define-color window_bg_color {{colors.background.light.hex}}; @define-color window_bg_color {{colors.background.light.hex}};
@define-color window_fg_color {{colors.on_background.light.hex}}; @define-color window_fg_color {{colors.on_background.light.hex}};
@define-color headerbar_bg_color {{colors.surface_dim.light.hex}}; @define-color headerbar_bg_color {{colors.surface_container.light.hex}};
@define-color headerbar_backdrop_color {{colors.surface_container.light.hex}};
@define-color headerbar_fg_color {{colors.on_surface.light.hex}}; @define-color headerbar_fg_color {{colors.on_surface.light.hex}};
@define-color popover_bg_color {{colors.surface_dim.light.hex}}; @define-color card_bg_color {{colors.surface_container.light.hex}};
@define-color popover_fg_color {{colors.on_surface.light.hex}};
@define-color view_bg_color {{colors.surface.light.hex}};
@define-color view_fg_color {{colors.on_surface.light.hex}};
@define-color card_bg_color {{colors.surface.light.hex}};
@define-color card_fg_color {{colors.on_surface.light.hex}}; @define-color card_fg_color {{colors.on_surface.light.hex}};
@define-color sidebar_bg_color @window_bg_color; @define-color sidebar_bg_color {{colors.surface_container.light.hex}};
@define-color sidebar_fg_color @window_fg_color; @define-color sidebar_fg_color {{colors.on_surface.light.hex}};
@define-color sidebar_border_color @window_bg_color; @define-color secondary_sidebar_bg_color {{colors.surface_container_low.light.hex}};
@define-color sidebar_backdrop_color @window_bg_color; @define-color secondary_sidebar_backdrop_color {{colors.surface_container_low.light.hex}};
@define-color secondary_sidebar_fg_color {{colors.on_surface.light.hex}};
@define-color sidebar_border_color @sidebar_bg_color;
@define-color sidebar_backdrop_color @sidebar_bg_color;
@define-color view_bg_color {{colors.surface_container_lowest.light.hex}};
@define-color view_fg_color {{colors.on_surface.light.hex}};
@define-color overview_bg_color {{colors.surface_container_lowest.light.hex}};
@define-color overview_fg_color {{colors.on_surface.light.hex}};
/* Popups */
@define-color popover_bg_color {{colors.surface_container_highest.light.hex}};
@define-color popover_fg_color {{colors.on_surface.light.hex}};
@define-color dialog_bg_color {{colors.surface_container_high.light.hex}};
@define-color dialog_fg_color {{colors.on_surface.light.hex}};
@define-color thumbnail_bg_color {{colors.surface_container_high.light.hex}};
@define-color thumbnail_fg_color {{colors.on_surface.light.hex}};
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
/* Accents */
@define-color accent_color {{colors.primary.dark.hex}}; @define-color accent_color {{colors.primary.dark.hex}};
@define-color accent_fg_color {{colors.on_primary.dark.hex}}; @define-color accent_fg_color {{colors.on_primary.dark.hex}};
@define-color accent_bg_color {{colors.primary.dark.hex}}; @define-color accent_bg_color {{colors.primary.dark.hex}};
@define-color destructive_bg_color {{colors.error_container.dark.hex}};
@define-color destructive_fg_color {{colors.on_error_container.dark.hex}};
@define-color destructive_color {{colors.error.dark.hex}};
@define-color success_bg_color #374B3E;
@define-color success_fg_color #D1E9D6;
@define-color success_color #B5CCBA;
/* Base surfaces */
@define-color window_bg_color {{colors.background.dark.hex}}; @define-color window_bg_color {{colors.background.dark.hex}};
@define-color window_fg_color {{colors.on_background.dark.hex}}; @define-color window_fg_color {{colors.on_background.dark.hex}};
@define-color headerbar_bg_color {{colors.surface_dim.dark.hex}}; @define-color headerbar_bg_color {{colors.surface_container.dark.hex}};
@define-color headerbar_backdrop_color {{colors.surface_container.dark.hex}};
@define-color headerbar_fg_color {{colors.on_surface.dark.hex}}; @define-color headerbar_fg_color {{colors.on_surface.dark.hex}};
@define-color popover_bg_color {{colors.surface_dim.dark.hex}}; @define-color card_bg_color {{colors.surface_container.dark.hex}};
@define-color popover_fg_color {{colors.on_surface.dark.hex}};
@define-color view_bg_color {{colors.surface.dark.hex}};
@define-color view_fg_color {{colors.on_surface.dark.hex}};
@define-color card_bg_color {{colors.surface.dark.hex}};
@define-color card_fg_color {{colors.on_surface.dark.hex}}; @define-color card_fg_color {{colors.on_surface.dark.hex}};
@define-color sidebar_bg_color @window_bg_color; @define-color sidebar_bg_color {{colors.surface_container.dark.hex}};
@define-color sidebar_fg_color @window_fg_color; @define-color sidebar_fg_color {{colors.on_surface.dark.hex}};
@define-color sidebar_border_color @window_bg_color; @define-color secondary_sidebar_bg_color {{colors.surface_container_low.dark.hex}};
@define-color sidebar_backdrop_color @window_bg_color; @define-color secondary_sidebar_backdrop_color {{colors.surface_container_low.dark.hex}};
@define-color secondary_sidebar_fg_color {{colors.on_surface.dark.hex}};
@define-color sidebar_border_color @sidebar_bg_color;
@define-color sidebar_backdrop_color @sidebar_bg_color;
@define-color view_bg_color {{colors.surface_container_lowest.dark.hex}};
@define-color view_fg_color {{colors.on_surface.dark.hex}};
@define-color overview_bg_color {{colors.surface_container_lowest.dark.hex}};
@define-color overview_fg_color {{colors.on_surface.dark.hex}};
/* Popups */
@define-color popover_bg_color {{colors.surface_container_highest.dark.hex}};
@define-color popover_fg_color {{colors.on_surface.dark.hex}};
@define-color dialog_bg_color {{colors.surface_container_high.dark.hex}};
@define-color dialog_fg_color {{colors.on_surface.dark.hex}};
@define-color thumbnail_bg_color {{colors.surface_container_high.dark.hex}};
@define-color thumbnail_fg_color {{colors.on_surface.dark.hex}};
} }
@@ -1,6 +1,6 @@
general { general {
col.active_border = rgba({{colors.outline.default.hex_stripped}}AA) col.active_border = rgba({{colors.outline.default.hex_stripped}}77)
col.inactive_border = rgba({{colors.outline_variant.default.hex_stripped}}AA) col.inactive_border = rgba({{colors.outline_variant.default.hex_stripped}}55)
} }
misc { misc {
@@ -29,4 +29,4 @@ plugin {
} }
} }
windowrulev2 = bordercolor rgba({{colors.primary.default.hex_stripped}}AA) rgba({{colors.primary.default.hex_stripped}}77),pinned:1 windowrule = border_color rgba({{colors.primary.default.hex_stripped}}AA) rgba({{colors.primary.default.hex_stripped}}77), match:pin 1
@@ -37,14 +37,6 @@ Singleton {
} }
} }
property real screenZoom: 1
onScreenZoomChanged: {
Quickshell.execDetached(["hyprctl", "keyword", "cursor:zoom_factor", root.screenZoom.toString()]);
}
Behavior on screenZoom {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
GlobalShortcut { GlobalShortcut {
name: "workspaceNumber" name: "workspaceNumber"
description: "Hold to show workspace numbers, release to show icons" description: "Hold to show workspace numbers, release to show icons"
@@ -56,16 +48,4 @@ Singleton {
root.superDown = false root.superDown = false
} }
} }
IpcHandler {
target: "zoom"
function zoomIn() {
screenZoom = Math.min(screenZoom + 0.4, 3.0)
}
function zoomOut() {
screenZoom = Math.max(screenZoom - 0.4, 1)
}
}
} }
@@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#000000">
<path d="M17.5 12C20.5376 12 23 14.4624 23 17.5C23 20.5376 20.5376 23 17.5 23C14.4624 23 12 20.5376 12 17.5C12 14.4624 14.4624 12 17.5 12ZM21 8.5L21.0012 12.0226C19.9907 11.3753 18.7892 11 17.5 11C13.9101 11 11 13.9101 11 17.5C11 18.7892 11.3753 19.9907 12.0226 21.0012L6.25 21C4.45507 21 3 19.5449 3 17.75V8.5H21ZM17.5 14L17.4101 14.0081C17.206 14.0451 17.0451 14.206 17.0081 14.4101L17 14.5V17H14.5L14.4101 17.0081C14.206 17.0451 14.0451 17.206 14.0081 17.4101L14 17.5L14.0081 17.5899C14.0451 17.794 14.206 17.9549 14.4101 17.9919L14.5 18H17V20.5L17.0081 20.5899C17.0451 20.794 17.206 20.9549 17.4101 20.9919L17.5 21L17.5899 20.9919C17.794 20.9549 17.9549 20.794 17.9919 20.5899L18 20.5V18H20.5L20.5899 17.9919C20.794 17.9549 20.9549 17.794 20.9919 17.5899L21 17.5L20.9919 17.4101C20.9549 17.206 20.794 17.0451 20.5899 17.0081L20.5 17H18V14.5L17.9919 14.4101C17.9549 14.206 17.794 14.0451 17.5899 14.0081L17.5 14ZM17.75 3C19.5449 3 21 4.45507 21 6.25V7H3V6.25C3 4.45507 4.45507 3 6.25 3H17.75Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#000000">
<path d="M17.5 12C20.5376 12 23 14.4624 23 17.5C23 20.5376 20.5376 23 17.5 23C14.4624 23 12 20.5376 12 17.5C12 14.4624 14.4624 12 17.5 12ZM17.75 3C19.5449 3 21 4.45507 21 6.25L21.0012 12.0226C20.5378 11.7258 20.0342 11.4861 19.5004 11.3136L19.5 8.5H4.5V17.75C4.5 18.7165 5.2835 19.5 6.25 19.5L11.3136 19.5004C11.4861 20.0342 11.7258 20.5378 12.0226 21.0012L6.25 21C4.45507 21 3 19.5449 3 17.75V6.25C3 4.45507 4.45507 3 6.25 3H17.75ZM17.5 14L17.4101 14.0081C17.206 14.0451 17.0451 14.206 17.0081 14.4101L17 14.5V17H14.5L14.4101 17.0081C14.206 17.0451 14.0451 17.206 14.0081 17.4101L14 17.5L14.0081 17.5899C14.0451 17.794 14.206 17.9549 14.4101 17.9919L14.5 18H17V20.5L17.0081 20.5899C17.0451 20.794 17.206 20.9549 17.4101 20.9919L17.5 21L17.5899 20.9919C17.794 20.9549 17.9549 20.794 17.9919 20.5899L18 20.5V18H20.5L20.5899 17.9919C20.794 17.9549 20.9549 17.794 20.9919 17.5899L21 17.5L20.9919 17.4101C20.9549 17.206 20.794 17.0451 20.5899 17.0081L20.5 17H18V14.5L17.9919 14.4101C17.9549 14.206 17.794 14.0451 17.5899 14.0081L17.5 14ZM17.75 4.5H6.25C5.2835 4.5 4.5 5.2835 4.5 6.25V7H19.5V6.25C19.5 5.2835 18.7165 4.5 17.75 4.5Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1 @@
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13.925 2.503a2.25 2.25 0 0 1 1.94 1.11L16.679 5h2.071A3.25 3.25 0 0 1 22 8.25v9.5A3.25 3.25 0 0 1 18.75 21H5.25A3.25 3.25 0 0 1 2 17.75v-9.5A3.25 3.25 0 0 1 5.25 5h2.08l.875-1.424a2.25 2.25 0 0 1 1.917-1.073h3.803ZM12 8a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9Zm0 1.5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z" fill="#212121"/></svg>

After

Width:  |  Height:  |  Size: 420 B

@@ -0,0 +1 @@
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13.925 2.503a2.25 2.25 0 0 1 1.94 1.11L16.679 5h2.071A3.25 3.25 0 0 1 22 8.25v9.5A3.25 3.25 0 0 1 18.75 21H5.25A3.25 3.25 0 0 1 2 17.75v-9.5A3.25 3.25 0 0 1 5.25 5h2.08l.875-1.424a2.25 2.25 0 0 1 1.917-1.073h3.803Zm0 1.5h-3.803a.75.75 0 0 0-.574.268l-.065.09L8.39 6.141a.75.75 0 0 1-.639.358h-2.5A1.75 1.75 0 0 0 3.5 8.25v9.5c0 .966.784 1.75 1.75 1.75h13.5a1.75 1.75 0 0 0 1.75-1.75v-9.5a1.75 1.75 0 0 0-1.75-1.75h-2.5a.75.75 0 0 1-.647-.37l-1.032-1.757a.75.75 0 0 0-.646-.37ZM12 8a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9Zm0 1.5a3 3 0 1 0 0 6 3 3 0 0 0 0-6Z" fill="#212121"/></svg>

After

Width:  |  Height:  |  Size: 682 B

@@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#000000">
<path d="M7 15.5C7 16.2797 7.59489 16.9204 8.35554 16.9931L8.5 17H21C21.5523 17 22 17.4477 22 18C22 18.5128 21.614 18.9355 21.1166 18.9933L21 19H19V21C19 21.5523 18.5523 22 18 22C17.4872 22 17.0645 21.614 17.0067 21.1166L17 21V19H8.5C6.63144 19 5.10487 17.5357 5.00518 15.692L5 15.5V7H3C2.44772 7 2 6.55228 2 6C2 5.48716 2.38604 5.06449 2.88338 5.00673L3 5H5V3C5 2.44772 5.44772 2 6 2C6.51284 2 6.93551 2.38604 6.99327 2.88338L7 3V15.5ZM8 5H15.5C17.3686 5 18.8951 6.46428 18.9948 8.30796L19 8.5V16H17V8.5C17 7.7203 16.4051 7.07955 15.6445 7.00687L15.5 7H8V5Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 721 B

@@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#000000">
<path d="M21.25 17C21.6642 17 22 17.3358 22 17.75C22 18.1297 21.7178 18.4435 21.3518 18.4932L21.25 18.5H18.5V21.25C18.5 21.6642 18.1642 22 17.75 22C17.3703 22 17.0565 21.7178 17.0068 21.3518L17 21.25V18.5H8.75C7.01697 18.5 5.60075 17.1435 5.50514 15.4344L5.5 15.25L5.499 7H2.75C2.33579 7 2 6.66421 2 6.25C2 5.8703 2.28215 5.55651 2.64823 5.50685L2.75 5.5H5.499L5.5 2.75C5.5 2.33579 5.83579 2 6.25 2C6.6297 2 6.94349 2.28215 6.99315 2.64823L7 2.75L6.999 5.5H7V7H6.999L7 15.25C7 16.1682 7.70711 16.9212 8.60647 16.9942L8.75 17H21.25ZM8 5.5H15.25C16.983 5.5 18.3992 6.85646 18.4949 8.56558L18.5 8.75V16H17V8.75C17 7.83183 16.2929 7.07881 15.3935 7.0058L15.25 7H8V5.5Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 827 B

@@ -0,0 +1 @@
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m11.557 13.646-.083.071-6.927 6.8a3.234 3.234 0 0 0 1.703.481h4.914l.356-1.423c.162-.648.497-1.24.97-1.712l2.11-2.11-2.075-2.036-.094-.078a.75.75 0 0 0-.873.007Zm4.946-5.394a.752.752 0 1 0-1.504 0 .752.752 0 0 0 1.504 0Zm-.843 6.441-2.085-2.046-.128-.117a2.25 2.25 0 0 0-2.888-.006l-.136.123-6.938 6.81A3.234 3.234 0 0 1 3 17.75v-11.5A3.25 3.25 0 0 1 6.25 3h11.499a3.25 3.25 0 0 1 3.25 3.25v4.761a3.279 3.279 0 0 0-2.608.95l-2.731 2.732ZM13.5 8.252a2.252 2.252 0 1 0 4.503 0 2.252 2.252 0 0 0-4.504 0Zm5.598 4.417-5.901 5.901a2.685 2.685 0 0 0-.707 1.248l-.457 1.83c-.2.797.522 1.518 1.318 1.319l1.83-.458a2.685 2.685 0 0 0 1.248-.706L22.33 15.9a2.286 2.286 0 0 0-3.233-3.232Z" fill="#212121"/></svg>

After

Width:  |  Height:  |  Size: 804 B

@@ -0,0 +1 @@
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20.998 6.25A3.25 3.25 0 0 0 17.748 3H6.25A3.25 3.25 0 0 0 3 6.25v11.499a3.25 3.25 0 0 0 3.25 3.25h4.914l.356-1.424.02-.076H6.25c-.204 0-.4-.035-.582-.1l5.807-5.685.083-.07a.75.75 0 0 1 .966.07l2.079 2.036 1.06-1.06-2.09-2.048-.128-.116a2.25 2.25 0 0 0-3.02.116l-5.822 5.7a1.746 1.746 0 0 1-.103-.593v-11.5c0-.966.783-1.75 1.75-1.75h11.499c.966 0 1.75.784 1.75 1.75v4.983c.478-.19.993-.264 1.5-.22V6.25Zm-3.495 2.502a2.252 2.252 0 1 0-4.504 0 2.252 2.252 0 0 0 4.504 0Zm-3.004 0a.752.752 0 1 1 1.504 0 .752.752 0 0 1-1.504 0Zm4.6 3.917-5.902 5.901a2.685 2.685 0 0 0-.707 1.248l-.457 1.83c-.2.797.522 1.518 1.318 1.319l1.83-.458a2.685 2.685 0 0 0 1.248-.706L22.33 15.9a2.286 2.286 0 0 0-3.233-3.232Z" fill="#212121"/></svg>

After

Width:  |  Height:  |  Size: 826 B

@@ -0,0 +1 @@
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M2.747 15a.75.75 0 0 1 .743.648l.007.102v3.502l.007.128a1.25 1.25 0 0 0 1.115 1.116l.128.006h3.5l.102.007a.75.75 0 0 1 0 1.486l-.102.007h-3.5l-.167-.005a2.75 2.75 0 0 1-2.578-2.57l-.005-.175V15.75l.007-.102A.75.75 0 0 1 2.747 15Zm18.5 0a.75.75 0 0 1 .743.648l.007.102v3.502a2.75 2.75 0 0 1-2.582 2.745l-.168.005h-3.5a.75.75 0 0 1-.102-1.493l.102-.007h3.5a1.25 1.25 0 0 0 1.244-1.122l.006-.128V15.75a.75.75 0 0 1 .75-.75ZM12 15a1 1 0 0 1 .117 1.993L12 17H8a1 1 0 0 1-.116-1.993L8 15h4Zm4-4a1 1 0 0 1 .117 1.993L16 13H8a1 1 0 0 1-.116-1.993L8 11h8ZM8.247 2a.75.75 0 0 1 .102 1.493l-.102.007h-3.5a1.25 1.25 0 0 0-1.243 1.122l-.007.128v3.502a.75.75 0 0 1-1.493.102l-.007-.102V4.75A2.75 2.75 0 0 1 4.58 2.005L4.747 2h3.5Zm11 0 .168.005a2.75 2.75 0 0 1 2.577 2.57l.005.175v3.502l-.007.102a.75.75 0 0 1-1.486 0l-.007-.102V4.75l-.006-.128a1.25 1.25 0 0 0-1.116-1.116l-.128-.006h-3.5l-.102-.007a.75.75 0 0 1 0-1.486L15.747 2h3.5ZM16 7a1 1 0 0 1 .117 1.993L16 9H8a1 1 0 0 1-.116-1.993L8 7h8Z" fill="#212121"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1 @@
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M2.747 15a.75.75 0 0 1 .743.648l.007.102v3.502l.007.128a1.25 1.25 0 0 0 1.115 1.116l.128.006h3.5l.102.007a.75.75 0 0 1 0 1.486l-.102.007h-3.5l-.167-.005a2.75 2.75 0 0 1-2.578-2.57l-.005-.175V15.75l.007-.102A.75.75 0 0 1 2.747 15Zm18.5 0a.75.75 0 0 1 .743.648l.007.102v3.502a2.75 2.75 0 0 1-2.582 2.745l-.168.005h-3.5a.75.75 0 0 1-.102-1.493l.102-.007h3.5a1.25 1.25 0 0 0 1.244-1.122l.006-.128V15.75a.75.75 0 0 1 .75-.75Zm-8.992.5a.75.75 0 0 1 .102 1.493l-.102.007H7.75a.75.75 0 0 1-.102-1.493l.102-.007h4.505Zm3.995-4.25a.75.75 0 0 1 .102 1.493l-.102.007h-8.5a.75.75 0 0 1-.102-1.493l.102-.007h8.5ZM8.247 2a.75.75 0 0 1 .102 1.493l-.102.007h-3.5a1.25 1.25 0 0 0-1.243 1.122l-.007.128v3.502a.75.75 0 0 1-1.493.102l-.007-.102V4.75A2.75 2.75 0 0 1 4.58 2.005L4.747 2h3.5Zm11 0 .168.005a2.75 2.75 0 0 1 2.577 2.57l.005.175v3.502l-.007.102a.75.75 0 0 1-1.486 0l-.007-.102V4.75l-.006-.128a1.25 1.25 0 0 0-1.116-1.116l-.128-.006h-3.5l-.102-.007a.75.75 0 0 1 0-1.486L15.747 2h3.5ZM16.25 7a.75.75 0 0 1 .102 1.493l-.102.007h-8.5a.75.75 0 0 1-.102-1.493L7.75 7h8.5Z" fill="#212121"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#000000">
<path d="M3 6.5C3 4.567 4.567 3 6.5 3H9C9.55228 3 10 3.44772 10 4C10 4.55228 9.55228 5 9 5H6.5C5.67157 5 5 5.67157 5 6.5V9C5 9.55229 4.55228 10 4 10C3.44772 10 3 9.55229 3 9V6.5ZM21 17.5C21 19.433 19.433 21 17.5 21H15C14.4477 21 14 20.5523 14 20C14 19.4477 14.4477 19 15 19L17.5 19C18.3284 19 19 18.3284 19 17.5V15C19 14.4477 19.4477 14 20 14C20.5523 14 21 14.4477 21 15V17.5ZM21 6.5C21 4.567 19.433 3 17.5 3H15C14.4477 3 14 3.44772 14 4C14 4.55228 14.4477 5 15 5H17.5C18.3284 5 19 5.67157 19 6.5V9C19 9.55228 19.4477 10 20 10C20.5523 10 21 9.55229 21 9V6.5ZM6.5 21C4.567 21 3 19.433 3 17.5V15C3 14.4477 3.44772 14 4 14C4.55229 14 5 14.4477 5 15L5 17.5C5 18.3284 5.67157 19 6.5 19H9C9.55229 19 10 19.4477 10 20C10 20.5523 9.55228 21 9 21H6.5ZM12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15ZM7.5 8.75C8.19036 8.75 8.75 8.19036 8.75 7.5C8.75 6.80964 8.19036 6.25 7.5 6.25C6.80964 6.25 6.25 6.80964 6.25 7.5C6.25 8.19036 6.80964 8.75 7.5 8.75Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#000000">
<path d="M17.75 3C19.5449 3 21 4.45508 21 6.25V9.25C21 9.66421 20.6642 10 20.25 10C19.8358 10 19.5 9.66421 19.5 9.25V6.25C19.5 5.2835 18.7165 4.5 17.75 4.5L14.75 4.5C14.3358 4.5 14 4.16421 14 3.75C14 3.33579 14.3358 3 14.75 3H17.75ZM6.25 3C4.45507 3 3 4.45507 3 6.25V9.25C3 9.66421 3.33579 10 3.75 10C4.16421 10 4.5 9.66421 4.5 9.25V6.25C4.5 5.2835 5.2835 4.5 6.25 4.5H9.25C9.66421 4.5 10 4.16421 10 3.75C10 3.33579 9.66421 3 9.25 3H6.25ZM17.75 21C19.5449 21 21 19.5449 21 17.75V14.75C21 14.3358 20.6642 14 20.25 14C19.8358 14 19.5 14.3358 19.5 14.75V17.75C19.5 18.7165 18.7165 19.5 17.75 19.5H14.75C14.3358 19.5 14 19.8358 14 20.25C14 20.6642 14.3358 21 14.75 21H17.75ZM3 17.75C3 19.5449 4.45507 21 6.25 21H9.25C9.66421 21 10 20.6642 10 20.25C10 19.8358 9.66421 19.5 9.25 19.5H6.25C5.2835 19.5 4.5 18.7165 4.5 17.75L4.5 14.75C4.5 14.3358 4.16421 14 3.75 14C3.33579 14 3 14.3358 3 14.75L3 17.75ZM12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15ZM12 13.5C11.1716 13.5 10.5 12.8284 10.5 12C10.5 11.1716 11.1716 10.5 12 10.5C12.8284 10.5 13.5 11.1716 13.5 12C13.5 12.8284 12.8284 13.5 12 13.5ZM7.5 8.5C8.05229 8.5 8.5 8.05229 8.5 7.5C8.5 6.94772 8.05229 6.5 7.5 6.5C6.94772 6.5 6.5 6.94772 6.5 7.5C6.5 8.05229 6.94772 8.5 7.5 8.5Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1 @@
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M16 16.25a3.25 3.25 0 0 1-3.25 3.25h-7.5A3.25 3.25 0 0 1 2 16.25v-8.5A3.25 3.25 0 0 1 5.25 4.5h7.5A3.25 3.25 0 0 1 16 7.75v8.5Zm5.762-10.357a1 1 0 0 1 .238.648v10.918a1 1 0 0 1-1.648.762L17 15.37V8.628l3.352-2.849a1 1 0 0 1 1.41.114Z" fill="#212121"/></svg>

After

Width:  |  Height:  |  Size: 361 B

@@ -0,0 +1 @@
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13.75 4.5A3.25 3.25 0 0 1 17 7.75v.173l3.864-2.318A.75.75 0 0 1 22 6.248V17.75a.75.75 0 0 1-1.136.643L17 16.075v.175a3.25 3.25 0 0 1-3.25 3.25h-8.5A3.25 3.25 0 0 1 2 16.25v-8.5A3.25 3.25 0 0 1 5.25 4.5h8.5Zm0 1.5h-8.5A1.75 1.75 0 0 0 3.5 7.75v8.5c0 .966.784 1.75 1.75 1.75h8.5a1.75 1.75 0 0 0 1.75-1.75v-8.5A1.75 1.75 0 0 0 13.75 6Zm6.75 1.573L17 9.674v4.651l3.5 2.1V7.573Z" fill="#212121"/></svg>

After

Width:  |  Height:  |  Size: 502 B

@@ -28,15 +28,11 @@ Singleton {
property real autoBackgroundTransparency: { // y = 0.5768x^2 - 0.759x + 0.2896 property real autoBackgroundTransparency: { // y = 0.5768x^2 - 0.759x + 0.2896
let x = wallpaperVibrancy let x = wallpaperVibrancy
let y = 0.5768 * (x * x) - 0.759 * (x) + 0.2896 let y = 0.5768 * (x * x) - 0.759 * (x) + 0.2896
return Math.max(0, Math.min(0.22, y)) return Math.max(0, Math.min(0.22, y)) - 0.12 * (m3colors.darkmode ? 0 : 1)
}
property real autoContentTransparency: { // y = -10.1734x^2 + 3.4457x + 0.1872
let x = autoBackgroundTransparency
let y = -10.1734 * (x * x) + 3.4457 * (x) + 0.1872
return Math.max(0, Math.min(0.6, y))
} }
property real autoContentTransparency: 0.9
property real backgroundTransparency: Config?.options.appearance.transparency.enable ? Config?.options.appearance.transparency.automatic ? autoBackgroundTransparency : Config?.options.appearance.transparency.backgroundTransparency : 0 property real backgroundTransparency: Config?.options.appearance.transparency.enable ? Config?.options.appearance.transparency.automatic ? autoBackgroundTransparency : Config?.options.appearance.transparency.backgroundTransparency : 0
property real contentTransparency: Config?.options.appearance.transparency.enable ? Config?.options.appearance.transparency.automatic ? autoContentTransparency : Config?.options.appearance.transparency.contentTransparency : 0 property real contentTransparency: Config?.options.appearance.transparency.automatic ? autoContentTransparency : Config?.options.appearance.transparency.contentTransparency
m3colors: QtObject { m3colors: QtObject {
property bool darkmode: true property bool darkmode: true
@@ -114,30 +110,41 @@ Singleton {
colors: QtObject { colors: QtObject {
property color colSubtext: m3colors.m3outline property color colSubtext: m3colors.m3outline
property color colLayer0: ColorUtils.mix(ColorUtils.transparentize(m3colors.m3background, root.backgroundTransparency), m3colors.m3primary, Config.options.appearance.extraBackgroundTint ? 0.99 : 1) // Layer 0
property color colLayer0Base: ColorUtils.mix(m3colors.m3background, m3colors.m3primary, Config.options.appearance.extraBackgroundTint ? 0.99 : 1)
property color colLayer0: ColorUtils.transparentize(colLayer0Base, root.backgroundTransparency)
property color colOnLayer0: m3colors.m3onBackground property color colOnLayer0: m3colors.m3onBackground
property color colLayer0Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.9, root.contentTransparency)) property color colLayer0Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.9, root.contentTransparency))
property color colLayer0Active: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.8, root.contentTransparency)) property color colLayer0Active: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.8, root.contentTransparency))
property color colLayer0Border: ColorUtils.mix(root.m3colors.m3outlineVariant, colLayer0, 0.4) property color colLayer0Border: ColorUtils.mix(root.m3colors.m3outlineVariant, colLayer0, 0.4)
property color colLayer1: ColorUtils.transparentize(m3colors.m3surfaceContainerLow, root.contentTransparency); // Layer 1
property color colLayer1Base: m3colors.m3surfaceContainerLow
property color colLayer1: ColorUtils.solveOverlayColor(colLayer0Base, colLayer1Base, 1 - root.contentTransparency);
property color colOnLayer1: m3colors.m3onSurfaceVariant; property color colOnLayer1: m3colors.m3onSurfaceVariant;
property color colOnLayer1Inactive: ColorUtils.mix(colOnLayer1, colLayer1, 0.45); property color colOnLayer1Inactive: ColorUtils.mix(colOnLayer1, colLayer1, 0.45);
property color colLayer2: ColorUtils.transparentize(m3colors.m3surfaceContainer, root.contentTransparency)
property color colOnLayer2: m3colors.m3onSurface;
property color colOnLayer2Disabled: ColorUtils.mix(colOnLayer2, m3colors.m3background, 0.4);
property color colLayer1Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer1, colOnLayer1, 0.92), root.contentTransparency) property color colLayer1Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer1, colOnLayer1, 0.92), root.contentTransparency)
property color colLayer1Active: ColorUtils.transparentize(ColorUtils.mix(colLayer1, colOnLayer1, 0.85), root.contentTransparency); property color colLayer1Active: ColorUtils.transparentize(ColorUtils.mix(colLayer1, colOnLayer1, 0.85), root.contentTransparency);
property color colLayer2Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer2, colOnLayer2, 0.90), root.contentTransparency) // Layer 2
property color colLayer2Active: ColorUtils.transparentize(ColorUtils.mix(colLayer2, colOnLayer2, 0.80), root.contentTransparency); property color colLayer2Base: m3colors.m3surfaceContainer
property color colLayer2Disabled: ColorUtils.transparentize(ColorUtils.mix(colLayer2, m3colors.m3background, 0.8), root.contentTransparency); property color colLayer2: ColorUtils.solveOverlayColor(colLayer1Base, colLayer2Base, 1 - root.contentTransparency)
property color colLayer3: ColorUtils.transparentize(m3colors.m3surfaceContainerHigh, root.contentTransparency) property color colLayer2Hover: ColorUtils.solveOverlayColor(colLayer1Base, ColorUtils.mix(colLayer2Base, colOnLayer2, 0.90), 1 - root.contentTransparency)
property color colLayer2Active: ColorUtils.solveOverlayColor(colLayer1Base, ColorUtils.mix(colLayer2Base, colOnLayer2, 0.80), 1 - root.contentTransparency);
property color colLayer2Disabled: ColorUtils.solveOverlayColor(colLayer1Base, ColorUtils.mix(colLayer2Base, m3colors.m3background, 0.8), 1 - root.contentTransparency);
property color colOnLayer2: m3colors.m3onSurface;
property color colOnLayer2Disabled: ColorUtils.mix(colOnLayer2, m3colors.m3background, 0.4);
// Layer 3
property color colLayer3Base: m3colors.m3surfaceContainerHigh
property color colLayer3: ColorUtils.solveOverlayColor(colLayer2Base, colLayer3Base, 1 - root.contentTransparency)
property color colLayer3Hover: ColorUtils.solveOverlayColor(colLayer2Base, ColorUtils.mix(colLayer3Base, colOnLayer3, 0.90), 1 - root.contentTransparency)
property color colLayer3Active: ColorUtils.solveOverlayColor(colLayer2Base, ColorUtils.mix(colLayer3Base, colOnLayer3, 0.80), 1 - root.contentTransparency);
property color colOnLayer3: m3colors.m3onSurface; property color colOnLayer3: m3colors.m3onSurface;
property color colLayer3Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer3, colOnLayer3, 0.90), root.contentTransparency) // Layer 4
property color colLayer3Active: ColorUtils.transparentize(ColorUtils.mix(colLayer3, colOnLayer3, 0.80), root.contentTransparency); property color colLayer4Base: m3colors.m3surfaceContainerHighest
property color colLayer4: ColorUtils.transparentize(m3colors.m3surfaceContainerHighest, root.contentTransparency) property color colLayer4: ColorUtils.solveOverlayColor(colLayer3Base, colLayer4Base, 1 - root.contentTransparency)
property color colLayer4Hover: ColorUtils.solveOverlayColor(colLayer3Base, ColorUtils.mix(colLayer4Base, colOnLayer4, 0.90), 1 - root.contentTransparency)
property color colLayer4Active: ColorUtils.solveOverlayColor(colLayer3Base, ColorUtils.mix(colLayer4Base, colOnLayer4, 0.80), 1 - root.contentTransparency);
property color colOnLayer4: m3colors.m3onSurface; property color colOnLayer4: m3colors.m3onSurface;
property color colLayer4Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer4, colOnLayer4, 0.90), root.contentTransparency) // Primary
property color colLayer4Active: ColorUtils.transparentize(ColorUtils.mix(colLayer4, colOnLayer4, 0.80), root.contentTransparency);
property color colPrimary: m3colors.m3primary property color colPrimary: m3colors.m3primary
property color colOnPrimary: m3colors.m3onPrimary property color colOnPrimary: m3colors.m3onPrimary
property color colPrimaryHover: ColorUtils.mix(colors.colPrimary, colLayer1Hover, 0.87) property color colPrimaryHover: ColorUtils.mix(colors.colPrimary, colLayer1Hover, 0.87)
@@ -146,13 +153,16 @@ Singleton {
property color colPrimaryContainerHover: ColorUtils.mix(colors.colPrimaryContainer, colors.colOnPrimaryContainer, 0.9) property color colPrimaryContainerHover: ColorUtils.mix(colors.colPrimaryContainer, colors.colOnPrimaryContainer, 0.9)
property color colPrimaryContainerActive: ColorUtils.mix(colors.colPrimaryContainer, colors.colOnPrimaryContainer, 0.8) property color colPrimaryContainerActive: ColorUtils.mix(colors.colPrimaryContainer, colors.colOnPrimaryContainer, 0.8)
property color colOnPrimaryContainer: m3colors.m3onPrimaryContainer property color colOnPrimaryContainer: m3colors.m3onPrimaryContainer
// Secondary
property color colSecondary: m3colors.m3secondary property color colSecondary: m3colors.m3secondary
property color colOnSecondary: m3colors.m3onSecondary
property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85) property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85)
property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4) property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4)
property color colOnSecondary: m3colors.m3onSecondary
property color colSecondaryContainer: m3colors.m3secondaryContainer property color colSecondaryContainer: m3colors.m3secondaryContainer
property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, m3colors.m3onSecondaryContainer, 0.90) property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, m3colors.m3onSecondaryContainer, 0.90)
property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, m3colors.m3onSecondaryContainer, 0.54) property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, m3colors.m3onSecondaryContainer, 0.54)
property color colOnSecondaryContainer: m3colors.m3onSecondaryContainer
// Tertiary
property color colTertiary: m3colors.m3tertiary property color colTertiary: m3colors.m3tertiary
property color colTertiaryHover: ColorUtils.mix(m3colors.m3tertiary, colLayer1Hover, 0.85) property color colTertiaryHover: ColorUtils.mix(m3colors.m3tertiary, colLayer1Hover, 0.85)
property color colTertiaryActive: ColorUtils.mix(m3colors.m3tertiary, colLayer1Active, 0.4) property color colTertiaryActive: ColorUtils.mix(m3colors.m3tertiary, colLayer1Active, 0.4)
@@ -161,16 +171,17 @@ Singleton {
property color colTertiaryContainerActive: ColorUtils.mix(m3colors.m3tertiaryContainer, colLayer1Active, 0.54) property color colTertiaryContainerActive: ColorUtils.mix(m3colors.m3tertiaryContainer, colLayer1Active, 0.54)
property color colOnTertiary: m3colors.m3onTertiary property color colOnTertiary: m3colors.m3onTertiary
property color colOnTertiaryContainer: m3colors.m3onTertiaryContainer property color colOnTertiaryContainer: m3colors.m3onTertiaryContainer
property color colOnSecondaryContainer: m3colors.m3onSecondaryContainer // Surface
property color colSurfaceContainerLow: ColorUtils.transparentize(m3colors.m3surfaceContainerLow, root.contentTransparency)
property color colSurfaceContainer: ColorUtils.transparentize(m3colors.m3surfaceContainer, root.contentTransparency)
property color colBackgroundSurfaceContainer: ColorUtils.transparentize(m3colors.m3surfaceContainer, root.backgroundTransparency) property color colBackgroundSurfaceContainer: ColorUtils.transparentize(m3colors.m3surfaceContainer, root.backgroundTransparency)
property color colSurfaceContainerHigh: ColorUtils.transparentize(m3colors.m3surfaceContainerHigh, root.contentTransparency) property color colSurfaceContainerLow: ColorUtils.solveOverlayColor(m3colors.m3background, m3colors.m3surfaceContainerLow, 1 - root.contentTransparency)
property color colSurfaceContainerHighest: ColorUtils.transparentize(m3colors.m3surfaceContainerHighest, root.contentTransparency) property color colSurfaceContainer: ColorUtils.solveOverlayColor(m3colors.m3surfaceContainerLow, m3colors.m3surfaceContainer, 1 - root.contentTransparency)
property color colSurfaceContainerHigh: ColorUtils.solveOverlayColor(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 1 - root.contentTransparency)
property color colSurfaceContainerHighest: ColorUtils.solveOverlayColor(m3colors.m3surfaceContainerHigh, m3colors.m3surfaceContainerHighest, 1 - root.contentTransparency)
property color colSurfaceContainerHighestHover: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95) property color colSurfaceContainerHighestHover: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95)
property color colSurfaceContainerHighestActive: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85) property color colSurfaceContainerHighestActive: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85)
property color colOnSurface: m3colors.m3onSurface property color colOnSurface: m3colors.m3onSurface
property color colOnSurfaceVariant: m3colors.m3onSurfaceVariant property color colOnSurfaceVariant: m3colors.m3onSurfaceVariant
// Misc
property color colTooltip: m3colors.m3inverseSurface property color colTooltip: m3colors.m3inverseSurface
property color colOnTooltip: m3colors.m3inverseOnSurface property color colOnTooltip: m3colors.m3inverseOnSurface
property color colScrim: ColorUtils.transparentize(m3colors.m3scrim, 0.5) property color colScrim: ColorUtils.transparentize(m3colors.m3scrim, 0.5)
@@ -78,10 +78,7 @@ Singleton {
JsonAdapter { JsonAdapter {
id: configOptionsJsonAdapter id: configOptionsJsonAdapter
property list<string> enabledPanels: [ property string panelFamily: "ii" // "ii", "waffle"
"iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"
]
property string panelFamily: "ii" // "ii", "w"
property JsonObject policies: JsonObject { property JsonObject policies: JsonObject {
property int ai: 1 // 0: No | 1: Yes | 2: Local property int ai: 1 // 0: No | 1: Yes | 2: Local
@@ -189,7 +186,17 @@ Singleton {
property bool useSineCookie: false property bool useSineCookie: false
} }
property JsonObject digital: JsonObject { property JsonObject digital: JsonObject {
property bool adaptiveAlignment: true
property bool showDate: true
property bool animateChange: true property bool animateChange: true
property bool vertical: false
property JsonObject font: JsonObject {
property string family: "Google Sans Flex"
property real weight: 350
property real width: 100
property real size: 90
property real roundness: 0
}
} }
property JsonObject quote: JsonObject { property JsonObject quote: JsonObject {
property bool enable: false property bool enable: false
@@ -566,6 +573,7 @@ Singleton {
} }
property JsonObject updates: JsonObject { property JsonObject updates: JsonObject {
property bool enableCheck: true
property int checkInterval: 120 // minutes property int checkInterval: 120 // minutes
property int adviseUpdateThreshold: 75 // packages property int adviseUpdateThreshold: 75 // packages
property int stronglyAdviseUpdateThreshold: 200 // packages property int stronglyAdviseUpdateThreshold: 200 // packages
@@ -59,7 +59,7 @@ Singleton {
property string hyprlandInstanceSignature: "" property string hyprlandInstanceSignature: ""
property JsonObject ai: JsonObject { property JsonObject ai: JsonObject {
property string model property string model: "gemini-2.5-flash"
property real temperature: 0.5 property real temperature: 0.5
} }
@@ -135,4 +135,38 @@ Singleton {
var c = Qt.color(color); var c = Qt.color(color);
return c.hslLightness < 0.5; return c.hslLightness < 0.5;
} }
/**
* Clamps a value to the inclusive range [0, 1].
*
* @param {number} x - The value to clamp.
* @returns {number} The clamped value in the range [0, 1].
*/
function clamp01(x) {
return Math.min(1, Math.max(0, x));
}
/**
* Solves for the solid overlay color that, when composited over a base color
* with a given opacity, yields the target color.
*
* The compositing equation is:
* result = overlay * overlayOpacity + base * (1 - overlayOpacity)
*
* This function algebraically inverts that equation per channel.
*
* @param {Qt.rgba} baseColor - The base (background) color.
* @param {Qt.rgba} targetColor - The resulting color after compositing.
* @param {number} overlayOpacity - The overlay opacity (0-1).
* @returns {Qt.rgba} The solved overlay color
*/
function solveOverlayColor(baseColor, targetColor, overlayOpacity) {
let invA = 1.0 - overlayOpacity;
let r = (targetColor.r - baseColor.r * invA) / overlayOpacity;
let g = (targetColor.g - baseColor.g * invA) / overlayOpacity;
let b = (targetColor.b - baseColor.b * invA) / overlayOpacity;
return Qt.rgba(clamp01(r), clamp01(g), clamp01(b), overlayOpacity);
}
} }
@@ -92,7 +92,6 @@ Scope {
WlSessionLock { WlSessionLock {
id: lock id: lock
locked: GlobalStates.screenLocked locked: GlobalStates.screenLocked
surface: root.sessionLockSurface surface: root.sessionLockSurface
} }
@@ -0,0 +1,81 @@
pragma ComponentBehavior: Bound
pragma Singleton
import qs.modules.common
import qs.modules.common.utils
import qs.modules.common.functions
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Controls
import Qt.labs.synchronizer
import Quickshell
Singleton {
id: root
enum Action {
Copy,
Edit,
Search,
CharRecognition,
Record,
RecordWithSound
}
property string imageSearchEngineBaseUrl: Config.options.search.imageSearch.imageSearchEngineBaseUrl
property string fileUploadApiEndpoint: "https://uguu.se/upload"
function getCommand(x, y, width, height, screenshotPath, action, saveDir = "") {
// Set command for action
const rx = Math.round(x);
const ry = Math.round(y);
const rw = Math.round(width);
const rh = Math.round(height);
const cropBase = `magick ${StringUtils.shellSingleQuoteEscape(screenshotPath)} `
+ `-crop ${rw}x${rh}+${rx}+${ry}`
const cropToStdout = `${cropBase} -`
const cropInPlace = `${cropBase} '${StringUtils.shellSingleQuoteEscape(screenshotPath)}'`
const cleanup = `rm '${StringUtils.shellSingleQuoteEscape(screenshotPath)}'`
const slurpRegion = `${rx},${ry} ${rw}x${rh}`
const uploadAndGetUrl = (filePath) => {
return `curl -sF files[]=@'${StringUtils.shellSingleQuoteEscape(filePath)}' ${root.fileUploadApiEndpoint} | jq -r '.files[0].url'`
}
const annotationCommand = `${Config.options.regionSelector.annotation.useSatty ? "satty" : "swappy"} -f -`;
switch (action) {
case ScreenshotAction.Action.Copy:
if (saveDir === "") {
// not saving the screenshot, just copy to clipboard
return ["bash", "-c", `${cropToStdout} | wl-copy && ${cleanup}`]
break;
}
return [
"bash", "-c",
`mkdir -p '${StringUtils.shellSingleQuoteEscape(saveDir)}' && \
saveFileName="screenshot-$(date '+%Y-%m-%d_%H.%M.%S').png" && \
savePath="${saveDir}/$saveFileName" && \
${cropToStdout} | tee >(wl-copy) > "$savePath" && \
${cleanup}`
]
break;
case ScreenshotAction.Action.Edit:
return ["bash", "-c", `${cropToStdout} | ${annotationCommand} && ${cleanup}`]
break;
case ScreenshotAction.Action.Search:
return ["bash", "-c", `${cropInPlace} && xdg-open "${root.imageSearchEngineBaseUrl}$(${uploadAndGetUrl(screenshotPath)})" && ${cleanup}`]
break;
case ScreenshotAction.Action.CharRecognition:
return ["bash", "-c", `${cropInPlace} && tesseract '${StringUtils.shellSingleQuoteEscape(screenshotPath)}' stdout -l $(tesseract --list-langs | awk 'NR>1{print $1}' | tr '\\n' '+' | sed 's/\\+$/\\n/') | wl-copy && ${cleanup}`]
break;
case ScreenshotAction.Action.Record:
return ["bash", "-c", `${Directories.recordScriptPath} --region '${slurpRegion}'`]
break;
case ScreenshotAction.Action.RecordWithSound:
return ["bash", "-c", `${Directories.recordScriptPath} --region '${slurpRegion}' --sound`]
break;
default:
console.warn("[Region Selector] Unknown snip action, skipping snip.");
return;
}
}
}
@@ -0,0 +1,14 @@
import QtQuick
import Quickshell
import Quickshell.Io
import qs.modules.common
import qs.modules.common.functions
Process {
id: screenshotProc
running: true
property string screenshotDir: Directories.screenshotTemp
required property ShellScreen screen
property string screenshotPath: `${screenshotDir}/image-${screen.name}`
command: ["bash", "-c", `mkdir -p '${StringUtils.shellSingleQuoteEscape(screenshotDir)}' && grim -o '${StringUtils.shellSingleQuoteEscape(screen.name)}' '${StringUtils.shellSingleQuoteEscape(screenshotPath)}'`]
}
@@ -0,0 +1,47 @@
import qs.modules.common.widgets
import qs.modules.common
import QtQuick
import QtQuick.Layouts
import qs.services
RowLayout {
id: root
spacing: 10
Layout.leftMargin: 8
Layout.rightMargin: 8
property string text: ""
property string buttonIcon: ""
property alias value: slider.value
property alias stopIndicatorValues: slider.stopIndicatorValues
property bool usePercentTooltip: true
property real from: slider.from
property real to: slider.to
property real textWidth: 120
RowLayout {
id: row
spacing: 10
OptionalMaterialSymbol {
id: iconWidget
icon: root.buttonIcon
iconSize: Appearance.font.pixelSize.larger
}
StyledText {
id: labelWidget
Layout.preferredWidth: root.textWidth
text: root.text
color: Appearance.colors.colOnSecondaryContainer
}
}
StyledSlider {
id: slider
configuration: StyledSlider.Configuration.XS
usePercentTooltip: root.usePercentTooltip
value: root.value
from: root.from
to: root.to
}
}
@@ -0,0 +1,28 @@
import QtQuick
import qs.modules.common
import qs.modules.common.functions
Canvas {
id: root
property color color: "#ffffff"
property int dashLength: 6
property int gapLength: 4
property int borderWidth: 1
onDashLengthChanged: requestPaint()
onGapLengthChanged: requestPaint()
onWidthChanged: requestPaint()
onHeightChanged: requestPaint()
onPaint: {
var ctx = getContext("2d");
ctx.clearRect(0, 0, width, height);
ctx.save();
ctx.strokeStyle = root.color;
ctx.lineWidth = root.borderWidth;
if (root.gapLength > 0) {
ctx.setLineDash([root.dashLength, root.gapLength]); // Set dash pattern
}
ctx.strokeRect(root.borderWidth / 2, root.borderWidth / 2, width - root.borderWidth, height - root.borderWidth); // Draw it
ctx.restore();
}
}
@@ -14,12 +14,16 @@ MouseArea {
property bool automaticallyReset: true property bool automaticallyReset: true
readonly property real dragDiffX: _dragDiffX readonly property real dragDiffX: _dragDiffX
readonly property real dragDiffY: _dragDiffY readonly property real dragDiffY: _dragDiffY
property real startX: 0
property real startY: 0
property real regionTopLeftX: Math.min(startX, startX + _dragDiffX)
property real regionTopLeftY: Math.min(startY, startY + _dragDiffY)
property real regionWidth: Math.abs(_dragDiffX)
property real regionHeight: Math.abs(_dragDiffY)
signal dragPressed(diffX: real, diffY: real) signal dragPressed(diffX: real, diffY: real)
signal dragReleased(diffX: real, diffY: real) signal dragReleased(diffX: real, diffY: real)
property real startX: 0
property real startY: 0
property bool dragging: false property bool dragging: false
property real _dragDiffX: 0 property real _dragDiffX: 0
property real _dragDiffY: 0 property real _dragDiffY: 0
@@ -121,7 +121,7 @@ MouseArea { // Notification group area
id: background id: background
anchors.left: parent.left anchors.left: parent.left
width: parent.width width: parent.width
color: popup ? ColorUtils.applyAlpha(Appearance.colors.colLayer2, 1 - Appearance.backgroundTransparency) : Appearance.colors.colLayer2 color: popup ? Appearance.colors.colBackgroundSurfaceContainer : Appearance.colors.colLayer2
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
anchors.leftMargin: root.xOffset anchors.leftMargin: root.xOffset
@@ -32,7 +32,7 @@ Item {
Rectangle { // The dialog Rectangle { // The dialog
id: dialog id: dialog
color: Appearance.colors.colSurfaceContainerHigh color: Appearance.m3colors.m3surfaceContainerHigh
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
anchors.fill: parent anchors.fill: parent
anchors.margins: dialogMargin anchors.margins: dialogMargin
@@ -192,7 +192,7 @@ ComboBox {
id: popupBackground id: popupBackground
anchors.fill: parent anchors.fill: parent
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
color: Appearance.colors.colSurfaceContainerHigh color: Appearance.m3colors.m3surfaceContainerHigh
} }
} }
@@ -46,7 +46,8 @@ Slider {
property real handleWidth: root.pressed ? handlePressedWidth : handleDefaultWidth property real handleWidth: root.pressed ? handlePressedWidth : handleDefaultWidth
property real handleMargins: 4 property real handleMargins: 4
property real trackDotSize: 3 property real trackDotSize: 3
property string tooltipContent: `${Math.round(value * 100)}%` property bool usePercentTooltip: true
property string tooltipContent: usePercentTooltip ? `${Math.round(((value - from) / (to - from)) * 100)}%` : `${Math.round(value)}`
property bool wavy: configuration === StyledSlider.Configuration.Wavy // If true, the progress bar will have a wavy fill effect property bool wavy: configuration === StyledSlider.Configuration.Wavy // If true, the progress bar will have a wavy fill effect
property bool animateWave: true property bool animateWave: true
property real waveAmplitudeMultiplier: wavy ? 0.5 : 0 property real waveAmplitudeMultiplier: wavy ? 0.5 : 0
@@ -12,19 +12,30 @@ Item {
required property var tabButtonList required property var tabButtonList
function incrementCurrentIndex() { function incrementCurrentIndex() {
tabBar.incrementCurrentIndex() tabBar.incrementCurrentIndex();
} }
function decrementCurrentIndex() { function decrementCurrentIndex() {
tabBar.decrementCurrentIndex() tabBar.decrementCurrentIndex();
} }
function setCurrentIndex(index) { function setCurrentIndex(index) {
tabBar.setCurrentIndex(index) tabBar.setCurrentIndex(index);
} }
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
implicitWidth: contentItem.implicitWidth implicitWidth: contentItem.implicitWidth
implicitHeight: 40 implicitHeight: 40
property Component delegate: ToolbarTabButton {
required property int index
required property var modelData
current: index == root.currentIndex
text: modelData.name
materialSymbol: modelData.icon
onClicked: {
root.setCurrentIndex(index);
}
}
Row { Row {
id: contentItem id: contentItem
z: 1 z: 1
@@ -33,16 +44,7 @@ Item {
Repeater { Repeater {
model: root.tabButtonList model: root.tabButtonList
delegate: ToolbarTabButton { delegate: root.delegate
required property int index
required property var modelData
current: index == root.currentIndex
text: modelData.name
materialSymbol: modelData.icon
onClicked: {
root.setCurrentIndex(index)
}
}
} }
} }
@@ -76,23 +78,23 @@ Item {
z: 2 z: 2
acceptedButtons: Qt.NoButton acceptedButtons: Qt.NoButton
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onWheel: (event) => { onWheel: event => {
if (event.angleDelta.y < 0) { if (event.angleDelta.y < 0) {
root.incrementCurrentIndex(); root.incrementCurrentIndex();
} } else {
else {
root.decrementCurrentIndex(); root.decrementCurrentIndex();
} }
} }
} }
// TabBar doesn't allow tabs to be of different sizes. Literally unusable. // TabBar doesn't allow tabs to be of different sizes. That's what I thought...
// We use it only for the logic and draw stuff manually // We use it only for the logic and draw stuff manually
TabBar { TabBar {
id: tabBar id: tabBar
z: -1 z: -1
background: null background: null
Repeater { // This is to fool the TabBar that it has tabs so it does the indices properly Repeater {
// This is to fool the TabBar that it has tabs so it does the indices properly
model: root.tabButtonList.length model: root.tabButtonList.length
delegate: TabButton { delegate: TabButton {
background: null background: null
@@ -59,7 +59,8 @@ AbstractWidget {
function onReadyChanged() { refreshPlacementIfNeeded() } function onReadyChanged() { refreshPlacementIfNeeded() }
} }
function refreshPlacementIfNeeded() { function refreshPlacementIfNeeded() {
if (!Config.ready || (root.placementStrategy === "free" && root.needsColText)) return; if (!Config.ready) return;
if (root.placementStrategy === "free" && !root.needsColText) return;
leastBusyRegionProc.wallpaperPath = root.wallpaperPath; leastBusyRegionProc.wallpaperPath = root.wallpaperPath;
leastBusyRegionProc.running = false; leastBusyRegionProc.running = false;
leastBusyRegionProc.running = true; leastBusyRegionProc.running = true;
@@ -0,0 +1,19 @@
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Layouts
StyledText {
Layout.fillWidth: true
font {
family: Appearance.font.family.expressive
pixelSize: 20
weight: 350
// Set empty to prevent conflicts, not meaningless
styleName: ""
variableAxes: ({})
}
style: Text.Raised
styleColor: Appearance.colors.colShadow
animateChange: Config.options.background.widgets.clock.digital.animateChange
}
@@ -26,7 +26,7 @@ AbstractBackgroundWidget {
visibleWhenLocked: true visibleWhenLocked: true
property var textHorizontalAlignment: { property var textHorizontalAlignment: {
if (root.forceCenter) if (!Config.options.background.widgets.clock.digital.adaptiveAlignment || root.forceCenter || Config.options.background.widgets.clock.digital.vertical)
return Text.AlignHCenter; return Text.AlignHCenter;
if (root.x < root.scaledScreenWidth / 3) if (root.x < root.scaledScreenWidth / 3)
return Text.AlignLeft; return Text.AlignLeft;
@@ -63,32 +63,9 @@ AbstractBackgroundWidget {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
shown: root.clockStyle === "digital" && (root.shouldShow) shown: root.clockStyle === "digital" && (root.shouldShow)
fade: false fade: false
sourceComponent: ColumnLayout { sourceComponent: DigitalClock {
id: clockColumn colText: root.colText
spacing: 6 textHorizontalAlignment: root.textHorizontalAlignment
ClockText {
font.pixelSize: 90
text: DateTime.time
}
ClockText {
Layout.topMargin: -5
text: DateTime.longDate
}
StyledText {
// Somehow gets fucked up if made a ClockText???
visible: Config.options.background.widgets.clock.quote.enable && Config.options.background.widgets.clock.quote.text.length > 0
Layout.fillWidth: true
horizontalAlignment: root.textHorizontalAlignment
font {
pixelSize: Appearance.font.pixelSize.normal
weight: 350
}
color: root.colText
style: Text.Raised
styleColor: Appearance.colors.colShadow
text: Config.options.background.widgets.clock.quote.text
}
} }
} }
StatusRow { StatusRow {
@@ -154,19 +131,6 @@ AbstractBackgroundWidget {
} }
} }
component ClockText: StyledText {
Layout.fillWidth: true
horizontalAlignment: root.textHorizontalAlignment
font {
family: Appearance.font.family.expressive
pixelSize: 20
weight: Font.DemiBold
}
color: root.colText
style: Text.Raised
styleColor: Appearance.colors.colShadow
animateChange: Config.options.background.widgets.clock.digital.animateChange
}
component ClockStatusText: Row { component ClockStatusText: Row {
id: statusTextRow id: statusTextRow
property alias statusIcon: statusIconWidget.text property alias statusIcon: statusIconWidget.text
@@ -190,6 +154,7 @@ AbstractBackgroundWidget {
ClockText { ClockText {
id: statusTextWidget id: statusTextWidget
color: statusTextRow.textColor color: statusTextRow.textColor
horizontalAlignment: root.textHorizontalAlignment
anchors.verticalCenter: statusTextRow.verticalCenter anchors.verticalCenter: statusTextRow.verticalCenter
font { font {
pixelSize: Appearance.font.pixelSize.large pixelSize: Appearance.font.pixelSize.large
@@ -66,16 +66,9 @@ Item {
} }
} }
Connections {
target: Config
function onReadyChanged() {
categoryFileView.path = Directories.generatedWallpaperCategoryPath
}
}
FileView { FileView {
id: categoryFileView id: categoryFileView
path: "" path: Config.ready ? Directories.generatedWallpaperCategoryPath : ""
watchChanges: true watchChanges: true
onFileChanged: reload() onFileChanged: reload()
onLoaded: { onLoaded: {
@@ -85,7 +78,7 @@ Item {
property bool useSineCookie: Config.options.background.widgets.clock.cookie.useSineCookie property bool useSineCookie: Config.options.background.widgets.clock.cookie.useSineCookie
StyledDropShadow { StyledDropShadow {
target: useSineCookie ? sineCookieLoader : roundedPolygonCookieLoader target: root.useSineCookie ? sineCookieLoader : roundedPolygonCookieLoader
RotationAnimation on rotation { RotationAnimation on rotation {
running: Config.options.background.widgets.clock.cookie.constantlyRotate running: Config.options.background.widgets.clock.cookie.constantlyRotate
@@ -100,7 +93,7 @@ Item {
id: sineCookieLoader id: sineCookieLoader
z: 0 z: 0
visible: false // The DropShadow already draws it visible: false // The DropShadow already draws it
active: useSineCookie active: root.useSineCookie
sourceComponent: SineCookie { sourceComponent: SineCookie {
implicitSize: root.implicitSize implicitSize: root.implicitSize
sides: Config.options.background.widgets.clock.cookie.sides sides: Config.options.background.widgets.clock.cookie.sides
@@ -111,7 +104,7 @@ Item {
id: roundedPolygonCookieLoader id: roundedPolygonCookieLoader
z: 0 z: 0
visible: false // The DropShadow already draws it visible: false // The DropShadow already draws it
active: !useSineCookie active: !root.useSineCookie
sourceComponent: MaterialCookie { sourceComponent: MaterialCookie {
implicitSize: root.implicitSize implicitSize: root.implicitSize
sides: Config.options.background.widgets.clock.cookie.sides sides: Config.options.background.widgets.clock.cookie.sides
@@ -0,0 +1,71 @@
pragma ComponentBehavior: Bound
import qs.services
import qs.modules.common
import QtQuick
import QtQuick.Layouts
ColumnLayout {
id: clockColumn
spacing: 4
property bool isVertical: Config.options.background.widgets.clock.digital.vertical
property color colText: Appearance.colors.colOnSecondaryContainer
property var textHorizontalAlignment: Text.AlignHCenter
// Time
ClockText {
id: timeTextTop
text: clockColumn.isVertical ? DateTime.time.split(":")[0].padStart(2, "0") : DateTime.time
color: clockColumn.colText
horizontalAlignment: Text.AlignHCenter
font {
pixelSize: Config.options.background.widgets.clock.digital.font.size
weight: Config.options.background.widgets.clock.digital.font.weight
family: Config.options.background.widgets.clock.digital.font.family
variableAxes: ({
"wdth": Config.options.background.widgets.clock.digital.font.width,
"ROND": Config.options.background.widgets.clock.digital.font.roundness
})
}
}
Loader {
Layout.topMargin: -40
Layout.fillWidth: true
active: clockColumn.isVertical
visible: active
sourceComponent: ClockText {
id: timeTextBottom
text: DateTime.time.split(":")[1].split(" ")[0].padStart(2, "0")
color: clockColumn.colText
horizontalAlignment: clockColumn.textHorizontalAlignment
font {
pixelSize: timeTextTop.font.pixelSize
weight: timeTextTop.font.weight
family: timeTextTop.font.family
variableAxes: timeTextTop.font.variableAxes
}
}
}
// Date
ClockText {
visible: Config.options.background.widgets.clock.digital.showDate
Layout.topMargin: -20
Layout.fillWidth: true
text: DateTime.longDate
color: clockColumn.colText
horizontalAlignment: clockColumn.textHorizontalAlignment
}
// Quote
ClockText {
visible: Config.options.background.widgets.clock.quote.enable && Config.options.background.widgets.clock.quote.text.length > 0
font.pixelSize: Appearance.font.pixelSize.normal
text: Config.options.background.widgets.clock.quote.text
animateChange: false
color: clockColumn.colText
horizontalAlignment: clockColumn.textHorizontalAlignment
}
}
@@ -1,3 +1,5 @@
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
@@ -60,6 +62,7 @@ Scope {
} }
color: "transparent" color: "transparent"
// Positioning
anchors { anchors {
top: !Config.options.bar.bottom top: !Config.options.bar.bottom
bottom: Config.options.bar.bottom bottom: Config.options.bar.bottom
@@ -72,6 +75,14 @@ Scope {
bottom: (Config.options.interactions.deadPixelWorkaround.enable && barRoot.anchors.bottom) * -1 bottom: (Config.options.interactions.deadPixelWorkaround.enable && barRoot.anchors.bottom) * -1
} }
// Include in focus grab
Component.onCompleted: {
GlobalFocusGrab.addPersistent(barRoot);
}
Component.onDestruction: {
GlobalFocusGrab.removePersistent(barRoot);
}
MouseArea { MouseArea {
id: hoverRegion id: hoverRegion
hoverEnabled: true hoverEnabled: true
@@ -80,19 +80,21 @@ Item { // Bar content region
RowLayout { RowLayout {
id: leftSectionRowLayout id: leftSectionRowLayout
anchors.fill: parent anchors.fill: parent
spacing: 10 spacing: 0
LeftSidebarButton { // Left sidebar button LeftSidebarButton { // Left sidebar button
id: leftSidebarButton
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Appearance.rounding.screenRounding Layout.leftMargin: Appearance.rounding.screenRounding
colBackground: barLeftSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) colBackground: barLeftSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1)
} }
ActiveWindow { ActiveWindow {
visible: root.useShortenedForm === 0 Layout.leftMargin: 10 + (leftSidebarButton.visible ? 0 : Appearance.rounding.screenRounding)
Layout.rightMargin: Appearance.rounding.screenRounding Layout.rightMargin: Appearance.rounding.screenRounding
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
visible: root.useShortenedForm === 0
} }
} }
} }
@@ -9,6 +9,11 @@ RippleButton {
property bool showPing: false property bool showPing: false
property bool aiChatEnabled: Config.options.policies.ai !== 0
property bool translatorEnabled: Config.options.sidebar.translator.enable
property bool animeEnabled: Config.options.policies.weeb !== 0
visible: aiChatEnabled || translatorEnabled || animeEnabled
property real buttonPadding: 5 property real buttonPadding: 5
implicitWidth: distroIcon.width + buttonPadding * 2 implicitWidth: distroIcon.width + buttonPadding * 2
implicitHeight: distroIcon.height + buttonPadding * 2 implicitHeight: distroIcon.height + buttonPadding * 2
@@ -18,9 +18,10 @@ Item {
property bool borderless: Config.options.bar.borderless property bool borderless: Config.options.bar.borderless
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.QsWindow.window?.screen) readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.QsWindow.window?.screen)
readonly property Toplevel activeWindow: ToplevelManager.activeToplevel readonly property Toplevel activeWindow: ToplevelManager.activeToplevel
readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1
readonly property int workspacesShown: Config.options.bar.workspaces.shown readonly property int workspacesShown: Config.options.bar.workspaces.shown
readonly property int workspaceGroup: Math.floor((monitor?.activeWorkspace?.id - 1) / root.workspacesShown) readonly property int workspaceGroup: Math.floor((effectiveActiveWorkspaceId - 1) / root.workspacesShown)
property list<bool> workspaceOccupied: [] property list<bool> workspaceOccupied: []
property int widgetPadding: 4 property int widgetPadding: 4
property int workspaceButtonWidth: 26 property int workspaceButtonWidth: 26
@@ -29,7 +30,7 @@ Item {
property real workspaceIconSizeShrinked: workspaceButtonWidth * 0.55 property real workspaceIconSizeShrinked: workspaceButtonWidth * 0.55
property real workspaceIconOpacityShrinked: 1 property real workspaceIconOpacityShrinked: 1
property real workspaceIconMarginShrinked: -4 property real workspaceIconMarginShrinked: -4
property int workspaceIndexInGroup: (monitor?.activeWorkspace?.id - 1) % root.workspacesShown property int workspaceIndexInGroup: (effectiveActiveWorkspaceId - 1) % root.workspacesShown
property bool showNumbers: false property bool showNumbers: false
Timer { Timer {
@@ -122,8 +123,8 @@ Item {
implicitWidth: workspaceButtonWidth implicitWidth: workspaceButtonWidth
implicitHeight: workspaceButtonWidth implicitHeight: workspaceButtonWidth
radius: (width / 2) radius: (width / 2)
property var previousOccupied: (workspaceOccupied[index-1] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index)) property var previousOccupied: (workspaceOccupied[index-1] && !(!activeWindow?.activated && root.effectiveActiveWorkspaceId === index))
property var rightOccupied: (workspaceOccupied[index+1] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index+2)) property var rightOccupied: (workspaceOccupied[index+1] && !(!activeWindow?.activated && root.effectiveActiveWorkspaceId === index+2))
property var radiusPrev: previousOccupied ? 0 : (width / 2) property var radiusPrev: previousOccupied ? 0 : (width / 2)
property var radiusNext: rightOccupied ? 0 : (width / 2) property var radiusNext: rightOccupied ? 0 : (width / 2)
@@ -133,7 +134,7 @@ Item {
bottomRightRadius: radiusNext bottomRightRadius: radiusNext
color: ColorUtils.transparentize(Appearance.m3colors.m3secondaryContainer, 0.4) color: ColorUtils.transparentize(Appearance.m3colors.m3secondaryContainer, 0.4)
opacity: (workspaceOccupied[index] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index+1)) ? 1 : 0 opacity: (workspaceOccupied[index] && !(!activeWindow?.activated && root.effectiveActiveWorkspaceId === index+1)) ? 1 : 0
Behavior on opacity { Behavior on opacity {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this) animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
@@ -225,7 +226,7 @@ Item {
} }
text: Config.options?.bar.workspaces.numberMap[button.workspaceValue - 1] || button.workspaceValue text: Config.options?.bar.workspaces.numberMap[button.workspaceValue - 1] || button.workspaceValue
elide: Text.ElideRight elide: Text.ElideRight
color: (monitor?.activeWorkspace?.id == button.workspaceValue) ? color: (root.effectiveActiveWorkspaceId == button.workspaceValue) ?
Appearance.m3colors.m3onPrimary : Appearance.m3colors.m3onPrimary :
(workspaceOccupied[index] ? Appearance.m3colors.m3onSecondaryContainer : (workspaceOccupied[index] ? Appearance.m3colors.m3onSecondaryContainer :
Appearance.colors.colOnLayer1Inactive) Appearance.colors.colOnLayer1Inactive)
@@ -245,7 +246,7 @@ Item {
width: workspaceButtonWidth * 0.18 width: workspaceButtonWidth * 0.18
height: width height: width
radius: width / 2 radius: width / 2
color: (monitor?.activeWorkspace?.id == button.workspaceValue) ? color: (root.effectiveActiveWorkspaceId == button.workspaceValue) ?
Appearance.m3colors.m3onPrimary : Appearance.m3colors.m3onPrimary :
(workspaceOccupied[index] ? Appearance.m3colors.m3onSecondaryContainer : (workspaceOccupied[index] ? Appearance.m3colors.m3onSecondaryContainer :
Appearance.colors.colOnLayer1Inactive) Appearance.colors.colOnLayer1Inactive)
@@ -100,5 +100,16 @@ StyledPopup {
value: Weather.data.sunset value: Weather.data.sunset
} }
} }
// Footer: last refresh
StyledText {
Layout.alignment: Qt.AlignHCenter
text: Translation.tr("Last refresh: %1").arg(Weather.data.lastRefresh)
font {
weight: Font.Medium
pixelSize: Appearance.font.pixelSize.smaller
}
color: Appearance.colors.colOnSurfaceVariant
}
} }
} }
@@ -54,13 +54,16 @@ Scope { // Scope
item: cheatsheetBackground item: cheatsheetBackground
} }
HyprlandFocusGrab { // Click outside to close Component.onCompleted: {
id: grab GlobalFocusGrab.addDismissable(cheatsheetRoot);
windows: [cheatsheetRoot] }
active: cheatsheetRoot.visible Component.onDestruction: {
onCleared: () => { GlobalFocusGrab.removeDismissable(cheatsheetRoot);
if (!active) }
cheatsheetRoot.hide(); Connections {
target: GlobalFocusGrab
function onDismissed() {
cheatsheetRoot.hide();
} }
} }
@@ -133,7 +133,7 @@ Item {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
} }
clip: true clip: true
color: Appearance.colors.colSurfaceContainer color: Appearance.m3colors.m3surfaceContainer
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: Appearance.sizes.elevationMargin anchors.bottomMargin: Appearance.sizes.elevationMargin
@@ -6,36 +6,61 @@ import qs.modules.common.functions
import qs.modules.common.panels.lock import qs.modules.common.panels.lock
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Hyprland import Quickshell.Hyprland
LockScreen { LockScreen {
id: root id: root
// Monitor name -> workspace id to restore on unlock (set when locking)
property var savedWorkspaces: ({})
Timer {
id: restoreTimer
interval: 150
repeat: false
onTriggered: {
var batch = ""
for (var j = 0; j < Quickshell.screens.length; ++j) {
var monName = Quickshell.screens[j].name
var wsId = root.savedWorkspaces[monName]
if (wsId !== undefined) {
batch += "dispatch focusmonitor " + monName + "; dispatch workspace " + wsId + "; "
}
}
if (batch.length > 0) {
Quickshell.execDetached(["hyprctl", "--batch", batch + "reload"])
}
}
}
lockSurface: LockSurface { lockSurface: LockSurface {
context: root.context context: root.context
} }
// Push everything down // Single batch for lock and unlock so we don't race multiple hyprctl calls
property var windowData: [] Connections {
function saveWindowPositionAndTile() { target: GlobalStates
Quickshell.execDetached(["hyprctl", "keyword", "dwindle:pseudotile", "true"]); function onScreenLockedChanged() {
root.windowData = HyprlandData.windowList.filter(w => (w.floating && w.workspace.id === HyprlandData.activeWorkspace.id)); if (GlobalStates.screenLocked) {
root.windowData.forEach(w => { // Lock: save workspace per monitor and move all to temp workspace in one batch
Hyprland.dispatch(`pseudo address:${w.address}`); var next = {}
Hyprland.dispatch(`settiled address:${w.address}`); var batch = "keyword animation workspaces,1,7,menu_decel,slidevert; "
Hyprland.dispatch(`movetoworkspacesilent ${w.workspace.id},address:${w.address}`); for (var i = 0; i < Quickshell.screens.length; ++i) {
}); var mon = Quickshell.screens[i].name
} var mData = HyprlandData.monitors.find(m => m.name === mon)
function restoreWindowPositionAndTile() { var ws = (mData?.activeWorkspace?.id ?? 1)
root.windowData.forEach(w => { next[mon] = ws
Hyprland.dispatch(`setfloating address:${w.address}`); batch += "dispatch focusmonitor " + mon + "; dispatch workspace " + (2147483647 - ws) + "; "
Hyprland.dispatch(`movewindowpixel exact ${w.at[0]} ${w.at[1]}, address:${w.address}`); }
Hyprland.dispatch(`pseudo address:${w.address}`); root.savedWorkspaces = next
}); Quickshell.execDetached(["hyprctl", "--batch", batch + "reload"])
Quickshell.execDetached(["hyprctl", "keyword", "dwindle:pseudotile", "false"]); } else {
restoreTimer.start()
}
}
} }
// Push everything down (visual only; workspace switch is in Connections above)
Variants { Variants {
model: Quickshell.screens model: Quickshell.screens
delegate: Scope { delegate: Scope {
@@ -44,15 +69,6 @@ LockScreen {
property string targetMonitorName: modelData.name property string targetMonitorName: modelData.name
property int verticalMovementDistance: modelData.height property int verticalMovementDistance: modelData.height
property int horizontalSqueeze: modelData.width * 0.2 property int horizontalSqueeze: modelData.width * 0.2
onShouldPushChanged: {
if (shouldPush) {
root.saveWindowPositionAndTile();
Quickshell.execDetached(["bash", "-c", `hyprctl keyword monitor ${targetMonitorName}, addreserved, ${verticalMovementDistance}, ${-verticalMovementDistance}, ${horizontalSqueeze}, ${horizontalSqueeze}`]);
} else {
Quickshell.execDetached(["bash", "-c", `hyprctl keyword monitor ${targetMonitorName}, addreserved, 0, 0, 0, 0`]);
root.restoreWindowPositionAndTile();
}
}
} }
} }
} }
@@ -136,6 +136,8 @@ MouseArea {
// Style // Style
clip: true clip: true
font.pixelSize: Appearance.font.pixelSize.small font.pixelSize: Appearance.font.pixelSize.small
selectedTextColor: materialShapeChars ? "transparent" : Appearance.colors.colOnSecondaryContainer
selectionColor: materialShapeChars ? "transparent" : Appearance.colors.colSecondaryContainer
// Password // Password
enabled: !root.context.unlockInProgress enabled: !root.context.unlockInProgress
@@ -195,6 +197,9 @@ MouseArea {
} }
sourceComponent: PasswordChars { sourceComponent: PasswordChars {
length: root.context.currentText.length length: root.context.currentText.length
selectionStart: passwordBox.selectionStart
selectionEnd: passwordBox.selectionEnd
cursorPosition: passwordBox.cursorPosition
} }
} }
} }
@@ -215,7 +220,7 @@ MouseArea {
iconSize: 24 iconSize: 24
text: { text: {
if (root.context.targetAction === LockContext.ActionEnum.Unlock) { if (root.context.targetAction === LockContext.ActionEnum.Unlock) {
return root.ctrlHeld ? "emoji_food_beverage" : "arrow_right_alt"; return root.ctrlHeld ? "coffee" : "arrow_right_alt";
} else if (root.context.targetAction === LockContext.ActionEnum.Poweroff) { } else if (root.context.targetAction === LockContext.ActionEnum.Poweroff) {
return "power_settings_new"; return "power_settings_new";
} else if (root.context.targetAction === LockContext.ActionEnum.Reboot) { } else if (root.context.targetAction === LockContext.ActionEnum.Reboot) {
@@ -9,29 +9,62 @@ import Quickshell
StyledFlickable { StyledFlickable {
id: root id: root
required property int length required property int length
property int selectionStart
property int selectionEnd
property int cursorPosition
property color color: Appearance.colors.colPrimary
property color selectedTextColor: Appearance.colors.colOnSecondaryContainer
property color selectionColor: Appearance.colors.colSecondaryContainer
property int charSize: 20
contentWidth: dotsRow.implicitWidth contentWidth: dotsRow.implicitWidth
contentX: (Math.max(contentWidth - width, 0)) contentX: (Math.max(contentWidth - width, 0))
Behavior on contentX { Behavior on contentX {
animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this) animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
} }
Rectangle {
id: cursor
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: root.charSize * root.cursorPosition
}
color: root.color
implicitWidth: 2
implicitHeight: root.charSize
Behavior on anchors.leftMargin {
animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(cursor)
}
}
Row { Row {
id: dotsRow id: dotsRow
anchors { anchors {
left: parent.left left: parent.left
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
leftMargin: 4 leftMargin: 4 - 5 // -5 to account for spacing being simulated by char item width
} }
spacing: 10 spacing: 0
Repeater { Repeater {
model: ScriptModel { model: ScriptModel { // TODO: use proper custom object model to insert new char at the correct pos
values: Array(root.length) values: Array(root.length)
} }
delegate: Item {
delegate: Rectangle {
id: charItem id: charItem
required property int index required property int index
implicitWidth: 10 implicitWidth: root.charSize
implicitHeight: 10 implicitHeight: root.charSize
property bool selected: index >= root.selectionStart && index < root.selectionEnd
color: ColorUtils.transparentize(root.selectionColor, selected ? 0 : 1)
MaterialShape { MaterialShape {
id: materialShape id: materialShape
anchors.centerIn: parent anchors.centerIn: parent
@@ -46,7 +79,7 @@ StyledFlickable {
] ]
shape: charShapes[charItem.index % charShapes.length] shape: charShapes[charItem.index % charShapes.length]
// Animate on appearance // Animate on appearance
color: Appearance.colors.colPrimary color: charItem.selected ? root.selectedTextColor : root.color
implicitSize: 0 implicitSize: 0
opacity: 0 opacity: 0
scale: 0.5 scale: 0.5
@@ -81,7 +81,7 @@ Scope {
} }
sourceComponent: PanelWindow { sourceComponent: PanelWindow {
id: mediaControlsRoot id: panelWindow
visible: true visible: true
exclusionMode: ExclusionMode.Ignore exclusionMode: ExclusionMode.Ignore
@@ -98,9 +98,9 @@ Scope {
right: Config.options.bar.vertical && Config.options.bar.bottom right: Config.options.bar.vertical && Config.options.bar.bottom
} }
margins { margins {
top: Config.options.bar.vertical ? ((mediaControlsRoot.screen.height / 2) - widgetHeight * 1.5) : Appearance.sizes.barHeight top: Config.options.bar.vertical ? ((panelWindow.screen.height / 2) - widgetHeight * 1.5) : Appearance.sizes.barHeight
bottom: Appearance.sizes.barHeight bottom: Appearance.sizes.barHeight
left: Config.options.bar.vertical ? Appearance.sizes.barHeight : ((mediaControlsRoot.screen.width / 2) - (osdWidth / 2) - widgetWidth) left: Config.options.bar.vertical ? Appearance.sizes.barHeight : ((panelWindow.screen.width / 2) - (osdWidth / 2) - widgetWidth)
right: Appearance.sizes.barHeight right: Appearance.sizes.barHeight
} }
@@ -108,13 +108,16 @@ Scope {
item: playerColumnLayout item: playerColumnLayout
} }
HyprlandFocusGrab { Component.onCompleted: {
windows: [mediaControlsRoot] GlobalFocusGrab.addDismissable(panelWindow);
active: mediaControlsLoader.active }
onCleared: () => { Component.onDestruction: {
if (!active) { GlobalFocusGrab.removeDismissable(panelWindow);
GlobalStates.mediaControlsOpen = false; }
} Connections {
target: GlobalFocusGrab
function onDismissed() {
GlobalStates.mediaControlsOpen = false;
} }
} }
@@ -137,10 +140,13 @@ Scope {
} }
} }
Item { // No player placeholder Item {
// No player placeholder
Layout.alignment: { Layout.alignment: {
if (mediaControlsRoot.anchors.left) return Qt.AlignLeft; if (panelWindow.anchors.left)
if (mediaControlsRoot.anchors.right) return Qt.AlignRight; return Qt.AlignLeft;
if (panelWindow.anchors.right)
return Qt.AlignRight;
return Qt.AlignHCenter; return Qt.AlignHCenter;
} }
Layout.leftMargin: Appearance.sizes.hyprlandGapsOut Layout.leftMargin: Appearance.sizes.hyprlandGapsOut
@@ -153,7 +159,7 @@ Scope {
target: placeholderBackground target: placeholderBackground
} }
Rectangle { Rectangle {
id: placeholderBackground id: placeholderBackground
anchors.centerIn: parent anchors.centerIn: parent
color: Appearance.colors.colLayer0 color: Appearance.colors.colLayer0
@@ -57,6 +57,13 @@ Scope { // Scope
item: oskBackground item: oskBackground
} }
// Make it usable with other panels
Component.onCompleted: {
GlobalFocusGrab.addPersistent(oskRoot);
}
Component.onDestruction: {
GlobalFocusGrab.removePersistent(oskRoot);
}
// Background // Background
StyledRectangularShadow { StyledRectangularShadow {
@@ -4,5 +4,5 @@ import qs.modules.common
Rectangle { Rectangle {
id: contentItem id: contentItem
anchors.fill: parent anchors.fill: parent
color: Appearance.colors.colSurfaceContainer color: Appearance.m3colors.m3surfaceContainer
} }
@@ -190,7 +190,7 @@ AbstractOverlayWidget {
fill: parent fill: parent
margins: root.resizeMargin margins: root.resizeMargin
} }
color: ColorUtils.transparentize(Appearance.colors.colLayer1, (root.fancyBorders && GlobalStates.overlayOpen) ? 0 : 1) color: ColorUtils.transparentize(Appearance.colors.colLayer1Base, (root.fancyBorders && GlobalStates.overlayOpen) ? 0 : 1)
radius: root.radius radius: root.radius
border.color: ColorUtils.transparentize(Appearance.colors.colOutlineVariant, GlobalStates.overlayOpen ? 0 : 1) border.color: ColorUtils.transparentize(Appearance.colors.colOutlineVariant, GlobalStates.overlayOpen ? 0 : 1)
border.width: 1 border.width: 1
@@ -217,7 +217,7 @@ AbstractOverlayWidget {
Layout.fillWidth: true Layout.fillWidth: true
implicitWidth: titleBarRow.implicitWidth + root.padding * 2 implicitWidth: titleBarRow.implicitWidth + root.padding * 2
implicitHeight: titleBarRow.implicitHeight + root.padding * 2 implicitHeight: titleBarRow.implicitHeight + root.padding * 2
color: root.fancyBorders ? "transparent" : Appearance.colors.colLayer1 color: root.fancyBorders ? "transparent" : Appearance.colors.colLayer1Base
// border.color: Appearance.colors.colOutlineVariant // border.color: Appearance.colors.colOutlineVariant
// border.width: 1 // border.width: 1
@@ -14,116 +14,96 @@ import Quickshell.Hyprland
Scope { Scope {
id: overviewScope id: overviewScope
property bool dontAutoCancelSearch: false property bool dontAutoCancelSearch: false
Variants {
id: overviewVariants PanelWindow {
model: Quickshell.screens id: panelWindow
PanelWindow { property string searchingText: ""
id: root readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen)
required property var modelData property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor?.id)
property string searchingText: "" visible: GlobalStates.overviewOpen
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen)
property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor?.id) WlrLayershell.namespace: "quickshell:overview"
screen: modelData WlrLayershell.layer: WlrLayer.Top
WlrLayershell.keyboardFocus: GlobalStates.overviewOpen ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
color: "transparent"
mask: Region {
item: GlobalStates.overviewOpen ? columnLayout : null
}
anchors {
top: true
bottom: true
left: true
right: true
}
Connections {
target: GlobalStates
function onOverviewOpenChanged() {
if (!GlobalStates.overviewOpen) {
searchWidget.disableExpandAnimation();
overviewScope.dontAutoCancelSearch = false;
GlobalFocusGrab.dismiss();
} else {
if (!overviewScope.dontAutoCancelSearch) {
searchWidget.cancelSearch();
}
GlobalFocusGrab.addDismissable(panelWindow);
}
}
}
Connections {
target: GlobalFocusGrab
function onDismissed() {
GlobalStates.overviewOpen = false;
}
}
implicitWidth: columnLayout.implicitWidth
implicitHeight: columnLayout.implicitHeight
function setSearchingText(text) {
searchWidget.setSearchingText(text);
searchWidget.focusFirstItem();
}
Column {
id: columnLayout
visible: GlobalStates.overviewOpen visible: GlobalStates.overviewOpen
WlrLayershell.namespace: "quickshell:overview"
WlrLayershell.layer: WlrLayer.Overlay
// WlrLayershell.keyboardFocus: GlobalStates.overviewOpen ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
color: "transparent"
mask: Region {
item: GlobalStates.overviewOpen ? columnLayout : null
}
anchors { anchors {
top: true horizontalCenter: parent.horizontalCenter
bottom: true top: parent.top
left: true
right: true
} }
spacing: -8
HyprlandFocusGrab { Keys.onPressed: event => {
id: grab if (event.key === Qt.Key_Escape) {
windows: [root] GlobalStates.overviewOpen = false;
property bool canBeActive: root.monitorIsFocused } else if (event.key === Qt.Key_Left) {
active: false if (!panelWindow.searchingText)
onCleared: () => { Hyprland.dispatch("workspace r-1");
if (!active) } else if (event.key === Qt.Key_Right) {
GlobalStates.overviewOpen = false; if (!panelWindow.searchingText)
Hyprland.dispatch("workspace r+1");
} }
} }
Connections { SearchWidget {
target: GlobalStates id: searchWidget
function onOverviewOpenChanged() { anchors.horizontalCenter: parent.horizontalCenter
if (!GlobalStates.overviewOpen) { Synchronizer on searchingText {
searchWidget.disableExpandAnimation(); property alias source: panelWindow.searchingText
overviewScope.dontAutoCancelSearch = false;
} else {
if (!overviewScope.dontAutoCancelSearch) {
searchWidget.cancelSearch();
}
delayedGrabTimer.start();
}
} }
} }
Timer { Loader {
id: delayedGrabTimer id: overviewLoader
interval: Config.options.hacks.arbitraryRaceConditionDelay anchors.horizontalCenter: parent.horizontalCenter
repeat: false active: GlobalStates.overviewOpen && (Config?.options.overview.enable ?? true)
onTriggered: { sourceComponent: OverviewWidget {
if (!grab.canBeActive) screen: panelWindow.screen
return; visible: (panelWindow.searchingText == "")
grab.active = GlobalStates.overviewOpen;
}
}
implicitWidth: columnLayout.implicitWidth
implicitHeight: columnLayout.implicitHeight
function setSearchingText(text) {
searchWidget.setSearchingText(text);
searchWidget.focusFirstItem();
}
Column {
id: columnLayout
visible: GlobalStates.overviewOpen
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
}
spacing: -8
Keys.onPressed: event => {
if (event.key === Qt.Key_Escape) {
GlobalStates.overviewOpen = false;
} else if (event.key === Qt.Key_Left) {
if (!root.searchingText)
Hyprland.dispatch("workspace r-1");
} else if (event.key === Qt.Key_Right) {
if (!root.searchingText)
Hyprland.dispatch("workspace r+1");
}
}
SearchWidget {
id: searchWidget
anchors.horizontalCenter: parent.horizontalCenter
Synchronizer on searchingText {
property alias source: root.searchingText
}
}
Loader {
id: overviewLoader
anchors.horizontalCenter: parent.horizontalCenter
active: GlobalStates.overviewOpen && (Config?.options.overview.enable ?? true)
sourceComponent: OverviewWidget {
panelWindow: root
visible: (root.searchingText == "")
}
} }
} }
} }
@@ -134,15 +114,9 @@ Scope {
GlobalStates.overviewOpen = false; GlobalStates.overviewOpen = false;
return; return;
} }
for (let i = 0; i < overviewVariants.instances.length; i++) { overviewScope.dontAutoCancelSearch = true;
let panelWindow = overviewVariants.instances[i]; panelWindow.setSearchingText(Config.options.search.prefix.clipboard);
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) { GlobalStates.overviewOpen = true;
overviewScope.dontAutoCancelSearch = true;
panelWindow.setSearchingText(Config.options.search.prefix.clipboard);
GlobalStates.overviewOpen = true;
return;
}
}
} }
function toggleEmojis() { function toggleEmojis() {
@@ -150,15 +124,9 @@ Scope {
GlobalStates.overviewOpen = false; GlobalStates.overviewOpen = false;
return; return;
} }
for (let i = 0; i < overviewVariants.instances.length; i++) { overviewScope.dontAutoCancelSearch = true;
let panelWindow = overviewVariants.instances[i]; panelWindow.setSearchingText(Config.options.search.prefix.emojis);
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) { GlobalStates.overviewOpen = true;
overviewScope.dontAutoCancelSearch = true;
panelWindow.setSearchingText(Config.options.search.prefix.emojis);
GlobalStates.overviewOpen = true;
return;
}
}
} }
IpcHandler { IpcHandler {
@@ -192,6 +160,14 @@ Scope {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen; GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
} }
} }
GlobalShortcut {
name: "overviewWorkspacesClose"
description: "Closes overview on press"
onPressed: {
GlobalStates.overviewOpen = false;
}
}
GlobalShortcut { GlobalShortcut {
name: "overviewWorkspacesToggle" name: "overviewWorkspacesToggle"
description: "Toggles overview on press" description: "Toggles overview on press"
@@ -13,11 +13,13 @@ import Quickshell.Hyprland
Item { Item {
id: root id: root
required property var panelWindow required property var screen
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen) readonly property HyprlandMonitor monitor: Hyprland.monitorFor(screen)
readonly property var toplevels: ToplevelManager.toplevels readonly property var toplevels: ToplevelManager.toplevels
// Clamp to avoid lock-screen temp workspace (2147483647 - N) leaking into UI
readonly property int effectiveActiveWorkspaceId: Math.max(1, Math.min(100, monitor?.activeWorkspace?.id ?? 1))
readonly property int workspacesShown: Config.options.overview.rows * Config.options.overview.columns readonly property int workspacesShown: Config.options.overview.rows * Config.options.overview.columns
readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / workspacesShown) readonly property int workspaceGroup: Math.floor((effectiveActiveWorkspaceId - 1) / workspacesShown)
property bool monitorIsFocused: (Hyprland.focusedMonitor?.name == monitor.name) property bool monitorIsFocused: (Hyprland.focusedMonitor?.name == monitor.name)
property var windows: HyprlandData.windowList property var windows: HyprlandData.windowList
property var windowByAddress: HyprlandData.windowByAddress property var windowByAddress: HyprlandData.windowByAddress
@@ -101,7 +103,7 @@ Item {
required property int index required property int index
property int colIndex: index property int colIndex: index
property int workspaceValue: root.workspaceGroup * root.workspacesShown + getWsInCell(row.index, colIndex) property int workspaceValue: root.workspaceGroup * root.workspacesShown + getWsInCell(row.index, colIndex)
property color defaultWorkspaceColor: ColorUtils.mix(Appearance.colors.colBackgroundSurfaceContainer, Appearance.colors.colSurfaceContainerHigh, 0.8) property color defaultWorkspaceColor: Appearance.colors.colSurfaceContainerLow
property color hoveredWorkspaceColor: ColorUtils.mix(defaultWorkspaceColor, Appearance.colors.colLayer1Hover, 0.1) property color hoveredWorkspaceColor: ColorUtils.mix(defaultWorkspaceColor, Appearance.colors.colLayer1Hover, 0.1)
property color hoveredBorderColor: Appearance.colors.colLayer2Hover property color hoveredBorderColor: Appearance.colors.colLayer2Hover
property bool hoveredWhileDragging: false property bool hoveredWhileDragging: false
@@ -301,8 +303,8 @@ Item {
Rectangle { // Focused workspace indicator Rectangle { // Focused workspace indicator
id: focusedWorkspaceIndicator id: focusedWorkspaceIndicator
property int rowIndex: getWsRow(monitor.activeWorkspace?.id) property int rowIndex: getWsRow(root.effectiveActiveWorkspaceId)
property int colIndex: getWsColumn(monitor.activeWorkspace?.id) property int colIndex: getWsColumn(root.effectiveActiveWorkspaceId)
x: (root.workspaceImplicitWidth + workspaceSpacing) * colIndex x: (root.workspaceImplicitWidth + workspaceSpacing) * colIndex
y: (root.workspaceImplicitHeight + workspaceSpacing) * rowIndex y: (root.workspaceImplicitHeight + workspaceSpacing) * rowIndex
z: root.windowZ z: root.windowZ
@@ -1,15 +1,12 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs import qs
import qs.services import qs.services
import qs.modules.common import qs.modules.common
import qs.modules.common.widgets import qs.modules.common.widgets
import qs.modules.common.functions import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
RowLayout { RowLayout {
id: root id: root
@@ -92,6 +89,16 @@ RowLayout {
} }
} }
} }
Keys.onPressed: event => {
if (event.key === Qt.Key_Tab) {
if (LauncherSearch.results.length === 0) return;
const tabbedText = LauncherSearch.results[0].name;
LauncherSearch.query = tabbedText;
searchInput.text = tabbedText;
event.accepted = true;
}
}
} }
IconToolbarButton { IconToolbarButton {
@@ -1,23 +1,28 @@
pragma ComponentBehavior: Bound
import Qt.labs.synchronizer
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs import qs
import qs.services import qs.services
import qs.modules.common import qs.modules.common
import qs.modules.common.widgets import qs.modules.common.widgets
import qs.modules.common.functions import qs.modules.common.functions
import Qt.labs.synchronizer
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
Item { // Wrapper Item { // Wrapper
id: root id: root
readonly property string xdgConfigHome: Directories.config readonly property string xdgConfigHome: Directories.config
readonly property int typingDebounceInterval: 200
readonly property int typingResultLimit: 15 // Should be enough to cover the whole view
property string searchingText: LauncherSearch.query property string searchingText: LauncherSearch.query
property bool showResults: searchingText != "" property bool showResults: searchingText != ""
implicitWidth: searchWidgetContent.implicitWidth + Appearance.sizes.elevationMargin * 2 implicitWidth: searchWidgetContent.implicitWidth + Appearance.sizes.elevationMargin * 2
implicitHeight: searchBar.implicitHeight + searchBar.verticalPadding * 2 + Appearance.sizes.elevationMargin * 2 implicitHeight: searchWidgetContent.implicitHeight + searchBar.verticalPadding * 2 + Appearance.sizes.elevationMargin * 2
function focusFirstItem() { function focusFirstItem() {
appResults.currentIndex = 0; appResults.currentIndex = 0;
@@ -178,30 +183,48 @@ Item { // Wrapper
} }
} }
model: ScriptModel { Timer {
id: model id: debounceTimer
objectProp: "key" interval: root.typingDebounceInterval
values: LauncherSearch.results onTriggered: {
onValuesChanged: { resultModel.values = LauncherSearch.results ?? [];
root.focusFirstItem();
} }
} }
Connections {
target: LauncherSearch
function onResultsChanged() {
resultModel.values = LauncherSearch.results.slice(0, root.typingResultLimit);
root.focusFirstItem();
debounceTimer.restart();
}
}
model: ScriptModel {
id: resultModel
objectProp: "key"
}
delegate: SearchItem { delegate: SearchItem {
id: searchItem
// The selectable item for each search result // The selectable item for each search result
required property var modelData required property var modelData
anchors.left: parent?.left anchors.left: parent?.left
anchors.right: parent?.right anchors.right: parent?.right
entry: modelData entry: modelData
query: StringUtils.cleanOnePrefix(root.searchingText, [ query: StringUtils.cleanOnePrefix(root.searchingText, [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])
Config.options.search.prefix.action,
Config.options.search.prefix.app, Keys.onPressed: event => {
Config.options.search.prefix.clipboard, if (event.key === Qt.Key_Tab) {
Config.options.search.prefix.emojis, if (LauncherSearch.results.length === 0)
Config.options.search.prefix.math, return;
Config.options.search.prefix.shellCommand, const tabbedText = searchItem.modelData.name;
Config.options.search.prefix.webSearch LauncherSearch.query = tabbedText;
]) searchBar.searchInput.text = tabbedText;
event.accepted = true;
root.focusSearchInput();
}
}
} }
} }
} }
@@ -0,0 +1,112 @@
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
Item {
id: root
property var action
property var selectionMode
property string description: switch (root.action) {
case RegionSelection.SnipAction.Copy:
case RegionSelection.SnipAction.Edit:
return Translation.tr("Copy region (LMB) or annotate (RMB)");
case RegionSelection.SnipAction.Search:
return Translation.tr("Search with Google Lens");
case RegionSelection.SnipAction.CharRecognition:
return Translation.tr("Recognize text");
case RegionSelection.SnipAction.Record:
case RegionSelection.SnipAction.RecordWithSound:
return Translation.tr("Record region");
}
property string materialSymbol: switch (root.action) {
case RegionSelection.SnipAction.Copy:
case RegionSelection.SnipAction.Edit:
return "content_cut";
case RegionSelection.SnipAction.Search:
return "image_search";
case RegionSelection.SnipAction.CharRecognition:
return "document_scanner";
case RegionSelection.SnipAction.Record:
case RegionSelection.SnipAction.RecordWithSound:
return "videocam";
default:
return "";
}
property bool showDescription: true
function hideDescription() {
root.showDescription = false
}
Timer {
id: descTimeout
interval: 1000
running: true
onTriggered: {
root.hideDescription()
}
}
onActionChanged: {
root.showDescription = true
descTimeout.restart()
}
property int margins: 8
implicitWidth: content.implicitWidth + margins * 2
implicitHeight: content.implicitHeight + margins * 2
Rectangle {
id: content
anchors.centerIn: parent
property real padding: 8
implicitHeight: 38
implicitWidth: root.showDescription ? contentRow.implicitWidth + padding * 2 : implicitHeight
clip: true
topLeftRadius: 6
bottomLeftRadius: implicitHeight - topLeftRadius
bottomRightRadius: bottomLeftRadius
topRightRadius: bottomLeftRadius
color: Appearance.colors.colPrimary
Behavior on topLeftRadius {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
Behavior on implicitWidth {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
Row {
id: contentRow
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: content.padding
}
spacing: 12
MaterialSymbol {
anchors.verticalCenter: parent.verticalCenter
iconSize: 22
color: Appearance.colors.colOnPrimary
animateChange: true
text: root.materialSymbol
}
FadeLoader {
id: descriptionLoader
anchors.verticalCenter: parent.verticalCenter
shown: root.showDescription
sourceComponent: StyledText {
color: Appearance.colors.colOnPrimary
text: root.description
anchors.right: parent.right
anchors.rightMargin: 6
}
}
}
}
}
@@ -23,48 +23,6 @@ Toolbar {
// Signals // Signals
signal dismiss() signal dismiss()
MaterialShape {
Layout.fillHeight: true
Layout.leftMargin: 2
Layout.rightMargin: 2
implicitSize: 36 // Intentionally smaller because this one is brighter than others
shape: switch (root.action) {
case RegionSelection.SnipAction.Copy:
case RegionSelection.SnipAction.Edit:
return MaterialShape.Shape.Cookie4Sided;
case RegionSelection.SnipAction.Search:
return MaterialShape.Shape.Pentagon;
case RegionSelection.SnipAction.CharRecognition:
return MaterialShape.Shape.Sunny;
case RegionSelection.SnipAction.Record:
case RegionSelection.SnipAction.RecordWithSound:
return MaterialShape.Shape.Gem;
default:
return MaterialShape.Shape.Cookie12Sided;
}
color: Appearance.colors.colPrimary
MaterialSymbol {
anchors.centerIn: parent
iconSize: 22
color: Appearance.colors.colOnPrimary
animateChange: true
text: switch (root.action) {
case RegionSelection.SnipAction.Copy:
case RegionSelection.SnipAction.Edit:
return "content_cut";
case RegionSelection.SnipAction.Search:
return "image_search";
case RegionSelection.SnipAction.CharRecognition:
return "document_scanner";
case RegionSelection.SnipAction.Record:
case RegionSelection.SnipAction.RecordWithSound:
return "videocam";
default:
return "";
}
}
}
ToolbarTabBar { ToolbarTabBar {
id: tabBar id: tabBar
tabButtonList: [ tabButtonList: [
@@ -76,5 +34,4 @@ Toolbar {
root.selectionMode = currentIndex === 0 ? RegionSelection.SelectionMode.RectCorners : RegionSelection.SelectionMode.Circle; root.selectionMode = currentIndex === 0 ? RegionSelection.SelectionMode.RectCorners : RegionSelection.SelectionMode.Circle;
} }
} }
} }
@@ -33,22 +33,40 @@ Item {
} }
// Selection border // Selection border
Rectangle { // Rectangle {
// id: selectionBorder
// z: 1
// anchors {
// left: parent.left
// top: parent.top
// leftMargin: root.regionX
// topMargin: root.regionY
// }
// width: root.regionWidth
// height: root.regionHeight
// color: "transparent"
// border.color: root.color
// border.width: 2
// // radius: root.standardRounding
// radius: 0 // TODO: figure out how to make the overlay thing work with rounding
// }
DashedBorder {
id: selectionBorder id: selectionBorder
z: 1 z: 9
anchors { anchors {
left: parent.left left: parent.left
top: parent.top top: parent.top
leftMargin: root.regionX leftMargin: Math.round(root.regionX) - borderWidth
topMargin: root.regionY topMargin: Math.round(root.regionY) - borderWidth
} }
width: root.regionWidth width: Math.round(root.regionWidth) + borderWidth * 2
height: root.regionHeight height: Math.round(root.regionHeight) + borderWidth * 2
color: "transparent"
border.color: root.color color: root.color
border.width: 2 dashLength: 6
// radius: root.standardRounding gapLength: 3
radius: 0 // TODO: figure out how to make the overlay thing work with rounding borderWidth: 1
} }
StyledText { StyledText {
@@ -1,5 +1,6 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.modules.common import qs.modules.common
import qs.modules.common.utils
import qs.modules.common.functions import qs.modules.common.functions
import qs.modules.common.widgets import qs.modules.common.widgets
import qs.services import qs.services
@@ -32,15 +33,9 @@ PanelWindow {
property var action: RegionSelection.SnipAction.Copy property var action: RegionSelection.SnipAction.Copy
property var selectionMode: RegionSelection.SelectionMode.RectCorners property var selectionMode: RegionSelection.SelectionMode.RectCorners
signal dismiss() signal dismiss()
property string saveScreenshotDir: Config.options.screenSnip.savePath !== ""
? Config.options.screenSnip.savePath
: ""
property string screenshotDir: Directories.screenshotTemp property string screenshotDir: Directories.screenshotTemp
property string imageSearchEngineBaseUrl: Config.options.search.imageSearch.imageSearchEngineBaseUrl property color overlayColor: ColorUtils.transparentize("#000000", 0.4)
property string fileUploadApiEndpoint: "https://uguu.se/upload"
property color overlayColor: "#88111111"
property color brightText: Appearance.m3colors.darkmode ? Appearance.colors.colOnLayer0 : Appearance.colors.colLayer0 property color brightText: Appearance.m3colors.darkmode ? Appearance.colors.colOnLayer0 : Appearance.colors.colLayer0
property color brightSecondary: Appearance.m3colors.darkmode ? Appearance.colors.colSecondary : Appearance.colors.colOnSecondary property color brightSecondary: Appearance.m3colors.darkmode ? Appearance.colors.colSecondary : Appearance.colors.colOnSecondary
property color brightTertiary: Appearance.m3colors.darkmode ? Appearance.colors.colTertiary : Qt.lighter(Appearance.colors.colPrimary) property color brightTertiary: Appearance.m3colors.darkmode ? Appearance.colors.colTertiary : Qt.lighter(Appearance.colors.colPrimary)
@@ -180,10 +175,12 @@ PanelWindow {
property real regionX: Math.min(dragStartX, draggingX) property real regionX: Math.min(dragStartX, draggingX)
property real regionY: Math.min(dragStartY, draggingY) property real regionY: Math.min(dragStartY, draggingY)
Process { TempScreenshotProcess {
id: screenshotProc id: screenshotProc
running: true running: true
command: ["bash", "-c", `mkdir -p '${StringUtils.shellSingleQuoteEscape(root.screenshotDir)}' && grim -o '${StringUtils.shellSingleQuoteEscape(root.screen.name)}' '${StringUtils.shellSingleQuoteEscape(root.screenshotPath)}'`] screen: root.screen
screenshotDir: root.screenshotDir
screenshotPath: root.screenshotPath
onExited: (exitCode, exitStatus) => { onExited: (exitCode, exitStatus) => {
if (root.enableContentRegions) imageDetectionProcess.running = true; if (root.enableContentRegions) imageDetectionProcess.running = true;
root.preparationDone = !checkRecordingProc.running; root.preparationDone = !checkRecordingProc.running;
@@ -229,6 +226,27 @@ PanelWindow {
} }
} }
function getScreenshotAction() {
switch(root.action) {
case RegionSelection.SnipAction.Copy:
return ScreenshotAction.Action.Copy;
case RegionSelection.SnipAction.Edit:
return ScreenshotAction.Action.Edit;
case RegionSelection.SnipAction.Search:
return ScreenshotAction.Action.Search;
case RegionSelection.SnipAction.CharRecognition:
return ScreenshotAction.Action.CharRecognition;
case RegionSelection.SnipAction.Record:
return ScreenshotAction.Action.Record;
case RegionSelection.SnipAction.RecordWithSound:
return ScreenshotAction.Action.RecordWithSound;
default:
console.warn("[Region Selector] Unknown snip action, skipping snip.");
root.dismiss();
return;
}
}
function snip() { function snip() {
// Validity check // Validity check
if (root.regionWidth <= 0 || root.regionHeight <= 0) { if (root.regionWidth <= 0 || root.regionHeight <= 0) {
@@ -246,62 +264,20 @@ PanelWindow {
if (root.action === RegionSelection.SnipAction.Copy || root.action === RegionSelection.SnipAction.Edit) { if (root.action === RegionSelection.SnipAction.Copy || root.action === RegionSelection.SnipAction.Edit) {
root.action = root.mouseButton === Qt.RightButton ? RegionSelection.SnipAction.Edit : RegionSelection.SnipAction.Copy; root.action = root.mouseButton === Qt.RightButton ? RegionSelection.SnipAction.Edit : RegionSelection.SnipAction.Copy;
} }
// Set command for action const screenshotDir = Config.options.screenSnip.savePath !== "" ? //
const rx = Math.round(root.regionX * root.monitorScale); Config.options.screenSnip.savePath : "";
const ry = Math.round(root.regionY * root.monitorScale); var screenshotAction = root.getScreenshotAction();
const rw = Math.round(root.regionWidth * root.monitorScale); const command = ScreenshotAction.getCommand(
const rh = Math.round(root.regionHeight * root.monitorScale); root.regionX * root.monitorScale, //
const cropBase = `magick ${StringUtils.shellSingleQuoteEscape(root.screenshotPath)} ` root.regionY * root.monitorScale, //
+ `-crop ${rw}x${rh}+${rx}+${ry}` root.regionWidth * root.monitorScale,//
const cropToStdout = `${cropBase} -` root.regionHeight * root.monitorScale, //
const cropInPlace = `${cropBase} '${StringUtils.shellSingleQuoteEscape(root.screenshotPath)}'` root.screenshotPath, //
const cleanup = `rm '${StringUtils.shellSingleQuoteEscape(root.screenshotPath)}'` screenshotAction, //
const slurpRegion = `${rx},${ry} ${rw}x${rh}` screenshotDir
const uploadAndGetUrl = (filePath) => { )
return `curl -sF files[]=@'${StringUtils.shellSingleQuoteEscape(filePath)}' ${root.fileUploadApiEndpoint} | jq -r '.files[0].url'` snipProc.command = command;
}
const annotationCommand = `${Config.options.regionSelector.annotation.useSatty ? "satty" : "swappy"} -f -`;
switch (root.action) {
case RegionSelection.SnipAction.Copy:
if (saveScreenshotDir === "") {
// not saving the screenshot, just copy to clipboard
snipProc.command = ["bash", "-c", `${cropToStdout} | wl-copy && ${cleanup}`]
break;
}
const savePathBase = root.saveScreenshotDir
snipProc.command = [
"bash", "-c",
`mkdir -p '${StringUtils.shellSingleQuoteEscape(savePathBase)}' && \
saveFileName="screenshot-$(date '+%Y-%m-%d_%H.%M.%S').png" && \
savePath="${savePathBase}/$saveFileName" && \
${cropToStdout} | tee >(wl-copy) > "$savePath" && \
${cleanup}`
]
break;
case RegionSelection.SnipAction.Edit:
snipProc.command = ["bash", "-c", `${cropToStdout} | ${annotationCommand} && ${cleanup}`]
break;
case RegionSelection.SnipAction.Search:
snipProc.command = ["bash", "-c", `${cropInPlace} && xdg-open "${root.imageSearchEngineBaseUrl}$(${uploadAndGetUrl(root.screenshotPath)})" && ${cleanup}`]
break;
case RegionSelection.SnipAction.CharRecognition:
snipProc.command = ["bash", "-c", `${cropInPlace} && tesseract '${StringUtils.shellSingleQuoteEscape(root.screenshotPath)}' stdout -l $(tesseract --list-langs | awk 'NR>1{print $1}' | tr '\\n' '+' | sed 's/\\+$/\\n/') | wl-copy && ${cleanup}`]
break;
case RegionSelection.SnipAction.Record:
snipProc.command = ["bash", "-c", `${Directories.recordScriptPath} --region '${slurpRegion}'`]
break;
case RegionSelection.SnipAction.RecordWithSound:
snipProc.command = ["bash", "-c", `${Directories.recordScriptPath} --region '${slurpRegion}' --sound`]
break;
default:
console.warn("[Region Selector] Unknown snip action, skipping snip.");
root.dismiss();
return;
}
// Image post-processing // Image post-processing
snipProc.startDetached(); snipProc.startDetached();
@@ -399,6 +375,14 @@ PanelWindow {
} }
} }
CursorGuide {
z: 9999
x: root.dragging ? root.regionX + root.regionWidth : mouseArea.mouseX
y: root.dragging ? root.regionY + root.regionHeight : mouseArea.mouseY
action: root.action
selectionMode: root.selectionMode
}
// Window regions // Window regions
Repeater { Repeater {
model: ScriptModel { model: ScriptModel {
@@ -471,7 +455,7 @@ PanelWindow {
// Controls // Controls
Row { Row {
id: regionSelectionControls id: regionSelectionControls
z: 9999 z: 10
anchors { anchors {
horizontalCenter: parent.horizontalCenter horizontalCenter: parent.horizontalCenter
bottom: parent.bottom bottom: parent.bottom
@@ -25,6 +25,10 @@ Rectangle {
border.width: targeted ? 4 : 2 border.width: targeted ? 4 : 2
radius: 4 radius: 4
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
visible: opacity > 0 visible: opacity > 0
Behavior on opacity { Behavior on opacity {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
@@ -45,9 +45,7 @@ Scope {
WlrLayershell.namespace: "quickshell:session" WlrLayershell.namespace: "quickshell:session"
WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
// This is a big surface so we needa carefully choose the transparency, color: ColorUtils.transparentize(Appearance.m3colors.m3background, Appearance.m3colors.darkmode ? 0.05 : 0.12)
// or we'll get a large scary rgb blob
color: ColorUtils.transparentize(Appearance.m3colors.m3background, Appearance.m3colors.darkmode ? 0.04 : 0.12)
anchors { anchors {
top: true top: true
@@ -240,7 +238,7 @@ Scope {
} }
} }
RowLayout { ColumnLayout {
anchors { anchors {
top: contentColumn.bottom top: contentColumn.bottom
topMargin: 10 topMargin: 10
@@ -249,19 +247,22 @@ Scope {
spacing: 10 spacing: 10
Loader { Loader {
active: SessionWarnings.packageManagerRunning Layout.alignment: Qt.AlignHCenter
active: SessionWarnings.downloadRunning
visible: active visible: active
sourceComponent: DescriptionLabel { sourceComponent: DescriptionLabel {
text: Translation.tr("Your package manager is running") text: Translation.tr("There might be a download in progress. Check your Downloads folder.")
textColor: Appearance.m3colors.m3onErrorContainer textColor: Appearance.m3colors.m3onErrorContainer
color: Appearance.m3colors.m3errorContainer color: Appearance.m3colors.m3errorContainer
} }
} }
Loader { Loader {
active: SessionWarnings.downloadRunning Layout.alignment: Qt.AlignHCenter
active: SessionWarnings.packageManagerRunning
visible: active visible: active
sourceComponent: DescriptionLabel { sourceComponent: DescriptionLabel {
text: Translation.tr("There might be a download in progress") text: Translation.tr("Your package manager is running")
textColor: Appearance.m3colors.m3onErrorContainer textColor: Appearance.m3colors.m3onErrorContainer
color: Appearance.m3colors.m3errorContainer color: Appearance.m3colors.m3errorContainer
} }
@@ -314,7 +314,10 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\)
implicitWidth: statusRowLayout.implicitWidth + 10 * 2 implicitWidth: statusRowLayout.implicitWidth + 10 * 2
implicitHeight: Math.max(statusRowLayout.implicitHeight, 38) implicitHeight: Math.max(statusRowLayout.implicitHeight, 38)
radius: Appearance.rounding.normal - root.padding radius: Appearance.rounding.normal - root.padding
color: Appearance.colors.colLayer2 color: messageListView.atYBeginning ? Appearance.colors.colLayer2 : Appearance.colors.colLayer2Base
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
RowLayout { RowLayout {
id: statusRowLayout id: statusRowLayout
anchors.centerIn: parent anchors.centerIn: parent
@@ -67,6 +67,7 @@ Scope { // Scope
onDetachChanged: { onDetachChanged: {
if (root.detach) { if (root.detach) {
GlobalFocusGrab.removeDismissable(sidebarLoader.item) // Remove sidebar from the focus grab system
sidebarContent.parent = null; // Detach content from sidebar sidebarContent.parent = null; // Detach content from sidebar
sidebarLoader.active = false; // Unload sidebar sidebarLoader.active = false; // Unload sidebar
detachedSidebarLoader.active = true; // Load detached window detachedSidebarLoader.active = true; // Load detached window
@@ -84,11 +85,11 @@ Scope { // Scope
active: true active: true
sourceComponent: PanelWindow { // Window sourceComponent: PanelWindow { // Window
id: sidebarRoot id: panelWindow
visible: GlobalStates.sidebarLeftOpen visible: GlobalStates.sidebarLeftOpen
property bool extend: false property bool extend: false
property real sidebarWidth: sidebarRoot.extend ? Appearance.sizes.sidebarWidthExtended : Appearance.sizes.sidebarWidth property real sidebarWidth: panelWindow.extend ? Appearance.sizes.sidebarWidthExtended : Appearance.sizes.sidebarWidth
property var contentParent: sidebarLeftBackground property var contentParent: sidebarLeftBackground
function hide() { function hide() {
@@ -113,15 +114,17 @@ Scope { // Scope
item: sidebarLeftBackground item: sidebarLeftBackground
} }
HyprlandFocusGrab { // Click outside to close onVisibleChanged: {
id: grab if (visible) {
windows: [ sidebarRoot ] GlobalFocusGrab.addDismissable(panelWindow);
active: sidebarRoot.visible && !root.pin } else {
onActiveChanged: { // Focus the selected tab GlobalFocusGrab.removeDismissable(panelWindow);
if (active) sidebarLeftBackground.children[0].focusActiveItem()
} }
onCleared: () => { }
if (!active) sidebarRoot.hide() Connections {
target: GlobalFocusGrab
function onDismissed() {
panelWindow.hide();
} }
} }
@@ -136,7 +139,7 @@ Scope { // Scope
anchors.left: parent.left anchors.left: parent.left
anchors.topMargin: Appearance.sizes.hyprlandGapsOut anchors.topMargin: Appearance.sizes.hyprlandGapsOut
anchors.leftMargin: Appearance.sizes.hyprlandGapsOut anchors.leftMargin: Appearance.sizes.hyprlandGapsOut
width: sidebarRoot.sidebarWidth - Appearance.sizes.hyprlandGapsOut - Appearance.sizes.elevationMargin width: panelWindow.sidebarWidth - Appearance.sizes.hyprlandGapsOut - Appearance.sizes.elevationMargin
height: parent.height - Appearance.sizes.hyprlandGapsOut * 2 height: parent.height - Appearance.sizes.hyprlandGapsOut * 2
color: Appearance.colors.colLayer0 color: Appearance.colors.colLayer0
border.width: 1 border.width: 1
@@ -149,11 +152,11 @@ Scope { // Scope
Keys.onPressed: (event) => { Keys.onPressed: (event) => {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
sidebarRoot.hide(); panelWindow.hide();
} }
if (event.modifiers === Qt.ControlModifier) { if (event.modifiers === Qt.ControlModifier) {
if (event.key === Qt.Key_O) { if (event.key === Qt.Key_O) {
sidebarRoot.extend = !sidebarRoot.extend; panelWindow.extend = !panelWindow.extend;
} else if (event.key === Qt.Key_D) { } else if (event.key === Qt.Key_D) {
root.toggleDetach(); root.toggleDetach();
} else if (event.key === Qt.Key_P) { } else if (event.key === Qt.Key_P) {
@@ -48,6 +48,7 @@ Item {
spacing: sidebarPadding spacing: sidebarPadding
Toolbar { Toolbar {
visible: tabButtonList.length > 0
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
enableShadow: false enableShadow: false
ToolbarTabBar { ToolbarTabBar {
@@ -83,9 +84,10 @@ Item {
} }
contentChildren: [ contentChildren: [
...((root.aiChatEnabled || (!root.translatorEnabled && !root.animeEnabled)) ? [aiChat.createObject()] : []), ...(root.aiChatEnabled ? [aiChat.createObject()] : []),
...(root.translatorEnabled ? [translator.createObject()] : []), ...(root.translatorEnabled ? [translator.createObject()] : []),
...(root.animeEnabled ? [anime.createObject()] : []) ...((root.tabButtonList.length === 0 || (!root.aiChatEnabled && !root.translatorEnabled && root.animeCloset)) ? [placeholder.createObject()] : []),
...(root.animeEnabled ? [anime.createObject()] : []),
] ]
} }
} }
@@ -102,6 +104,15 @@ Item {
id: anime id: anime
Anime {} Anime {}
} }
Component {
id: placeholder
Item {
StyledText {
anchors.centerIn: parent
text: root.animeCloset ? Translation.tr("Nothing") : Translation.tr("Enjoy your empty sidebar...")
color: Appearance.colors.colSubtext
}
}
}
} }
} }
@@ -126,7 +126,7 @@ Button {
opacity: root.showActions ? 1 : 0 opacity: root.showActions ? 1 : 0
visible: opacity > 0 visible: opacity > 0
radius: Appearance.rounding.small radius: Appearance.rounding.small
color: Appearance.colors.colSurfaceContainer color: Appearance.m3colors.m3surfaceContainer
implicitHeight: contextMenuColumnLayout.implicitHeight + radius * 2 implicitHeight: contextMenuColumnLayout.implicitHeight + radius * 2
implicitWidth: contextMenuColumnLayout.implicitWidth implicitWidth: contextMenuColumnLayout.implicitWidth
@@ -138,7 +138,7 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
// implicitHeight: tabStack.implicitHeight // implicitHeight: tabStack.implicitHeight
spacing: 10 spacing: 20
// Navigation rail // Navigation rail
Item { Item {
@@ -146,7 +146,7 @@ Rectangle {
Layout.fillWidth: false Layout.fillWidth: false
Layout.leftMargin: 10 Layout.leftMargin: 10
Layout.topMargin: 10 Layout.topMargin: 10
width: tabBar.width implicitWidth: tabBar.implicitWidth
// Navigation rail buttons // Navigation rail buttons
NavigationRailTabArray { NavigationRailTabArray {
id: tabBar id: tabBar
@@ -12,18 +12,17 @@ Scope {
property int sidebarWidth: Appearance.sizes.sidebarWidth property int sidebarWidth: Appearance.sizes.sidebarWidth
PanelWindow { PanelWindow {
id: sidebarRoot id: panelWindow
visible: GlobalStates.sidebarRightOpen visible: GlobalStates.sidebarRightOpen
function hide() { function hide() {
GlobalStates.sidebarRightOpen = false GlobalStates.sidebarRightOpen = false;
} }
exclusiveZone: 0 exclusiveZone: 0
implicitWidth: sidebarWidth implicitWidth: sidebarWidth
WlrLayershell.namespace: "quickshell:sidebarRight" WlrLayershell.namespace: "quickshell:sidebarRight"
// Hyprland 0.49: Focus is always exclusive and setting this breaks mouse focus grab WlrLayershell.keyboardFocus: GlobalStates.sidebarRightOpen ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
// WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
color: "transparent" color: "transparent"
anchors { anchors {
@@ -32,12 +31,17 @@ Scope {
bottom: true bottom: true
} }
HyprlandFocusGrab { onVisibleChanged: {
id: grab if (visible) {
windows: [ sidebarRoot ] GlobalFocusGrab.addDismissable(panelWindow);
active: GlobalStates.sidebarRightOpen } else {
onCleared: () => { GlobalFocusGrab.removeDismissable(panelWindow);
if (!active) sidebarRoot.hide() }
}
Connections {
target: GlobalFocusGrab
function onDismissed() {
panelWindow.hide();
} }
} }
@@ -53,16 +57,14 @@ Scope {
height: parent.height - Appearance.sizes.hyprlandGapsOut * 2 height: parent.height - Appearance.sizes.hyprlandGapsOut * 2
focus: GlobalStates.sidebarRightOpen focus: GlobalStates.sidebarRightOpen
Keys.onPressed: (event) => { Keys.onPressed: event => {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
sidebarRoot.hide(); panelWindow.hide();
} }
} }
sourceComponent: SidebarRightContent {} sourceComponent: SidebarRightContent {}
} }
} }
IpcHandler { IpcHandler {
@@ -105,5 +107,4 @@ Scope {
GlobalStates.sidebarRightOpen = false; GlobalStates.sidebarRightOpen = false;
} }
} }
} }
@@ -47,6 +47,7 @@ DialogListItem {
color: Appearance.colors.colOnSurfaceVariant color: Appearance.colors.colOnSurfaceVariant
elide: Text.ElideRight elide: Text.ElideRight
text: root.device?.name || Translation.tr("Unknown device") text: root.device?.name || Translation.tr("Unknown device")
textFormat: Text.PlainText
} }
StyledText { StyledText {
visible: (root.device?.connected || root.device?.paired) ?? false visible: (root.device?.connected || root.device?.paired) ?? false
@@ -139,7 +139,7 @@ Item {
anchors.margins: root.dialogMargins anchors.margins: root.dialogMargins
implicitHeight: dialogColumnLayout.implicitHeight implicitHeight: dialogColumnLayout.implicitHeight
color: Appearance.colors.colSurfaceContainerHigh color: Appearance.m3colors.m3surfaceContainerHigh
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
function addTask() { function addTask() {
@@ -40,6 +40,7 @@ DialogListItem {
color: Appearance.colors.colOnSurfaceVariant color: Appearance.colors.colOnSurfaceVariant
elide: Text.ElideRight elide: Text.ElideRight
text: root.wifiNetwork?.ssid ?? Translation.tr("Unknown") text: root.wifiNetwork?.ssid ?? Translation.tr("Unknown")
textFormat: Text.PlainText
} }
MaterialSymbol { MaterialSymbol {
visible: (root.wifiNetwork?.isSecure || root.wifiNetwork?.active) ?? false visible: (root.wifiNetwork?.isSecure || root.wifiNetwork?.active) ?? false
@@ -66,6 +66,7 @@ Scope {
} }
color: "transparent" color: "transparent"
// Positioning
anchors { anchors {
left: !Config.options.bar.bottom left: !Config.options.bar.bottom
right: Config.options.bar.bottom right: Config.options.bar.bottom
@@ -73,6 +74,14 @@ Scope {
bottom: true bottom: true
} }
// Include in focus grab
Component.onCompleted: {
GlobalFocusGrab.addPersistent(barRoot);
}
Component.onDestruction: {
GlobalFocusGrab.removePersistent(barRoot);
}
MouseArea { MouseArea {
id: hoverRegion id: hoverRegion
hoverEnabled: true hoverEnabled: true
@@ -73,7 +73,7 @@ MouseArea {
target: Wallpapers target: Wallpapers
function onThumbnailGenerated(directory) { function onThumbnailGenerated(directory) {
if (thumbnailImage.status !== Image.Error) return; if (thumbnailImage.status !== Image.Error) return;
if (FileUtils.parentDirectory(thumbnailImage.sourcePath) !== directory) return; if (FileUtils.parentDirectory(thumbnailImage.sourcePath) !== FileUtils.trimFileProtocol(directory)) return;
thumbnailImage.source = ""; thumbnailImage.source = "";
thumbnailImage.source = thumbnailImage.thumbnailPath; thumbnailImage.source = thumbnailImage.thumbnailPath;
} }
@@ -25,6 +25,7 @@ Scope {
exclusionMode: ExclusionMode.Ignore exclusionMode: ExclusionMode.Ignore
WlrLayershell.namespace: "quickshell:wallpaperSelector" WlrLayershell.namespace: "quickshell:wallpaperSelector"
WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
color: "transparent" color: "transparent"
anchors.top: true anchors.top: true
@@ -39,12 +40,16 @@ Scope {
implicitHeight: Appearance.sizes.wallpaperSelectorHeight implicitHeight: Appearance.sizes.wallpaperSelectorHeight
implicitWidth: Appearance.sizes.wallpaperSelectorWidth implicitWidth: Appearance.sizes.wallpaperSelectorWidth
HyprlandFocusGrab { // Click outside to close Component.onCompleted: {
id: grab GlobalFocusGrab.addDismissable(panelWindow);
windows: [ panelWindow ] }
active: wallpaperSelectorLoader.active Component.onDestruction: {
onCleared: () => { GlobalFocusGrab.removeDismissable(panelWindow);
if (!active) GlobalStates.wallpaperSelectorOpen = false; }
Connections {
target: GlobalFocusGrab
function onDismissed() {
GlobalStates.wallpaperSelectorOpen = false;
} }
} }
@@ -53,9 +53,9 @@ ContentPage {
} }
ContentSection { ContentSection {
id: settingsClock
icon: "clock_loader_40" icon: "clock_loader_40"
title: Translation.tr("Widget: Clock") title: Translation.tr("Widget: Clock")
id: settingsClock
function stylePresent(styleName) { function stylePresent(styleName) {
if (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === styleName) { if (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === styleName) {
@@ -120,61 +120,161 @@ ContentPage {
} }
} }
ContentSubsection { ConfigRow {
visible: !Config.options.background.widgets.clock.showOnlyWhenLocked ContentSubsection {
title: Translation.tr("Clock style") visible: !Config.options.background.widgets.clock.showOnlyWhenLocked
ConfigSelectionArray { title: Translation.tr("Clock style")
currentValue: Config.options.background.widgets.clock.style Layout.fillWidth: true
onSelected: newValue => { ConfigSelectionArray {
Config.options.background.widgets.clock.style = newValue; currentValue: Config.options.background.widgets.clock.style
} onSelected: newValue => {
options: [ Config.options.background.widgets.clock.style = newValue;
{
displayName: Translation.tr("Digital"),
icon: "timer_10",
value: "digital"
},
{
displayName: Translation.tr("Cookie"),
icon: "cookie",
value: "cookie"
} }
] options: [
{
displayName: Translation.tr("Digital"),
icon: "timer_10",
value: "digital"
},
{
displayName: Translation.tr("Cookie"),
icon: "cookie",
value: "cookie"
}
]
}
} }
}
ContentSubsection { ContentSubsection {
title: Translation.tr("Clock style (locked)") title: Translation.tr("Clock style (locked)")
ConfigSelectionArray { Layout.fillWidth: false
currentValue: Config.options.background.widgets.clock.styleLocked ConfigSelectionArray {
onSelected: newValue => { currentValue: Config.options.background.widgets.clock.styleLocked
Config.options.background.widgets.clock.styleLocked = newValue; onSelected: newValue => {
} Config.options.background.widgets.clock.styleLocked = newValue;
options: [
{
displayName: Translation.tr("Digital"),
icon: "timer_10",
value: "digital"
},
{
displayName: Translation.tr("Cookie"),
icon: "cookie",
value: "cookie"
} }
] options: [
{
displayName: Translation.tr("Digital"),
icon: "timer_10",
value: "digital"
},
{
displayName: Translation.tr("Cookie"),
icon: "cookie",
value: "cookie"
}
]
}
} }
} }
ContentSubsection { ContentSubsection {
visible: settingsClock.digitalPresent visible: settingsClock.digitalPresent
title: Translation.tr("Digital clock settings") title: Translation.tr("Digital clock settings")
tooltip: Translation.tr("Font width and roundness settings are only available for some fonts like Google Sans Flex")
ConfigSwitch { ConfigRow {
buttonIcon: "animation" uniform: true
text: Translation.tr("Animate time change") ConfigSwitch {
checked: Config.options.background.widgets.clock.digital.animateChange buttonIcon: "vertical_distribute"
onCheckedChanged: { text: Translation.tr("Vertical")
Config.options.background.widgets.clock.digital.animateChange = checked; checked: Config.options.background.widgets.clock.digital.vertical
onCheckedChanged: {
Config.options.background.widgets.clock.digital.vertical = checked;
}
}
ConfigSwitch {
buttonIcon: "animation"
text: Translation.tr("Animate time change")
checked: Config.options.background.widgets.clock.digital.animateChange
onCheckedChanged: {
Config.options.background.widgets.clock.digital.animateChange = checked;
}
}
}
ConfigRow {
uniform: true
ConfigSwitch {
buttonIcon: "date_range"
text: Translation.tr("Show date")
checked: Config.options.background.widgets.clock.digital.showDate
onCheckedChanged: {
Config.options.background.widgets.clock.digital.showDate = checked;
}
}
ConfigSwitch {
buttonIcon: "activity_zone"
text: Translation.tr("Use adaptive alignment")
checked: Config.options.background.widgets.clock.digital.adaptiveAlignment
onCheckedChanged: {
Config.options.background.widgets.clock.digital.adaptiveAlignment = checked;
}
StyledToolTip {
text: Translation.tr("Aligns the date and quote to left, center or right depending on its position on the screen.")
}
}
}
MaterialTextArea {
Layout.fillWidth: true
placeholderText: Translation.tr("Font family")
text: Config.options.background.widgets.clock.digital.font.family
wrapMode: TextEdit.Wrap
onTextChanged: {
Config.options.background.widgets.clock.digital.font.family = text;
}
}
ConfigSlider {
text: Translation.tr("Font weight")
value: Config.options.background.widgets.clock.digital.font.weight
usePercentTooltip: false
buttonIcon: "format_bold"
from: 1
to: 1000
stopIndicatorValues: [350]
onValueChanged: {
Config.options.background.widgets.clock.digital.font.weight = value;
}
}
ConfigSlider {
text: Translation.tr("Font size")
value: Config.options.background.widgets.clock.digital.font.size
usePercentTooltip: false
buttonIcon: "format_size"
from: 50
to: 700
stopIndicatorValues: [90]
onValueChanged: {
Config.options.background.widgets.clock.digital.font.size = value;
}
}
ConfigSlider {
text: Translation.tr("Font width")
value: Config.options.background.widgets.clock.digital.font.width
usePercentTooltip: false
buttonIcon: "fit_width"
from: 25
to: 125
stopIndicatorValues: [100]
onValueChanged: {
Config.options.background.widgets.clock.digital.font.width = value;
}
}
ConfigSlider {
text: Translation.tr("Font roundness")
value: Config.options.background.widgets.clock.digital.font.roundness
usePercentTooltip: false
buttonIcon: "line_curve"
from: 0
to: 100
onValueChanged: {
Config.options.background.widgets.clock.digital.font.roundness = value;
} }
} }
} }
@@ -141,7 +141,7 @@ ContentPage {
key: "Ctrl" key: "Ctrl"
} }
KeyboardKey { KeyboardKey {
key: "󰖳" key: Config.options.cheatsheet.superKey ?? "󰖳"
} }
StyledText { StyledText {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
@@ -225,9 +225,6 @@ ContentPage {
onCheckedChanged: { onCheckedChanged: {
Config.options.appearance.transparency.enable = checked; Config.options.appearance.transparency.enable = checked;
} }
StyledToolTip {
text: Translation.tr("Might look ass. Unsupported.")
}
} }
} }
@@ -203,6 +203,32 @@ ContentPage {
} }
} }
// There's no update indicator in ii for now so we shouldn't show this yet
// ContentSection {
// icon: "deployed_code_update"
// title: Translation.tr("System updates (Arch only)")
// ConfigSwitch {
// text: Translation.tr("Enable update checks")
// checked: Config.options.updates.enableCheck
// onCheckedChanged: {
// Config.options.updates.enableCheck = checked;
// }
// }
// ConfigSpinBox {
// icon: "av_timer"
// text: Translation.tr("Check interval (mins)")
// value: Config.options.updates.checkInterval
// from: 60
// to: 1440
// stepSize: 60
// onValueChanged: {
// Config.options.updates.checkInterval = value;
// }
// }
// }
ContentSection { ContentSection {
icon: "weather_mix" icon: "weather_mix"
title: Translation.tr("Weather") title: Translation.tr("Weather")
@@ -41,6 +41,7 @@ ExpandableChoiceButton {
elide: Text.ElideRight elide: Text.ElideRight
font.pixelSize: Looks.font.pixelSize.large font.pixelSize: Looks.font.pixelSize.large
text: root.device?.name || Translation.tr("Unknown device") text: root.device?.name || Translation.tr("Unknown device")
textFormat: Text.PlainText
} }
WText { // Status WText { // Status
id: statusText id: statusText
@@ -61,6 +61,7 @@ ExpandableChoiceButton {
elide: Text.ElideRight elide: Text.ElideRight
font.pixelSize: Looks.font.pixelSize.large font.pixelSize: Looks.font.pixelSize.large
text: root.wifiNetwork?.ssid ?? Translation.tr("Unknown") text: root.wifiNetwork?.ssid ?? Translation.tr("Unknown")
textFormat: Text.PlainText
} }
WText { // Status WText { // Status
id: statusText id: statusText
@@ -13,7 +13,7 @@ Scope {
LazyLoader { LazyLoader {
id: barLoader id: barLoader
active: GlobalStates.barOpen && !GlobalStates.screenLocked active: GlobalStates.barOpen
component: Variants { component: Variants {
model: Quickshell.screens model: Quickshell.screens
delegate: PanelWindow { // Bar window delegate: PanelWindow { // Bar window
@@ -12,7 +12,20 @@ AppButton {
required property var appEntry required property var appEntry
readonly property bool isSeparator: appEntry.appId === "SEPARATOR" readonly property bool isSeparator: appEntry.appId === "SEPARATOR"
readonly property var desktopEntry: DesktopEntries.heuristicLookup(appEntry.appId) property var desktopEntry: DesktopEntries.heuristicLookup(appEntry.appId)
Timer {
// Retry looking up the desktop entry if it failed (e.g. database not loaded yet)
property int retryCount: 5
interval: 1000
running: !root.isSeparator && root.desktopEntry === null && retryCount > 0
repeat: true
onTriggered: {
retryCount--;
root.desktopEntry = DesktopEntries.heuristicLookup(root.appEntry.appId);
}
}
property bool active: root.appEntry.toplevels.some(t => t.activated) property bool active: root.appEntry.toplevels.some(t => t.activated)
property bool hasWindows: appEntry.toplevels.length > 0 property bool hasWindows: appEntry.toplevels.length > 0
@@ -36,15 +36,34 @@ LockScreen {
Image { Image {
id: bg id: bg
z: 0 z: 0
anchors.fill: parent width: parent.width
height: parent.height
onStatusChanged: {
if (status === Image.Ready) {
print("Lock wallpaper loaded");
print(lockSurfaceItem.height);
y = -lockSurfaceItem.height;
openAnim.restart();
}
}
sourceSize: Qt.size(lockSurfaceItem.width, lockSurfaceItem.height) sourceSize: Qt.size(lockSurfaceItem.width, lockSurfaceItem.height)
source: Config.options.background.wallpaperPath source: Config.options.background.wallpaperPath
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
PropertyAnimation {
id: openAnim
target: bg
property: "y"
to: 0
duration: 350
easing.type: Easing.BezierSpline
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
}
} }
GaussianBlur { GaussianBlur {
z: 1 z: 1
anchors.fill: parent anchors.fill: bg
source: bg source: bg
radius: 100 radius: 100
samples: radius * 2 + 1 samples: radius * 2 + 1
@@ -67,7 +86,7 @@ LockScreen {
Interactables { Interactables {
id: interactables id: interactables
z: 2 z: 2
anchors.fill: parent anchors.fill: bg
} }
} }
@@ -83,12 +102,31 @@ LockScreen {
// } // }
function switchToFocusedView() { function switchToFocusedView() {
root.passwordView = true; switchToPasswordViewAnim.restart();
}
SequentialAnimation {
id: switchToPasswordViewAnim
PropertyAnimation {
target: unfocusedContent
property: "y"
from: 0
to: -height * 1.1
duration: 250
easing.type: Easing.BezierSpline
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
}
ScriptAction {
script: {
root.passwordView = true;
}
}
} }
Item { Item {
id: unfocusedContent id: unfocusedContent
anchors.fill: parent width: parent.width
height: parent.height
visible: !root.passwordView visible: !root.passwordView
ClockTextGroup { ClockTextGroup {
anchors { anchors {
@@ -17,8 +17,9 @@ Singleton {
property string iconsPath: `${Directories.assetsPath}/icons/fluent` property string iconsPath: `${Directories.assetsPath}/icons/fluent`
property bool dark: Appearance.m3colors.darkmode property bool dark: Appearance.m3colors.darkmode
property real backgroundTransparency: 0.16 readonly property bool transparencyEnabled: Config.options.appearance.transparency.enable
property real panelBackgroundTransparency: 0.14 property real backgroundTransparency: transparencyEnabled ? 0.16 : 0
property real panelBackgroundTransparency: transparencyEnabled ? 0.14 : 0
property real panelLayerTransparency: root.dark ? 0.9 : 0.7 property real panelLayerTransparency: root.dark ? 0.9 : 0.7
property real contentTransparency: root.dark ? 0.87 : 0.5 property real contentTransparency: root.dark ? 0.87 : 0.5
function applyBackgroundTransparency(col) { function applyBackgroundTransparency(col) {
@@ -27,23 +28,22 @@ Singleton {
function applyContentTransparency(col) { function applyContentTransparency(col) {
return ColorUtils.applyAlpha(col, 1 - root.contentTransparency) return ColorUtils.applyAlpha(col, 1 - root.contentTransparency)
} }
lightColors: QtObject { // TODO: figure out transparency lightColors: QtObject {
id: lightColors id: lightColors
property color bgPanelFooter: "#EEEEEE"
property color bgPanelBody: "#F2F2F2" property color bgPanelBody: "#F2F2F2"
property color bgPanelSeparator: "#E0E0E0" property color bgPanelSeparator: "#E0E0E0"
property color bg0: "#EEEEEE" property color bg0: "#EEEEEE"
property color bg0Border: '#adadad' property color bg0Border: '#BEBEBE'
property color bg1: "#F7F7F7"
property color bg1Base: "#F7F7F7" property color bg1Base: "#F7F7F7"
property color bg1: "#F7F7F7"
property color bg1Hover: "#F7F7F7" property color bg1Hover: "#F7F7F7"
property color bg1Active: '#EFEFEF' property color bg1Active: '#EFEFEF'
property color bg1Border: '#d7d7d7' property color bg1Border: '#E9E9E9'
property color bg2: "#FBFBFB" property color bg2: "#FBFBFB"
property color bg2Base: "#FBFBFB" property color bg2Base: "#FBFBFB"
property color bg2Hover: '#ffffff' property color bg2Hover: '#ffffff'
property color bg2Active: '#eeeeee' property color bg2Active: '#eeeeee'
property color bg2Border: '#cdcdcd' property color bg2Border: '#E0E0E0'
property color subfg: "#5C5C5C" property color subfg: "#5C5C5C"
property color fg: "#000000" property color fg: "#000000"
property color fg1: "#626262" property color fg1: "#626262"
@@ -58,21 +58,20 @@ Singleton {
} }
darkColors: QtObject { darkColors: QtObject {
id: darkColors id: darkColors
property color bgPanelFooter: "#1C1C1C" property color bgPanelBody: '#242424'
property color bgPanelBody: '#616161'
property color bgPanelSeparator: "#191919" property color bgPanelSeparator: "#191919"
property color bg0: "#1C1C1C" property color bg0: "#1C1C1C"
property color bg0Border: "#404040" property color bg0Border: "#404040"
property color bg1Base: "#2C2C2C" property color bg1Base: '#2C2C2C'
property color bg1: '#9f9f9f' property color bg1: '#2C2C2C'
property color bg1Hover: "#b3b3b3" property color bg1Hover: "#292929"
property color bg1Active: '#727272' property color bg1Active: '#252525'
property color bg1Border: '#bebebe' property color bg1Border: '#bebebe'
property color bg2Base: "#313131" property color bg2Base: "#313131"
property color bg2: '#8a8a8a' property color bg2: '#313131'
property color bg2Hover: '#b1b1b1' property color bg2Hover: '#363636'
property color bg2Active: '#919191' property color bg2Active: '#2B2B2B'
property color bg2Border: '#bdbdbd' property color bg2Border: '#404040'
property color subfg: "#CED1D7" property color subfg: "#CED1D7"
property color fg: "#FFFFFF" property color fg: "#FFFFFF"
property color fg1: "#D1D1D1" property color fg1: "#D1D1D1"
@@ -87,38 +86,47 @@ Singleton {
} }
colors: QtObject { colors: QtObject {
id: colors id: colors
// Special
property color shadow: ColorUtils.transparentize('#161616', 0.62) property color shadow: ColorUtils.transparentize('#161616', 0.62)
property color ambientShadow: ColorUtils.transparentize("#000000", 0.75) property color ambientShadow: ColorUtils.transparentize("#000000", 0.75)
property color bgPanelFooterBase: ColorUtils.transparentize(root.dark ? root.darkColors.bgPanelFooter : root.lightColors.bgPanelFooter, root.panelBackgroundTransparency) property color bgPanelFooterBase: root.dark ? root.darkColors.bg0 : root.lightColors.bg0
property color bgPanelFooter: ColorUtils.transparentize(root.dark ? root.darkColors.bgPanelFooter : root.lightColors.bgPanelFooter, root.panelLayerTransparency) property color bgPanelFooterBackground: ColorUtils.transparentize(root.dark ? root.darkColors.bg0 : root.lightColors.bg0, root.panelBackgroundTransparency)
property color bgPanelBody: ColorUtils.transparentize(root.dark ? root.darkColors.bgPanelBody : root.lightColors.bgPanelBody, root.panelLayerTransparency) property color bgPanelFooter: ColorUtils.transparentize(bgPanelFooterBackground, root.panelLayerTransparency)
property color bgPanelSeparator: ColorUtils.transparentize(root.dark ? root.darkColors.bgPanelSeparator : root.lightColors.bgPanelSeparator, root.backgroundTransparency) property color bgPanelBodyBase: root.dark ? root.darkColors.bgPanelBody : root.lightColors.bgPanelBody
property color bg0Opaque: root.dark ? root.darkColors.bg0 : root.lightColors.bg0 property color bgPanelBody: ColorUtils.solveOverlayColor(bgPanelFooterBackground,bgPanelBodyBase, 1 - root.panelLayerTransparency)
property color bg0: ColorUtils.transparentize(bg0Opaque, root.backgroundTransparency) property color bgPanelSeparator: ColorUtils.solveOverlayColor(bgPanelBodyBase, root.dark ? root.darkColors.bgPanelSeparator : root.lightColors.bgPanelSeparator, 1 - root.panelBackgroundTransparency)
// Layer 0
property color bg0Base: root.dark ? root.darkColors.bg0 : root.lightColors.bg0
property color bg0: ColorUtils.transparentize(bg0Base, root.backgroundTransparency)
property color bg0Border: ColorUtils.transparentize(root.dark ? root.darkColors.bg0Border : root.lightColors.bg0Border, root.backgroundTransparency) property color bg0Border: ColorUtils.transparentize(root.dark ? root.darkColors.bg0Border : root.lightColors.bg0Border, root.backgroundTransparency)
property color bg1Base: root.dark ? root.darkColors.bg1Base : root.lightColors.bg1Base // Layer 1
property color bg1: ColorUtils.transparentize(root.dark ? root.darkColors.bg1 : root.lightColors.bg1, root.contentTransparency) property color bg1Base: root.dark ? root.darkColors.bg1 : root.lightColors.bg1
property color bg1Hover: ColorUtils.transparentize(root.dark ? root.darkColors.bg1Hover : root.lightColors.bg1Hover, root.contentTransparency) property color bg1: ColorUtils.solveOverlayColor(bg0Base, bg1Base, 1 - root.contentTransparency)
property color bg1Active: ColorUtils.transparentize(root.dark ? root.darkColors.bg1Active : root.lightColors.bg1Active, root.contentTransparency) property color bg1Hover: ColorUtils.solveOverlayColor(bg0Base, root.dark ? root.darkColors.bg1Hover : root.lightColors.bg1Hover, 1 - root.contentTransparency)
property color bg1Border: ColorUtils.transparentize(root.dark ? root.darkColors.bg1Border : root.lightColors.bg1Border, root.contentTransparency) property color bg1Active: ColorUtils.solveOverlayColor(bg0Base, root.dark ? root.darkColors.bg1Active : root.lightColors.bg1Active, 1 - root.contentTransparency)
property color bg2Base: root.dark ? root.darkColors.bg2Base : root.lightColors.bg2Base property color bg1Border: ColorUtils.solveOverlayColor(bg0Base, root.dark ? root.darkColors.bg1Border : root.lightColors.bg1Border, 1 - root.contentTransparency)
property color bg2: ColorUtils.transparentize(root.dark ? root.darkColors.bg2 : root.lightColors.bg2, root.contentTransparency) // Layer 2
property color bg2Hover: ColorUtils.transparentize(root.dark ? root.darkColors.bg2Hover : root.lightColors.bg2Hover, root.contentTransparency) property color bg2Base: root.dark ? root.darkColors.bg2 : root.lightColors.bg2
property color bg2Active: ColorUtils.transparentize(root.dark ? root.darkColors.bg2Active : root.lightColors.bg2Active, root.contentTransparency) property color bg2: ColorUtils.solveOverlayColor(bgPanelBodyBase, bg2Base, 1 - root.contentTransparency)
property color bg2Border: ColorUtils.transparentize(root.dark ? root.darkColors.bg2Border : root.lightColors.bg2Border, root.contentTransparency) property color bg2Hover: ColorUtils.solveOverlayColor(bgPanelBodyBase, root.dark ? root.darkColors.bg2Hover : root.lightColors.bg2Hover, 1 - root.contentTransparency)
property color bg2Active: ColorUtils.solveOverlayColor(bgPanelBodyBase, root.dark ? root.darkColors.bg2Active : root.lightColors.bg2Active, 1 - root.contentTransparency)
property color bg2Border: ColorUtils.solveOverlayColor(bgPanelBodyBase, root.dark ? root.darkColors.bg2Border : root.lightColors.bg2Border, 1 - root.contentTransparency)
// Foreground / Text
property color subfg: root.dark ? root.darkColors.subfg : root.lightColors.subfg property color subfg: root.dark ? root.darkColors.subfg : root.lightColors.subfg
property color fg: root.dark ? root.darkColors.fg : root.lightColors.fg property color fg: root.dark ? root.darkColors.fg : root.lightColors.fg
property color fg1: root.dark ? root.darkColors.fg1 : root.lightColors.fg1 property color fg1: root.dark ? root.darkColors.fg1 : root.lightColors.fg1
property color inactiveIcon: root.dark ? root.darkColors.inactiveIcon : root.lightColors.inactiveIcon property color inactiveIcon: root.dark ? root.darkColors.inactiveIcon : root.lightColors.inactiveIcon
property color link: root.dark ? root.darkColors.link : root.lightColors.link
// Controls
property color controlBgInactive: root.dark ? root.darkColors.controlBgInactive : root.lightColors.controlBgInactive property color controlBgInactive: root.dark ? root.darkColors.controlBgInactive : root.lightColors.controlBgInactive
property color controlBg: root.dark ? root.darkColors.controlBg : root.lightColors.controlBg property color controlBg: root.dark ? root.darkColors.controlBg : root.lightColors.controlBg
property color controlBgHover: root.dark ? root.darkColors.controlBgHover : root.lightColors.controlBgHover property color controlBgHover: root.dark ? root.darkColors.controlBgHover : root.lightColors.controlBgHover
property color controlFg: root.dark ? root.darkColors.controlFg : root.lightColors.controlFg property color controlFg: root.dark ? root.darkColors.controlFg : root.lightColors.controlFg
property color inputBg: root.dark ? root.darkColors.inputBg : root.lightColors.inputBg property color inputBg: root.dark ? root.darkColors.inputBg : root.lightColors.inputBg
property color link: root.dark ? root.darkColors.link : root.lightColors.link
property color danger: "#C42B1C" property color danger: "#C42B1C"
property color dangerActive: "#B62D1F" property color dangerActive: "#B62D1F"
property color warning: "#FF9900" property color warning: "#FF9900"
// Accent
property color accent: Appearance.colors.colPrimary property color accent: Appearance.colors.colPrimary
property color accentHover: Appearance.colors.colPrimaryHover property color accentHover: Appearance.colors.colPrimaryHover
property color accentActive: Appearance.colors.colPrimaryActive property color accentActive: Appearance.colors.colPrimaryActive
@@ -39,9 +39,10 @@ Button {
} }
} }
property color fgColor: { property color fgColor: {
if (!root.enabled) return root.colForegroundDisabled
if (root.checked) return root.colForegroundToggled if (root.checked) return root.colForegroundToggled
if (root.enabled) return root.colForeground if (root.enabled) return root.colForeground
return root.colForegroundDisabled return root.colForeground
} }
property alias horizontalAlignment: buttonText.horizontalAlignment property alias horizontalAlignment: buttonText.horizontalAlignment
font { font {
@@ -76,8 +76,9 @@ Menu {
contentItem: Item { contentItem: Item {
implicitWidth: menuListView.implicitWidth implicitWidth: menuListView.implicitWidth
implicitHeight: menuListView.implicitHeight implicitHeight: menuListView.implicitHeight
ListView { WListView {
id: menuListView id: menuListView
interactive: contentHeight > height
anchors { anchors {
left: parent.left left: parent.left
right: parent.right right: parent.right
@@ -87,6 +88,7 @@ Menu {
topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins
bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin
} }
clip: true
implicitHeight: contentHeight implicitHeight: contentHeight
implicitWidth: Array.from({ implicitWidth: Array.from({
length: count length: count
@@ -6,6 +6,7 @@ import Quickshell
import Quickshell.Hyprland import Quickshell.Hyprland
import qs.modules.common import qs.modules.common
import qs.modules.common.functions import qs.modules.common.functions
import qs.modules.common.widgets
import qs.modules.waffle.looks import qs.modules.waffle.looks
MenuItem { MenuItem {
@@ -14,11 +15,11 @@ MenuItem {
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1) property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
property color colBackgroundHover: Looks.colors.bg2Hover property color colBackgroundHover: Looks.colors.bg2Hover
property color colBackgroundActive: Looks.colors.bg2Active property color colBackgroundActive: Looks.colors.bg2Active
property color colBackgroundToggled: Looks.colors.accent property color colBackgroundToggled: Looks.colors.bg2Hover
property color colBackgroundToggledHover: Looks.colors.accentHover property color colBackgroundToggledHover: Looks.colors.bg2Active
property color colBackgroundToggledActive: Looks.colors.accentActive property color colBackgroundToggledActive: Looks.colors.bg2Hover
property color colForeground: Looks.colors.fg property color colForeground: Looks.colors.fg
property color colForegroundToggled: Looks.colors.accentFg property color colForegroundToggled: Looks.colors.fg
property color colForegroundDisabled: ColorUtils.transparentize(Looks.colors.subfg, 0.4) property color colForegroundDisabled: ColorUtils.transparentize(Looks.colors.subfg, 0.4)
property color color: { property color color: {
if (!root.enabled) if (!root.enabled)
@@ -70,27 +71,57 @@ MenuItem {
implicitHeight: Math.max(28, contentItem.implicitHeight) + topInset + bottomInset implicitHeight: Math.max(28, contentItem.implicitHeight) + topInset + bottomInset
implicitWidth: contentItem.implicitWidth + leftInset + rightInset + leftPadding + rightPadding implicitWidth: contentItem.implicitWidth + leftInset + rightInset + leftPadding + rightPadding
contentItem: RowLayout { contentItem: Item {
id: contentLayout implicitWidth: contentLayout.implicitWidth
spacing: 12 implicitHeight: contentLayout.implicitHeight
FluentIcon {
id: buttonIcon RowLayout {
monochrome: true id: contentLayout
implicitSize: 20 anchors.fill: parent
Layout.fillWidth: false spacing: 12
Layout.alignment: Qt.AlignVCenter FluentIcon {
color: root.fgColor id: buttonIcon
visible: root.icon.name !== ""; monochrome: true
icon: root.icon.name implicitSize: 20
Layout.fillWidth: false
Layout.alignment: Qt.AlignVCenter
color: root.fgColor
visible: root.icon.name !== ""
icon: root.icon.name
}
WText {
id: buttonText
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
text: root.text
horizontalAlignment: Text.AlignLeft
font.pixelSize: Looks.font.pixelSize.large
color: root.fgColor
}
} }
WText {
id: buttonText WFadeLoader {
Layout.fillWidth: true anchors {
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft verticalCenter: parent.verticalCenter
text: root.text left: parent.left
horizontalAlignment: Text.AlignLeft leftMargin: -root.leftPadding + width
font.pixelSize: Looks.font.pixelSize.large }
color: root.fgColor shown: root.checked
sourceComponent: Rectangle {
implicitWidth: 3
implicitHeight: 3
radius: width / 2
color: Looks.colors.accent
property bool forceZeroHeight: true
height: forceZeroHeight ? 0 : Math.max(root.down ? 10 : 16, root.background.height - 18 * 2)
Component.onCompleted: {
forceZeroHeight = false;
}
Behavior on height {
animation: Looks.transition.resize.createObject(this)
}
}
} }
} }
} }
@@ -12,6 +12,7 @@ Item {
id: root id: root
property Item contentItem property Item contentItem
property real radius: Looks.radius.large property real radius: Looks.radius.large
property alias color: contentRect.color
property alias border: borderRect property alias border: borderRect
property alias borderColor: borderRect.border.color property alias borderColor: borderRect.border.color
property alias borderWidth: borderRect.border.width property alias borderWidth: borderRect.border.width
@@ -42,7 +43,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
z: 0 z: 0
color: Looks.colors.bgPanelFooterBase color: Looks.colors.bgPanelFooterBackground
implicitWidth: contentItem.implicitWidth implicitWidth: contentItem.implicitWidth
implicitHeight: contentItem.implicitHeight implicitHeight: contentItem.implicitHeight
layer.enabled: true layer.enabled: true
@@ -0,0 +1,38 @@
import QtQuick
import QtQuick.Layouts
import qs.modules.common
import qs.modules.common.widgets
Item {
id: root
property real padding: 9
property alias colBackground: background.color
property alias spacing: toolbarLayout.spacing
property alias radius: background.radius
default property alias data: toolbarLayout.data
implicitWidth: background.implicitWidth
implicitHeight: background.implicitHeight
Rectangle {
id: background
anchors.fill: parent
implicitHeight: 50
implicitWidth: toolbarLayout.implicitWidth + root.padding * 2
radius: Looks.radius.large
color: Looks.colors.bg0Base
border.width: 1
border.color: Looks.colors.bg1Border
RowLayout {
id: toolbarLayout
spacing: 4
anchors {
fill: parent
margins: root.padding
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More