danshari!

This commit is contained in:
2026-03-12 03:49:47 +01:00
parent ec92891e4d
commit 55090c6415
62 changed files with 19 additions and 11 deletions
-174
View File
@@ -1,174 +0,0 @@
* {
all: unset;
transition: 200ms ease-out;
}
.lyrics-window {
background-color: $bg;
border-radius: 14px;
border: 2px solid $border;
}
.lyrics-window-single {
background-color: rgba(30, 30, 46);
border-radius: 14px;
border: 2px solid $border;
}
.lyrics-box {
margin: 20px 10px 0 20px;
min-width: 500px;
min-height: 70px;
background-color: $gray-alt;
border-radius: 15px;
padding: 10px;
box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.lyrics-box-single {
margin: 5px 0px 5px 10px;
min-width: 735px;
}
.lyrics-text {
color: $fg;
font-size: 15px;
font-family: 'Maple Mono NF CN', 'Maple Mono CN', monospace;
}
.lyrics-text-single {
color: $fg;
font-size: 15px;
font-family: 'Maple Mono NF CN', 'Maple Mono CN', monospace;
min-height: 28px;
}
.control-box {
margin: 20px 10px 0 0;
padding: 6px;
min-height: 90px;
}
.offset-minus,
.offset-reset,
.offset-plus,
.offset-clear {
padding: 0px 6px;
margin: 0px 4px 0px 4px;
font-family: 'MesloLGM Nerd Font Mono';
font-size: 25px;
min-width: 16px;
}
.offset-minus-single,
.offset-plus-single,
.offset-reset-single,
.info-single {
padding: 0px 6px;
margin: 0;
font-family: 'MesloLGM Nerd Font Mono';
font-size: 20px;
min-width: 16px;
}
.offset-minus,
.offset-minus-single {
color: $blue;
}
.offset-plus,
.offset-plus-single {
color: $yellow;
}
.offset-reset,
.offset-reset-single {
color: $green;
}
.offset-clear {
color: $red;
}
.info-single {
color: $cyan;
}
.offset-minus:hover,
.offset-reset:hover,
.offset-plus:hover,
.offset-clear:hover,
.offset-minus-single:hover,
.offset-plus-single:hover,
.offset-reset-single:hover,
.lyrics-info:hover,
.info-single:hover,
.player-prev:hover,
.player-next:hover,
.player-pp:hover {
color: $fg;
}
.player-music-slider-box {
padding: 12px;
margin: 10px 0 20px 20px;
border-radius: 15px;
background-color: $gray-alt;
box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
min-height: 16px;
}
.player-music-slider trough {
background-color: $gray;
}
.player-music-slider highlight {
background-color: $border;
padding: 3px;
}
.player-music-slider {
min-width: 200px;
}
.player-controls-box {
margin: 10px 0 20px 20px;
}
.player-pp,
.player-next,
.player-prev,
.lyrics-info {
padding: 0px 6px;
margin: 0px 4px 0px 4px;
font-family: 'MesloLGM Nerd Font Mono';
font-size: 25px;
min-width: 16px;
color: $fg-alt;
}
.lyrics-info {
color: $cyan;
}
.offset-box {
padding: 11px;
margin: 10px 20px 20px 10px;
border-radius: 15px;
// background-color: $gray-alt;
// box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.offset-label {
color: $fg-alt;
font-size: 15px;
font-family: 'Maple Mono NF CN', 'Maple Mono CN', monospace;
margin-right: 10px;
}
.offset-value {
color: $fg;
font-size: 15px;
font-family: 'Maple Mono NF CN', 'Maple Mono CN', monospace;
margin-right: 10px;
}
-95
View File
@@ -1,95 +0,0 @@
(defpoll lyriclines :interval "500ms" "spotify-lyrics print -l 3 -a 1 -f \"$HOME/.local/state/eww/lyrics/offset\" | Lyrics/scripts/colorize.sh 2")
(deflisten lyricline "spotify-lyrics listen -l 1 -f \"$HOME/.local/state/eww/lyrics/offset\"")
(defpoll position :interval "1s" "spotify-lyrics position")
(defpoll length :interval "1s" "spotify-lyrics length")
(defpoll offset :interval "1s" "cat $HOME/.local/state/eww/lyrics/offset")
(defpoll play-button :interval "1s" "if spotify-lyrics status; then echo \"󰏤\"; else echo \"󰐊\"; fi")
(defvar hover false)
(defwidget lyrics []
(box :class "lyrics-window" :space-evenly "false" :orientation "v"
(box :class "lyrics-container" :space-evenly "false" :orientation "h"
(box :class "lyrics-box" :vexpand "false" :hexpand "false" :valign "center" :space-evenly "true" :orientation "v"
(label :class "lyrics-text"
:vexpand "false" :hexpand "false" :space-evenly "false"
:halign "start"
:unindent "false" :truncate "false" :truncate-left "false"
:markup lyriclines
)
)
(box :class "control-box" :vexpand "false" :hexpand "false" :space-evenly "true" :orientation "v"
(box :class "control-row-1" :space-evenly "false" :orientation "h"
(button :class "offset-plus" :onclick "Lyrics/scripts/lyric-offset.py +500" "󰾆")
(button :class "offset-minus" :onclick "Lyrics/scripts/lyric-offset.py -500" "󰓅")
)
(box :class "control-row-1" :space-evenly "false" :orientation "h"
(button :class "offset-reset" :onclick "Lyrics/scripts/lyric-offset.py" "󰾅")
(button :class "offset-clear" :onclick "Lyrics/scripts/lyric-clear.sh $(spotify-lyrics trackid)" "󰑙")
)
)
)
(box :class "player-controls" :space-evenly "false" :orientation "h"
(box :class "player-music-slider-box"
:vexpand "false" :hexpand "false" :valign "center" :space-evenly "false" :orientation "h"
(eventbox :onhover "eww update hover=true"
:onhoverlost "eww update hover=false"
:cursor "pointer"
:space-evenly "false"
(scale :orientation "h" :class "player-music-slider"
:min 0 :max length :value position
:onchange { hover ? "spotify-lyrics set-position {}" : "" })
)
)
(box :class "player-controls-box"
:vexpand "false" :hexpand "false" :valign "center" :space-evenly "false" :orientation "h"
(button :class "player-prev" :onclick "playerctl previous --player=spotify" "󰒮")
(button :class "player-pp" :onclick "playerctl play-pause --player=spotify" "${play-button}")
(button :class "player-next" :onclick "playerctl next --player=spotify" "󰒭")
(button :class "lyrics-info" :onclick "ghostty -e sh -c 'spotify-lyrics fetch | less' &" "")
)
(box :class "offset-box"
:vexpand "false" :hexpand "true" :valign "center" :halign "center" :space-evenly "false" :orientation "h"
(label :class "offset-label" :text "Offset (ms): ")
(label :class "offset-value" :text offset)
)
)
)
)
(defwidget lyrics-single []
(box :class "lyrics-window-single" :space-evenly "false" :orientation "h"
(box :class "lyrics-box-single"
:vexpand "false" :hexpand "false"
:valign "center" :space-evenly "false" :orientation "v"
(label :class "lyrics-text-single"
:vexpand "false" :hexpand "false" :space-evenly "false"
:halign "start"
:text lyricline
)
)
(box :class "control-box-single" :vexpand "false" :hexpand "false" :space-evenly "true" :orientation "v"
(box :class "control-row-1-single" :space-evenly "false" :orientation "h"
(button :class "info-single" :onclick "ghostty -e sh -c 'spotify-lyrics fetch | less' &" "")
(button :class "offset-plus-single" :onclick "Lyrics/scripts/lyric-offset.py +500" "󰾆")
(button :class "offset-reset-single" :onclick "Lyrics/scripts/lyric-offset.py" "󰾅")
(button :class "offset-minus-single" :onclick "Lyrics/scripts/lyric-offset.py -500" "󰓅")
)
)
)
)
(defwindow lyrics
:windowtype "normal"
:wm-ignore true
:monitor 0
:geometry (geometry :anchor "top center")
(lyrics)
)
(defwindow lyrics-single
:windowtype "normal"
:wm-ignore true
:monitor 0
:geometry (geometry :x 1108 :y -45)
(lyrics-single)
)
@@ -1,24 +0,0 @@
#!/usr/bin/env bash
HIGHLIGHT_COLOR="#cdd6f4" # text
NORMAL_COLOR="#7f849c" # overlay1
TARGET_LINE=1
[ -n "$1" ] && TARGET_LINE="$1"
mapfile -t lines
output=""
for i in "${!lines[@]}"; do
line_num=$((i + 1))
escaped_line=$(echo "${lines[$i]}" | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g')
[[ $i -gt 0 ]] && output+=$'\n' # +="\n" is not properly displayed in eww
if [[ $line_num -eq $TARGET_LINE ]]; then
output+="<span color=\"$HIGHLIGHT_COLOR\">$escaped_line</span>"
else
output+="<span color=\"$NORMAL_COLOR\">$escaped_line</span>"
fi
done
echo "$output"
@@ -1,9 +0,0 @@
#!/bin/sh
if [ -z "$1" ]; then
"spotify-lyrics" clear
notify-send -a "spotify-lyrics" "Cache Cleared" "Lyrics cache have been cleared."
else
"spotify-lyrics" clear "$1"
notify-send -a "spotify-lyrics" "Cache Cleared" "Lyrics cache for track $1 have been cleared."
fi
@@ -1,45 +0,0 @@
#!/usr/bin/env python3
APP_NAME = "spotify-lyrics"
STATE_DIR_NAME = "~/.local/state/eww/lyrics"
STATE_FILE_NAME = "offset"
def notify_send(title, message):
import subprocess
subprocess.run(["notify-send", "-t", "1000", "-a", APP_NAME, title, message], check=True)
def main():
import sys
import os
state_dir = os.path.expanduser(STATE_DIR_NAME)
if not os.path.exists(state_dir):
os.makedirs(state_dir)
offset_file = os.path.join(state_dir, STATE_FILE_NAME)
if not os.path.exists(offset_file):
with open(offset_file, "w") as f:
f.write("0")
if len(sys.argv) < 2:
new_offset = 0
else:
try:
increment = int(sys.argv[1])
with open(offset_file, "r") as f:
current_offset = int(f.read().strip())
new_offset = current_offset + increment
except ValueError:
print("Invalid input. Please provide an integer value.")
return
with open(offset_file, "w") as f:
f.write(str(new_offset))
notify_send("Lyrics Speed Changed", f"The offset has been changed to {new_offset} ms.")
if __name__ == "__main__":
main()
@@ -1,2 +0,0 @@
#!/bin/sh
-270
View File
@@ -1,270 +0,0 @@
* {
all: unset;
transition: 200ms ease-out;
}
.main-window {
background-color: $bg;
font-family: 'Sour Gummy', 'MesloLGM Nerd Font Mono', 'Noto Sans';
border-radius: 14px;
border: 2px solid $border;
}
.date-box {
// background-color: $bg;
margin: 20px 20px 0px 20px;
min-width: 290px;
padding: 20px 10px 20px 10px;
border-radius: 15px;
color: $fg;
// box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.time {
font-family: 'Sour Gummy ExtraLight';
font-weight: bold;
font-size: 100px;
margin-top: 24px;
}
.date {
font-size: 24px;
margin-top: 10px;
}
.weather-box {
background-color: $gray-alt;
margin: 20px 20px 0px 0px;
padding: 20px 10px 10px 20px;
border-radius: 15px;
box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.weather-desc {
color: $fg-alt;
font-size: 24px;
}
.weather-temp {
font-size: 36px;
color: $fg;
padding-top: 10px;
}
.weather-icon {
font-family: 'MesloLGM Nerd Font';
font-size: 60px;
margin-top: 5px;
margin-right: 20px;
}
.weather-updatetime {
color: $fg-alt;
font-size: 16px;
margin-top: 10px;
}
.stats-box {
background-color: $gray-alt;
margin: 20px 20px 0px 20px;
padding: 20px 35px 20px 25px;
border-radius: 15px;
box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.stats-header {
font-size: 24px;
font-weight: bold;
color: $gray;
}
.volume-icon,
.brightness-icon,
.cpu-icon,
.memory-icon {
font-size: 20px;
color: $fg;
}
.volume-scale trough,
.brightness-scale trough,
.cpu-scale trough,
.memory-scale trough {
all: unset;
background-color: $gray;
min-height: 10px;
border-radius: 15px;
margin-left: 10px;
}
.volume-scale highlight {
background-color: $sapphire;
border-radius: 15px;
}
.brightness-scale highlight {
background-color: $teal;
border-radius: 15px;
}
.cpu-scale highlight {
background-color: $yellow;
border-radius: 15px;
}
.memory-scale highlight {
background-color: $peach;
border-radius: 15px;
}
.fortune-box {
// background-color: $gray-alt;
margin: 20px 20px 0px 0px;
padding: 20px 35px 20px 25px;
border-radius: 15px;
// box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.fortune-header {
font-size: 24px;
font-weight: bold;
color: $gray;
}
.fortune-text {
font-family: 'Noto Sans';
font-size: 14px;
color: $fg;
margin-top: 10px;
}
.music-art-box {
background-size: cover;
background-repeat: no-repeat;
min-width: 455px;
min-height: 240px;
border-radius: 17px;
background-position: center;
margin: 20px 0px 0px 20px;
box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.music-title {
margin: 20px 0px 0px 20px;
font-size: 28px;
font-weight: bold;
color: $fg;
}
.music-artist {
margin: 10px 0px 0px 20px;
font-size: 20px;
color: $fg-alt;
}
.music-length {
margin: 90px 0px 0px 20px;
font-size: 18px;
font-weight: bold;
color: $fg-alt;
}
.music-stuff-box {
border-radius: 15px;
background: linear-gradient(to right, $bg-alt, transparent);
min-height: 240px;
}
.player-cover-box {
background-size: 140px;
min-height: 140px;
min-width: 140px;
border-radius: 20px;
background-repeat: no-repeat;
background-position: center;
}
.player-box {
margin: 40px 30px 30px 50px;
}
.player-info-box {
font-size: 16px;
}
.player-info-title,
.player-info-artist {
color: $border;
font-weight: bold;
}
.player-info-album,
.player-info-length {
color: $fg-alt;
}
.player-info-button {
background-color: $gray-alt;
padding: 15px;
border-radius: 20px;
font-weight: bold;
margin-top: 10px;
}
.cavabar {
font-family: 'Noto Sans';
font-size: 14px;
color: $border;
}
.music-controls-box {
margin: 20px 20px 0px 20px;
// background-color: $gray-alt;
padding: 0px 23px 0px 23px;
border-radius: 15px;
text-shadow: 0px 0px 10px rgba(0, 0, 0, 1);
// box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.music-next,
.music-previous {
font-size: 30px;
}
.music-pp {
font-size: 44px;
color: $fg;
}
.music-next:hover,
.music-previous:hover,
.music-pp:hover {
color: $orange;
}
.profile-stuff-box {
margin: 20px 20px 20px 20px;
// background-color: $gray-alt;
border-radius: 15px;
padding: 15px 20px 15px 20px;
// box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.profile-img {
border-radius: 10px;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
min-width: 90px;
box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.5);
}
.profile-stuff {
padding: 7px 0px 0px 30px;
font-size: 20px;
color: $fg;
}
.profile-name {
font-weight: bold;
}
-116
View File
@@ -1,116 +0,0 @@
;; variables
(defvar window false)
(defpoll time :interval "1s" "date '+%H:%M'")
(defpoll date :interval "1s" "date '+%A, %B %d'")
(deflisten notifications-cards "Main/scripts/logger.zsh subscribe")
(defpoll notifications-crits :interval "1s" "Main/scripts/logger.zsh crits")
(defpoll weather-icon :interval "5m" "Main/scripts/weather --icon")
(defpoll weather-temp :interval "5m" "Main/scripts/weather --temp")
(defpoll weather-desc :interval "5m" "Main/scripts/weather --stat")
(defpoll weather-updatetime :interval "5m" "Main/scripts/weather --updatetime")
(deflisten weather-color :initial "#7aa2f7" "Main/scripts/weather --hex")
(defpoll calendar-day :interval "20h" "+%d")
(defpoll calendar-year :interval "20h" "+%Y")
(defpoll calendar-month :interval "20h" "%+B")
(defpoll cpu :interval "1s" "Main/scripts/system --cpu")
(defpoll memory :interval "1s" "Main/scripts/system --mem")
(defpoll profile-image :interval "10h" "Main/scripts/details --image")
(defpoll profile-username :interval "1h" "whoami")
(defpoll profile-name :interval "1h" "Main/scripts/details --name")
(defpoll profile-kernel :interval "1h" "Main/scripts/details --kernel")
(defpoll profile-os :interval "1h" "Main/scripts/details --os")
(defpoll music-length :interval "1s" "Main/scripts/music-length")
(defpoll music-title :interval "1s" "Main/scripts/music-title --status")
(defpoll music-pp :interval "1s" "Main/scripts/music-title --icon")
(defpoll music-artist :interval "1s" "Main/scripts/music-artist")
(defpoll music-art :interval "1s" "Main/scripts/music-art")
(defpoll music-art-blur :interval "1s" "Main/scripts/music-art-blur")
(defpoll volume :interval "1s" "Main/scripts/system --vol")
(defpoll brightness :interval "1s" "Main/scripts/system --bri")
(defpoll fortune :interval "1h" "Main/scripts/fortune-split 32 6")
(deflisten cava "Main/scripts/cava")
(defpoll title :interval "1s" "Main/scripts/music-title --status")
(defpoll artist :interval "1s" "Main/scripts/player --artist")
(defpoll album :interval "1s" "Main/scripts/player --album")
(defpoll length-info :interval "1s" "Main/scripts/player --length-info")
(defvar volume-hover false)
(defvar brightness-hover false)
;; widgets
(defwidget main []
(box :class "main-window" :space-evenly "false" :orientation "v"
(box :class "top-row" :orientation "h" :space-evenly "false"
(box :class "date-box" :space-evenly "false" :orientation "v" :hexpand "false" :vexpand "false"
(label :class "time" :text time)
(label :class "date" :text date))
(box :class "weather-box" :space-evenly "false" :hexpand "true" :orientation "v"
(label :class "weather-desc" :halign "start" :text weather-desc)
(label :class "weather-temp" :halign "start" :text weather-temp)
(label :class "weather-updatetime" :halign "start" :text weather-updatetime)
(label :class "weather-icon" :halign "end" :valign "start" :text weather-icon :style "color: ${weather-color}")))
(box :class "second-row" :orientation "h" :space-evenly "false"
(box :class "stats-box" :space-evenly "false" :orientation "v" :spacing 8
(label :class "stats-header" :halign "start" :text "Stats")
(box :class "volume-stats" :hexpand "false" :vexpand "false" :space-evenly "false"
(label :tooltip "${volume}%" :class "volume-icon" :text "󰕾")
(eventbox :class "volume-eventbox"
:onhover "eww update volume-hover=true"
:onhoverlost "eww update volume-hover=false"
:cursor "pointer"
:space-evenly "false"
(scale :min 0 :max 101 :class "volume-scale" :width 150
:value {volume == "" ? 0 : volume}
:round-digits 0
:onchange { volume-hover ? "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ {}%" : "" }
)))
(box :class "brightness-stats" :hexpand "false" :vexpand "false" :space-evenly "false"
(label :tooltip "${brightness}%" :class "brightness-icon" :text "󰃠")
(eventbox :class "brightness-eventbox"
:onhover "eww update brightness-hover=true"
:onhoverlost "eww update brightness-hover=false"
:cursor "pointer"
:space-evenly "false"
(scale :min 0 :max 101 :class "brightness-scale" :width 150
:value {brightness == "" ? 0 : brightness}
:round-digits 0
:onchange { brightness-hover ? "brightnessctl set {}\% --class=backlight" : "" })))
(box :class "cpu-stats" :hexpand "false" :vexpand "false" :space-evenly "false"
(label :tooltip "${cpu}%" :class "cpu-icon" :text "󰘚")
(scale :min 0 :max 101 :active false :value {cpu == "" ? 0 : cpu} :class "cpu-scale" :width 150))
(box :class "memory-stats" :hexpand "false" :vexpand "false" :space-evenly "false"
(label :tooltip "${memory}%" :class "memory-icon" :text "󰍛")
(scale :min 0 :max 101 :active false :value {memory == "" ? 0 : memory} :class "memory-scale" :width 150)))
(box :class "fortune-box" :space-evenly "false" :hexpand "true" :orientation "v"
(label :class "fortune-header" :halign "start" :text "Fortune")
(label :class "fortune-text" :halign "start" :text fortune :show-truncated true :wrap true)))
(box :class "third-row" :orientation "h" :space-evenly "false"
(box :class "music-art-box" :space-evenly "false" :orientation "v" :hexpand "false" :vexpand "false" :style "background-image: url(\"${music-art-blur}\");"
(box :class "music-stuff-box" :space-evenly "false" :hexpand "false" :vexpand "false" :orientation "v"
(box :class "player-box" :hexpand "false" :vexpand "false" :space-evenly "true"
(box :class "player-info-box" :hexpand "false" :vexpand "false" :space-evenly "false" :orientation "v" :spacing 15
(label :class "player-info-title" :text "󰝚 Title: ${title}" :halign "start" :limit-width 30 :tooltip "${title}")
(label :class "player-info-artist" :text "󰠃 Artist: ${artist}" :halign "start" :limit-width 30 :tooltip "${artist}")
(label :class "player-info-album" :text "󰀥 Album: ${album}" :halign "start" :limit-width 30 :tooltip "${album}")
(label :class "player-info-length" :text "󰦚 Length: ${length-info}" :halign "start" :tooltip "${length-info}"))
(box :class "player-cover-box" :hexpand "false" :halign "end" :vexpand "false" :space-evenly "false" :style "background-image: url(\"${music-art}\");"))
(label :vexpand "true" :hexpand "false" :space-evenly "false" :valign "end"
:class "cavabar"
:text cava)))
(box :class "music-controls-box" :space-evenly "true" :hexpand "true" :vexpand "false" :orientation "v"
(button :class "music-previous" :halign "center" :onclick "playerctl previous" "󰒮")
(button :class "music-pp" :halign "center" :onclick "playerctl play-pause" "${music-pp}")
(button :class "music-next" :halign "center" :onclick "playerctl next" "󰒭")))
(box :class "profile-stuff-box" :space-evenly "false" :hexpand "false" :vexpand "false" :orientation "h" :height 140
(box :class "profile-img" :space-evenly "false" :hexpand "false" :vexpand "false" :orientation "v" :style "background-image: url(\"${profile-image}\");")
(box :class "profile-stuff" :orientation "v" :space-evenly "false" :hexpand "false" :vexpand "false" :spacing 8
(label :class "profile-name" :text profile-name :halign "start")
(label :class "profile-os" :text profile-os :halign "start")
(label :class "profile-kernel" :text profile-kernel :halign "start")))))
;; windows
(defwindow main
:windowtype "normal"
:wm-ignore true
:monitor 0
:geometry (geometry :x 0 :y 0)
(main))
Binary file not shown.

Before

Width:  |  Height:  |  Size: 919 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

-40
View File
@@ -1,40 +0,0 @@
#! /bin/bash
bar="▁▂▃▄▅▆▇█"
dict="s/;//g;"
# creating "dictionary" to replace char with bar
i=0
while [ $i -lt ${#bar} ]
do
dict="${dict}s/$i/${bar:$i:1}/g;"
i=$((i=i+1))
done
# make sure to clean pipe
pipe="/tmp/cava.fifo"
if [ -p $pipe ]; then
unlink $pipe
fi
mkfifo $pipe
# write cava config
config_file="/tmp/waybar_cava_config"
echo "
[general]
bars = 30
[output]
method = raw
raw_target = $pipe
data_format = ascii
ascii_max_range = 7
" > $config_file
# run cava in the background
cava -p $config_file &
# reading data from fifo
while read -r cmd; do
echo $cmd | sed $dict
done < $pipe
@@ -1,28 +0,0 @@
#!/bin/bash
if [[ $1 == "--image" ]]; then
FILE=$HOME/.face
if [[ -f "$FILE" ]]; then
echo "../../.face"
else
echo "Main/images/profile.png"
fi
fi
if [[ $1 == "--name" ]]; then
fullname=$(getent passwd "$(whoami)" | cut -d ':' -f 5 | cut -d ',' -f 1 | tr -d "\n")
if [ -z "$fullname" ]; then
echo "$(whoami)@$(hostnamectl | awk 'FNR==1 {print $3}')"
else
echo "$fullname"
fi
fi
if [[ $1 == "--kernel" ]]; then
echo "$(uname -r)"
fi
if [[ $1 == "--os" ]]; then
echo "$(cat /etc/os-release | awk 'NR==1'| awk -F '"' '{print $2}')"
fi
@@ -1,92 +0,0 @@
#!/usr/bin/env python3
import sys
import subprocess
def wrap(text, width, height):
lines = []
paragraphs = text.split('\n')
for paragraph in paragraphs:
if len(lines) >= height:
return []
# Skip empty paragraphs
if not paragraph.strip():
lines.append('')
continue
current_line = ''
words = paragraph.split()
for word in words:
if current_line:
test_line = current_line + ' ' + word
else:
test_line = word
if len(test_line) <= width:
current_line = test_line
else:
if current_line:
lines.append(current_line)
current_line = word
else:
while len(word) > width:
lines.append(word[:width])
word = word[width:]
current_line = word
if current_line:
lines.append(current_line)
return lines
RETRY_LIMIT = 10
def main():
if len(sys.argv) != 3:
print("Usage: fortune.py <width> <height>")
sys.exit(1)
try:
width = int(sys.argv[1])
if width <= 0:
raise ValueError()
height = int(sys.argv[2])
if height <= 0:
raise ValueError()
except ValueError:
print("Invalid argument.")
sys.exit(1)
i = 0
while True:
if i >= RETRY_LIMIT:
print("Failed to get fortune after multiple attempts.")
sys.exit(1)
i += 1
try:
buffer = subprocess.check_output(['fortune', '-s'], text=True)
except subprocess.CalledProcessError as e:
print(f"Error running fortune: {e}")
sys.exit(1)
lines = wrap(buffer, width, height)
if lines:
break
else:
print("retrying...")
for line in lines:
print(line)
if __name__ == "__main__":
main()
@@ -1,32 +0,0 @@
#!/bin/bash
# Set the source audio player here.
# Players supporting the MPRIS spec are supported.
# Examples: spotify, vlc, chrome, mpv and others.
# Use `playerctld` to always detect the latest player.
# See more here: https://github.com/altdesktop/playerctl/#selecting-players-to-control
PLAYER="playerctld"
# Format of the information displayed
# Eg. {{ artist }} - {{ album }} - {{ title }}
# See more attributes here: https://github.com/altdesktop/playerctl/#printing-properties-and-metadata
FORMAT="{{ album }}"
PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status 2>/dev/null)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
STATUS=$PLAYERCTL_STATUS
else
STATUS="No Album"
fi
if [ "$STATUS" = "Stopped" ]; then
echo "No Album"
elif [ "$STATUS" = "Paused" ]; then
playerctl --player=$PLAYER metadata --format "$FORMAT"
elif [ "$STATUS" = "No Alnum" ]; then
echo "$STATUS"
else
playerctl --player=$PLAYER metadata --format "$FORMAT"
fi
@@ -1,45 +0,0 @@
#!/bin/bash
tmp_dir="$HOME/.cache/eww/music-art"
art_path=$tmp_dir/temp.png
art_blur_path="$tmp_dir/temp-blur.png"
cache_path="$tmp_dir/cache.conf"
cache_blur_path="$tmp_dir/cache-blur.conf"
log_path="$tmp_dir/log.txt"
default_path="$HOME/.config/eww/Main/images/default-music.svg"
default_blur_path="$HOME/.config/eww/Main/images/default-music-blur.png"
mkdir -p "$tmp_dir"
artlink="$(playerctl metadata mpris:artUrl)"
[ -f "$cache_path" ] && . "$cache_path"
# avoid unnecessary downloads
if [ -z "$artlink" ]; then
art_path="$default_path"
art_blur_path="$default_blur_path"
elif [[ "$cachedlink" != "$artlink" ]]; then
echo "cachedlink=\"$artlink\"" > "$cache_path"
echo "Updating music art: $artlink" >> "$log_path"
if [[ "$artlink" == "file://"* ]]; then
# Handle local file URLs
local_file_path="${artlink#file://}"
if [[ -f "$local_file_path" ]]; then
magick "$local_file_path" "$art_path" || exit 1
fi
magick "$art_path" -blur 0x8 "$art_blur_path"
elif [[ "$artlink" =~ ^https?:// ]]; then
# Handle HTTP/HTTPS URLs
curl -s "$artlink" --output "$art_path"_orig || exit 1
magick "$art_path"_orig "$art_path" || exit 1
magick "$art_path" -blur 0x8 "$art_blur_path"
else
echo "Unknown art link format: $artlink" >> "$log_path"
art_path="$default_path"
art_blur_path="$default_blur_path"
fi
fi
echo "path=\"$art_blur_path\"" > "$cache_blur_path"
echo "$art_path"
@@ -1,8 +0,0 @@
#!/bin/bash
tmp_dir="$HOME/.cache/eww/music-art"
cache_blur_path="$tmp_dir/cache-blur.conf"
. "$cache_blur_path"
echo "$path"
@@ -1,32 +0,0 @@
#!/bin/bash
# Set the source audio player here.
# Players supporting the MPRIS spec are supported.
# Examples: spotify, vlc, chrome, mpv and others.
# Use `playerctld` to always detect the latest player.
# See more here: https://github.com/altdesktop/playerctl/#selecting-players-to-control
PLAYER="playerctld"
# Format of the information displayed
# Eg. {{ artist }} - {{ album }} - {{ title }}
# See more attributes here: https://github.com/altdesktop/playerctl/#printing-properties-and-metadata
FORMAT="{{ artist }}"
PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status 2>/dev/null)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
STATUS=$PLAYERCTL_STATUS
else
STATUS="No Artist"
fi
if [ "$STATUS" = "Stopped" ]; then
echo "No Artist"
elif [ "$STATUS" = "Paused" ]; then
playerctl --player=$PLAYER metadata --format "$FORMAT"
elif [ "$STATUS" = "No Artist" ]; then
echo "$STATUS"
else
playerctl --player=$PLAYER metadata --format "$FORMAT"
fi
@@ -1,32 +0,0 @@
#!/bin/bash
# Set the source audio player here.
# Players supporting the MPRIS spec are supported.
# Examples: spotify, vlc, chrome, mpv and others.
# Use `playerctld` to always detect the latest player.
# See more here: https://github.com/altdesktop/playerctl/#selecting-players-to-control
PLAYER="playerctld"
# Format of the information displayed
# Eg. {{ artist }} - {{ album }} - {{ title }}
# See more attributes here: https://github.com/altdesktop/playerctl/#printing-properties-and-metadata
FORMAT="{{ duration(position) }} / {{ duration(mpris:length) }}"
PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status 2>/dev/null)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
STATUS=$PLAYERCTL_STATUS
else
STATUS="--:-- / --:--"
fi
if [ "$STATUS" = "Stopped" ]; then
echo "--:-- / --:--"
elif [ "$STATUS" = "Paused" ]; then
playerctl --player=$PLAYER metadata --format "$FORMAT"
elif [ "$STATUS" = "--:-- / --:--" ]; then
echo "$STATUS"
else
playerctl --player=$PLAYER metadata --format "$FORMAT"
fi
@@ -1,32 +0,0 @@
#!/bin/bash
# Set the source audio player here.
# Players supporting the MPRIS spec are supported.
# Examples: spotify, vlc, chrome, mpv and others.
# Use `playerctld` to always detect the latest player.
# See more here: https://github.com/altdesktop/playerctl/#selecting-players-to-control
PLAYER="playerctld"
# Format of the information displayed
# Eg. {{ artist }} - {{ album }} - {{ title }}
# See more attributes here: https://github.com/altdesktop/playerctl/#printing-properties-and-metadata
FORMAT="{{ duration(mpris:length) }}"
PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status 2>/dev/null)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
STATUS=$PLAYERCTL_STATUS
else
STATUS="--:--"
fi
if [ "$STATUS" = "Stopped" ]; then
echo "--:--"
elif [ "$STATUS" = "Paused" ]; then
playerctl --player=$PLAYER metadata --format "$FORMAT"
elif [ "$STATUS" = "--:--" ]; then
echo "$STATUS"
else
playerctl --player=$PLAYER metadata --format "$FORMAT"
fi
@@ -1,4 +0,0 @@
#!/bin/bash
POS=$(playerctl -p spotify position)
python -c "print(float($POS*1000000))"
@@ -1,43 +0,0 @@
#!/bin/bash
# Set the source audio player here.
# Players supporting the MPRIS spec are supported.
# Examples: spotify, vlc, chrome, mpv and others.
# Use `playerctld` to always detect the latest player.
# See more here: https://github.com/altdesktop/playerctl/#selecting-players-to-control
PLAYER="playerctld"
# Format of the information displayed
# Eg. {{ artist }} - {{ album }} - {{ title }}
# See more attributes here: https://github.com/altdesktop/playerctl/#printing-properties-and-metadata
FORMAT="{{ title }}"
PLAYERCTL_STATUS=$(playerctl --player=$PLAYER status 2>/dev/null)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
STATUS=$PLAYERCTL_STATUS
else
STATUS="Nothing is playing"
fi
if [ "$1" == "--status" ]; then
if [ "$STATUS" = "Stopped" ]; then
echo "Nothing is playing"
elif [ "$STATUS" = "Paused" ]; then
playerctl --player=$PLAYER metadata --format "$FORMAT"
elif [ "$STATUS" = "Nothing is playing" ]; then
echo "$STATUS"
else
playerctl --player=$PLAYER metadata --format "$FORMAT"
fi
fi
if [ "$1" == "--icon" ]; then
if [[ $STATUS == "Playing" ]]; then
echo "󰏤"
else
echo "󰐊"
fi
fi
@@ -1,57 +0,0 @@
#!/bin/bash
if [[ $1 == "--length" ]]; then
playerctl -p spotify metadata mpris:length
fi
if [[ $1 == "--open" ]]; then
URL=$(playerctl -p spotify metadata xesam:url)
echo "$URL?go=1&utm_medium=desktop"
fi
if [[ $1 == "--artist" ]]; then
"$HOME/.config/eww/Main/scripts/music-artist"
fi
if [[ $1 == "--length-time" ]]; then
"$HOME/.config/eww/Main/scripts/music-length"
fi
if [[ $1 == "--length-info" ]]; then
"$HOME/.config/eww/Main/scripts/music-length-info"
fi
if [[ $1 == "--cover" ]]; then
"$HOME/.config/eww/Main/scripts/music-art"
fi
if [[ $1 == "--album" ]]; then
"$HOME/.config/eww/Main/scripts/music-album"
fi
if [[ $1 == "--current-volume" ]]; then
VOLUME=$(playerctl -p spotify volume)
echo $(python -c "print(float("$VOLUME")*100)")
fi
if [[ $1 == "--volume" ]]; then
CURRENT_VOLUME=$2
NOW_VOLUME=$(python -c "print(float($CURRENT_VOLUME)/100)")
playerctl -p spotify volume "$NOW_VOLUME"
fi
if [[ $1 == "--shuffle" ]]; then
if [[ $(playerctl -p spotify shuffle) == "On" ]]; then
playerctl -p spotify shuffle off
else
playerctl -p spotify shuffle On
fi
fi
if [[ $1 == "--current-pos" ]]; then
playerctl -p spotify position --format '{{ duration(position) }}'
fi
if [[ $1 == "--launch-lyrics" ]]; then
eww open --toggle lyrics
fi
@@ -1,70 +0,0 @@
#!/bin/bash
## Files and Data
PREV_TOTAL=0
PREV_IDLE=0
cpuFile="/tmp/.cpu_usage"
## Get CPU usage
get_cpu() {
if [[ -f "${cpuFile}" ]]; then
fileCont=$(cat "${cpuFile}")
PREV_TOTAL=$(echo "${fileCont}" | head -n 1)
PREV_IDLE=$(echo "${fileCont}" | tail -n 1)
fi
CPU=(`cat /proc/stat | grep '^cpu '`) # Get the total CPU statistics.
unset CPU[0] # Discard the "cpu" prefix.
IDLE=${CPU[4]} # Get the idle CPU time.
# Calculate the total CPU time.
TOTAL=0
for VALUE in "${CPU[@]:0:4}"; do
let "TOTAL=$TOTAL+$VALUE"
done
if [[ "${PREV_TOTAL}" != "" ]] && [[ "${PREV_IDLE}" != "" ]]; then
# Calculate the CPU usage since we last checked.
let "DIFF_IDLE=$IDLE-$PREV_IDLE"
let "DIFF_TOTAL=$TOTAL-$PREV_TOTAL"
let "DIFF_USAGE=(1000*($DIFF_TOTAL-$DIFF_IDLE)/$DIFF_TOTAL+5)/10"
echo "${DIFF_USAGE}"
else
echo "?"
fi
# Remember the total and idle CPU times for the next check.
echo "${TOTAL}" > "${cpuFile}"
echo "${IDLE}" >> "${cpuFile}"
}
## Get Used memory
get_mem() {
printf "%.0f\n" "$(free -m | grep Mem | awk '{print ($3/$2)*100}')"
}
## Get Volume
get_vol() {
pamixer --get-volume
}
## Get Brightness
get_brightness() {
if [ -z "$DISPLAY_DEVICE" ]; then
brightnessctl i --machine-readable | tr ',' ' ' | awk '{print $4}' | tr -d '%'
else
brightnessctl i -d $DISPLAY_DEVICE --machine-readable | tr ',' ' ' | awk '{print $4}' | tr -d '%'
fi
}
## Execute accordingly
if [[ "$1" == "--cpu" ]]; then
get_cpu
elif [[ "$1" == "--mem" ]]; then
get_mem
elif [[ "$1" == "--vol" ]]; then
get_vol
elif [[ "$1" == "--bri" ]]; then
get_brightness
fi
-157
View File
@@ -1,157 +0,0 @@
#!/bin/bash
## Collect data
cache_dir="$HOME/.cache/eww/weather"
cache_weather_stat=${cache_dir}/weather-stat
cache_weather_degree=${cache_dir}/weather-degree
cache_weather_hex=${cache_dir}/weather-hex
cache_weather_icon=${cache_dir}/weather-icon
cache_weather_updatetime=${cache_dir}/weather-updatetime
if [[ -z "$OPENWEATHER_API_KEY" ]]; then
echo "Please set the OPENWEATHER_API_KEY environment variable."
exit 1
fi
if [[ -z "$OPENWEATHER_LAT" ]]; then
echo "Please set the OPENWEATHER_LAT environment variable."
exit 1
fi
if [[ -z "$OPENWEATHER_LON" ]]; then
echo "Please set the OPENWEATHER_LON environment variable."
exit 1
fi
## Weather data
KEY=$OPENWEATHER_API_KEY
LAT=$OPENWEATHER_LAT
LON=$OPENWEATHER_LON
UNITS=metric
## Make cache dir
if [[ ! -d "$cache_dir" ]]; then
mkdir -p "${cache_dir}"
fi
## Get data
get_weather_data() {
weather=$(curl -sf "http://api.openweathermap.org/data/3.0/onecall?lat=${LAT}&lon=${LON}&exclude=minutely,hourly,daily&appid=${KEY}&units=${UNITS}")
echo "${weather}" >&2
weather=$(echo "$weather" | jq -r ".current")
if [ -n "$weather" ]; then
weather_temp=$(echo "$weather" | jq ".temp" | cut -d "." -f 1)
weather_icon_code=$(echo "$weather" | jq -r ".weather[].icon" | head -1)
weather_description=$(echo "$weather" | jq -r ".weather[].description" | head -1 | sed -e "s/\b\(.\)/\u\1/g")
#Big long if statement of doom
if [ "$weather_icon_code" == "50d" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "50n" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "01d" ]; then
weather_icon=" "
weather_hex="#e0af68"
elif [ "$weather_icon_code" == "01n" ]; then
weather_icon=" "
weather_hex="#c0caf5"
elif [ "$weather_icon_code" == "02d" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "02n" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "03d" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "03n" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "04d" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "04n" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "09d" ]; then
weather_icon=""
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "09n" ]; then
weather_icon=""
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "10d" ]; then
weather_icon=""
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "10n" ]; then
weather_icon=""
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "11d" ]; then
weather_icon=""
weather_hex="#ff9e64"
elif [ "$weather_icon_code" == "11n" ]; then
weather_icon=""
weather_hex="#ff9e64"
elif [ "$weather_icon_code" == "13d" ]; then
weather_icon=" "
weather_hex="#c0caf5"
elif [ "$weather_icon_code" == "13n" ]; then
weather_icon=" "
weather_hex="#c0caf5"
elif [ "$weather_icon_code" == "40d" ]; then
weather_icon=" "
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "40n" ]; then
weather_icon=" "
weather_hex="#7dcfff"
else
weather_icon=" "
weather_hex="#c0caf5"
fi
echo "$weather_icon" > "${cache_weather_icon}"
echo "$weather_description" > "${cache_weather_stat}"
echo "$weather_temp""°C" > "${cache_weather_degree}"
echo "$weather_hex" > "${cache_weather_hex}"
date "+%Y-%m-%d %H:%M:%S" | tee "${cache_weather_updatetime}" >/dev/null
else
echo "Weather Unavailable" > "${cache_weather_stat}"
echo " " > "${cache_weather_icon}"
echo "-" > "${cache_weather_degree}"
echo "#adadff" > "${cache_weather_hex}"
date "+%Y-%m-%d %H:%M:%S" | tee "${cache_weather_updatetime}" >/dev/null
fi
}
check_network() {
local max=12
local cnt=0
while [ $cnt -lt $max ]; do
if ping -c1 8.8.8.8 &>/dev/null || ping -c1 1.1.1.1 &>/dev/null; then
return 0
fi
echo "Waiting for network connection... (attempt: $((cnt + 1))/$max)" >&2
sleep 5
((cnt++))
done
echo "Network connection failed after $max attempts." >&2
return 1
}
## Execute
if [[ "$1" == "--getdata" ]]; then
if check_network; then
get_weather_data
fi
elif [[ "$1" == "--icon" ]]; then
cat "${cache_weather_icon}"
elif [[ "$1" == "--temp" ]]; then
cat "${cache_weather_degree}"
elif [[ "$1" == "--hex" ]]; then
tail -F "${cache_weather_hex}"
elif [[ "$1" == "--stat" ]]; then
cat "${cache_weather_stat}"
elif [[ "$1" == "--updatetime" ]]; then
cat "${cache_weather_updatetime}"
fi
-24
View File
@@ -1,24 +0,0 @@
#!/bin/bash
[ -f "$HOME/.local/snippets/apply-color-helper" ] || {
echo "Missing helper script: $HOME/.local/snippets/apply-color-helper"
exit 1
}
. "$HOME/.local/snippets/apply-color-helper"
file="$path"/eww.scss
sed -i "s|^\$border: #[0-9a-fA-F]\{6\};\$|\$border: #${colorHex};|" "$file" || {
log_error "Failed to edit ${file}"
exit 1
}
if pgrep -x eww -u "$USER" >/dev/null; then
eww reload || {
log_error "Failed to reload eww, is it running?"
exit 1
}
fi
log_success "eww"
-23
View File
@@ -1,23 +0,0 @@
/** Colors *******************************************/
$bg: #1e1e2e;
$bg-alt: #181825;
$fg: #cdd6f4;
$fg-alt: #a6adc8;
$red: #f38ba8;
$green: #a6e3a1;
$yellow: #f9e2af;
$orange: #fab387;
$blue: #89b4fa;
$purple: #cba6f7;
$cyan: #89dceb;
$gray: #585b70;
$gray-alt: #292a3c;
$lavender: #b4befe;
$sapphire: #74c7ec;
$teal: #94e2d5;
$peach: #fab387;
$border: #89b4fa;
@import './Main/eww.scss';
@import './Lyrics/eww.scss';
-2
View File
@@ -1,2 +0,0 @@
(include "./Main/eww.yuck")
(include "./Lyrics/eww.yuck")
-25
View File
@@ -1,25 +0,0 @@
#!/bin/bash
[ -f "$HOME/.local/snippets/apply-color-helper" ] || {
echo "Missing helper script: $HOME/.local/snippets/apply-color-helper"
exit 1
}
. "$HOME/.local/snippets/apply-color-helper"
file="$path"/fuzzel.ini
entries="match selection-match border"
if pgrep -x "fuzzel" -u "$USER" >/dev/null; then
pkill -x fuzzel || log_error "Failed to kill fuzzel process"
# and move on
fi
for entry in $entries; do
# Not very sure if alpha channels are neccessary here, but just in case
sed -i -E "s/^($entry\s*=\s*)([0-9A-Fa-f]{6})([0-9A-Fa-f]{0,2})/\1${colorHex}\3/" "$file" || {
log_error "Failed to edit ${file} for entry ${entry}"
exit 1
}
done
log_success "fuzzel"
-24
View File
@@ -1,24 +0,0 @@
terminal=kitty -e
prompt=">> "
layer=overlay
[colors]
background=1e1e2edd
text=cdd6f4ff
prompt=bac2deff
placeholder=7f849cff
input=cdd6f4ff
match=89b4faff
selection=585b70ff
selection-text=cdd6f4ff
selection-match=89b4faff
counter=7f849cff
border=89b4faff
[border]
radius=17
width=2
[dmenu]
exit-immediately-if-empty=yes
-28
View File
@@ -1,28 +0,0 @@
#!/bin/bash
[ -f "$HOME/.local/snippets/apply-color-helper" ] || {
echo "Missing helper script: $HOME/.local/snippets/apply-color-helper"
exit 1
}
. "$HOME/.local/snippets/apply-color-helper"
file="$path"/hyprland/colors.conf
sed -i -E "s/^(\s*col\.active_border\s*=\s*rgba\()([0-9A-Fa-f]{6})([0-9A-Fa-f]{2}\))$/\1${colorHex}\3/" "$file" || {
log_error "Failed to edit ${file} for entry col.active_border"
exit 1
}
sed -i -E "s/^(\s*col\.inactive_border\s*=\s*rgba\()([0-9A-Fa-f]{6})([0-9A-Fa-f]{2}\))$/\1${colorHex}\3/" "$file" || {
log_error "Failed to edit ${file} for entry col.active_border"
exit 1
}
if pgrep -x "hyprland" -u "$USER" >/dev/null; then
hyprctl reload || {
log_error "Failed to reload Hyprland"
exit 1
}
fi
log_success "hyprland"
@@ -1,7 +0,0 @@
source=~/.config/hypr/hyprland/env.conf
source=~/.config/hypr/hyprland/execs.conf
source=~/.config/hypr/hyprland/general.conf
source=~/.config/hypr/hyprland/rules.conf
source=~/.config/hypr/hyprland/colors.conf
source=~/.config/hypr/hyprland/keybinds.conf
source=~/.config/hypr/hyprland/monitors.conf
@@ -1,12 +0,0 @@
# exec = export SLURP_ARGS='-d -c BFE9F8BB -b 214C5844 -s 00000000'
general {
col.active_border = rgba(89b4faff)
col.inactive_border = rgba(89b4fa80)
}
misc {
background_color = rgba(181825FF)
}
windowrulev2 = bordercolor rgba(00DCE3AA) rgba(00DCE377),pinned:1
@@ -1,28 +0,0 @@
# ######### Input method ##########
# See https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland
env = QT_IM_MODULE, fcitx
env = XMODIFIERS, @im=fcitx
# env = GTK_IM_MODULE, fcitx
env = SDL_IM_MODULE, fcitx
env = GLFW_IM_MODULE, ibus
env = INPUT_METHOD, fcitx
# ############ Themes #############
env = QT_QPA_PLATFORM, wayland
env = QT_QPA_PLATFORMTHEME, kde
env = QT_STYLE_OVERRIDE, kvantum
# env = WLR_NO_HARDWARE_CURSORS, 1
# ######## Screen tearing #########
# env = WLR_DRM_NO_ATOMIC, 1
# ############ nvidia #############
env = LIBVA_DRIVER_NAME,nvidia
env = __GLX_VENDOR_LIBRARY_NAME,nvidia
env = NVD_BACKEND,direct
#env = AQ_DRM_DEVICES,$HYPR_AQ_DRM_DEVICES
# ############ others #############
env = XCURSOR_SIZE,24
env = HYPRCURSOR_SIZE,24
env = ELECTRON_OZONE_PLATFORM_HINT,auto
@@ -1,48 +0,0 @@
# Switch configs
exec-once = config-switch Hyprland
# Bar, wallpaper
exec-once = waybar
exec-once = wallpaper-daemon
# Input method
exec-once = fcitx5
# Core components (authentication, lock screen, notification daemon)
exec-once = gnome-keyring-daemon --start --components=secrets
# exec-once = hyprpolkitagent
exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
exec-once = hypridle
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 = hyprpm reload
exec-once = mako
exec-once = nm-applet
exec-once = blueman-applet
exec-once = eww daemon
# Audio
# exec-once = easyeffects --gapplication-service
# Clipboard: history
# exec-once = wl-paste --watch cliphist store &
exec-once = wl-paste --type text --watch cliphist store
exec-once = wl-paste --type image --watch cliphist store
# Cursor
exec-once = hyprctl setcursor Bibata-Modern-Ice 24
# Plugins
exec-once = hyprctl plugin load "/usr/lib/libhyprexpo.so"
# dock
# exec-once = nwg-dock-hyprland -d -i 32 -c "fuzzel" -ico "$HOME/.config/nwg-dock-hyprland/archlinux.png"
# Logitech Mouse
exec-once = solaar -w hide
# Applications associations
exec-once = kbuildsycoca6
# Sunshine
exec-once = sunshine
@@ -1,186 +0,0 @@
input {
# Keyboard: Add a layout and uncomment kb_options for Win+Space switching shortcut
kb_layout = de
# kb_options = grp:win_space_toggle
# kb_options = caps:swapescape
numlock_by_default = true
repeat_delay = 250
repeat_rate = 35
touchpad {
natural_scroll = yes
disable_while_typing = true
clickfinger_behavior = true
scroll_factor = 0.5
}
special_fallthrough = true
follow_mouse = 1
sensitivity = -0.25
}
binds {
# focus_window_on_workspace_c# For Auto-run stuff see execs.confhange = true
scroll_event_delay = 0
}
gesture = 4, horizontal, workspace
gestures {
workspace_swipe_distance = 700
workspace_swipe_cancel_ratio = 0.2
workspace_swipe_min_speed_to_force = 5
workspace_swipe_direction_lock = true
workspace_swipe_direction_lock_threshold = 10
workspace_swipe_create_new = true
}
general {
# Gaps and border
gaps_in = 2
gaps_out = 0
gaps_workspaces = 50
border_size = 2
resize_on_border = true
no_focus_fallback = true
layout = master
#focus_to_other_workspaces = true # ahhhh i still haven't properly implemented this
allow_tearing = true # This just allows the `immediate` window rule to work
snap {
enabled = true
}
}
dwindle {
preserve_split = true
smart_split = false
smart_resizing = false
}
master {
new_on_active = after
mfact = 0.6
orientation = right
}
decoration {
rounding = 14
blur {
enabled = true
xray = true
special = false
new_optimizations = true
size = 14
passes = 4
brightness = 1
noise = 0.01
contrast = 1
popups = true
popups_ignorealpha = 0.6
input_methods = true
input_methods_ignorealpha = 0.8
}
# Shadow
shadow {
enabled = true
ignore_window = true
range = 20
offset = 0 2
render_power = 4
color = rgba(0000002A)
}
# Dim
dim_inactive = false
dim_strength = 0.1
dim_special = 0
active_opacity = 1
inactive_opacity = 0.9
}
animations {
enabled = true
# Animation curves
bezier = linear, 0, 0, 1, 1
bezier = md3_standard, 0.2, 0, 0, 1
bezier = md3_decel, 0.05, 0.7, 0.1, 1
bezier = md3_accel, 0.3, 0, 0.8, 0.15
bezier = overshot, 0.05, 0.9, 0.1, 1.1
bezier = crazyshot, 0.1, 1.5, 0.76, 0.92
bezier = hyprnostretch, 0.05, 0.9, 0.1, 1.0
bezier = menu_decel, 0.1, 1, 0, 1
bezier = menu_accel, 0.38, 0.04, 1, 0.07
bezier = easeInOutCirc, 0.85, 0, 0.15, 1
bezier = easeOutCirc, 0, 0.55, 0.45, 1
bezier = easeOutExpo, 0.16, 1, 0.3, 1
bezier = softAcDecel, 0.26, 0.26, 0.15, 1
bezier = md2, 0.4, 0, 0.2, 1 # use with .2s duration
# Animation configs
animation = windows, 1, 3, md3_decel, popin 60%
animation = windowsIn, 1, 3, md3_decel, popin 60%
animation = windowsOut, 1, 3, md3_accel, popin 60%
animation = border, 1, 10, default
animation = fade, 1, 3, md3_decel
# animation = layers, 1, 2, md3_decel, slide
animation = layersIn, 1, 3, menu_decel, slide
animation = layersOut, 1, 1.6, menu_accel
animation = fadeLayersIn, 1, 2, menu_decel
animation = fadeLayersOut, 1, 2, menu_accel
animation = workspaces, 1, 7, menu_decel, slide
# animation = workspaces, 1, 2.5, softAcDecel, slide
# animation = workspaces, 1, 7, menu_decel, slidefade 15%
# animation = specialWorkspace, 1, 3, md3_decel, slidefadevert 15%
animation = specialWorkspace, 1, 3, md3_decel, slidevert
}
misc {
vfr = true
mouse_move_enables_dpms = true
key_press_enables_dpms = true
animate_manual_resizes = false
animate_mouse_windowdragging = false
enable_swallow = false
swallow_regex = (foot|kitty|allacritty|Alacritty)
disable_hyprland_logo = true
force_default_wallpaper = 0
new_window_takes_over_fullscreen = 2
allow_session_lock_restore = true
initial_workspace_tracking = false
# focus_on_activate = true
middle_click_paste = false
}
plugin {
hyprexpo {
columns = 3
gap_size = 5
bg_col = rgb(181825)
workspace_method = first 1 # [center/first] [workspace] e.g. first 1 or center m+1
enable_gesture = true # laptop touchpad, 4 fingers
gesture_distance = 200 # how far is the "max"
gesture_positive = false
}
}
xwayland {
force_zero_scaling = true
}
debug {
# overlay = true
disable_logs = false
}
experimental {
xx_color_management_v4 = true
}
@@ -1,175 +0,0 @@
# Lines ending with `# [hidden]` won't be shown on cheatsheet
# Lines starting with #! are section headings
#!
##! Apps
bind = Super, C, exec, code --password-store=gnome-libsecret # Launch VSCode (editor)
bind = Super, E, exec, dolphin --new-window # Launch file manager
bind = Super, W, exec, zen --new-window # Launch Browser
bind = Super, X, exec, gnome-text-editor # Launch Text Editor
bind = Super, B, exec, killall btop || ghostty -e btop # Launch btop (system monitor)
bind = Super, Space, exec, eww open main --toggle # Launch dashboard (eww)
bind = Super+Shift, V, exec, pavucontrol # Launch pavucontrol (volume mixer)
bind = Super+Shift, K, exec, waybar-toggle # Toggle waybar
bind = Super+Shift, L, exec, lyrics-widgets # Toggle lyrics player
bind = Super+Shift, F, exec, coin # Flip a coin
#!
##! Essentials
bind = Super, T, exec, kitty # Launch kitty (terminal)
bind = Super, Return, exec, kitty # [hidden]
bind = Super+Shift, Return, exec, ghostty # [hidden]
bind = Alt, Space, exec, pkill rofi || rofi -show drun # [hidden] Launch app launcher
bind = Super, Super_L, exec, pkill rofi || rofi -show drun # [hidden] Launch app launcher
bind = Super, R, exec, pkill rofi || rofi -show run # Launch command launcher
bind = , mouse:277, exec, killall rofi || rofi -show drun
##! Actions
# Screenshot, Record, OCR, Color picker, Clipboard history
bind = Super, V, exec, pkill rofi || cliphist list | rofi -dmenu -config ~/.config/rofi/dmenu.rasi -display-columns 2 -i | cliphist decode | wl-copy # Clipboard history >> clipboard
bind = Super, Period, exec, pkill rofi || rofi-emoji # Pick emoji >> clipboard
bind = Ctrl+Alt, Delete, exec, pkill wlogout || wlogout -p layer-shell # [hidden]
bind = Super+Shift, S, exec, screenshot-script area # Screen snip
bind = Super+Ctrl+Shift, S, exec, screenshot-script window # Screen snip (window)
bind = , Print, exec, screenshot-script full # Screen snip (whole screen)
# Color picker
bind = Super+Shift, C, exec, hyprpicker -a # Pick color (Hex) >> clipboard
# Fullscreen screenshot
# bindl=,Print,exec,grim - | wl-copy # Screenshot >> clipboard
# bindl= Ctrl,Print, exec, mkdir -p ~/Pictures/Screenshots && ~/.config/ags/scripts/grimblast.sh copysave screen ~/Pictures/Screenshots/Screenshot_"$(date '+%Y-%m-%d_%H.%M.%S')".png # Screenshot >> clipboard & file
# Recording stuff
# bind = Super+Alt, R, exec, ~/.config/ags/scripts/record-script # Record region (no sound)
# bind = Ctrl+Alt, R, exec, ~/.config/ags/scripts/record-script --fullscreen # [hidden] Record screen (no sound)
bind = Super+Alt, R, exec, record-script --fullscreen-sound # Record screen (with sound)
# wallpaper
bind = Super+Shift, W, exec, wallpaper-chooser # Launch wallpaper chooser
##! Session
# bind = Ctrl+Super, L, exec, ags run-js 'lock.lock()' # [hidden]
bind = Super, L, exec, loginctl lock-session # Lock
bindl = Ctrl+Shift+Alt+Super, L, exec, sleep 0.1 && systemctl suspend || loginctl suspend # Suspend system
bind = Ctrl+Shift+Alt+Super, Delete, exec, systemctl poweroff || loginctl poweroff # [hidden] Power off
#!
##! Media
bindl= Super+Shift, N, exec, playerctl next # Next track
bindl= ,XF86AudioNext, exec, playerctl next # [hidden]
bindl= ,XF86AudioPrev, exec, playerctl previous # [hidden]
bind = Super+Shift+Alt, mouse:275, exec, playerctl previous # [hidden]
bind = Super+Shift+Alt, mouse:276, exec, playerctl next # [hidden]
bindl= Super+Shift, B, exec, playerctl previous # Previous track
bindl= Super+Shift, P, exec, playerctl play-pause # Play/pause media
bindl= ,XF86AudioPlay, exec, playerctl play-pause # [hidden]
bindl= ,XF86AudioPause, exec, playerctl play-pause # [hidden]
#!
##! Sound & Brightness
bindl = ,XF86AudioMute, exec, pamixer --toggle-mute # [hidden]
bindl = Super+Shift, M, exec, pamixer --toggle-mute # [hidden]
bindle=, XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ && wp-vol # [hidden]
bindle=, XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- && wp-vol # [hidden]
bindle=, XF86MonBrightnessUp, exec, brightnessctl -d $DISPLAY_DEVICE set 5%+ # [hidden]
bindle=, XF86MonBrightnessDown, exec, brightnessctl -d $DISPLAY_DEVICE set 5%- # [hidden]
#!
##! Window management
# Focusing
#/# bind = Super, ←/↑/→/↓,, # Move focus in direction
bind = Super, Left, movefocus, l # [hidden]
bind = Super, Right, movefocus, r # [hidden]
bind = Super, Up, movefocus, u # [hidden]
bind = Super, Down, movefocus, d # [hidden]
bindm = Super, mouse:272, movewindow
bindm = Super, mouse:273, resizewindow
bind = Super, Q, killactive,
bind = Super, mouse:274, killactive # [hidden] Kill active window
bind = Super+Shift+Alt, Q, exec, hyprctl kill # Pick and kill a window
##! Window arrangement
#/# bind = Super+Shift, ←/↑/→/↓,, # Window: move in direction
bind = Super+Shift, Left, movewindow, l # [hidden]
bind = Super+Shift, Right, movewindow, r # [hidden]
bind = Super+Shift, Up, movewindow, u # [hidden]
bind = Super+Shift, Down, movewindow, d # [hidden]
# Window split ratio
#/# binde = Super, +/-,, # Window: split ratio +/- 0.1
binde = Super, udiaeresis, splitratio, -0.1 # [hidden]
binde = Super, plus, splitratio, +0.1 # [hidden]
# Positioning mode
bind = Super+Alt, Space, togglefloating,
bind = Super, mouse:276, togglefloating # [hidden]
bind = Super+Alt, F, fullscreenstate, 0 3 # Toggle fake fullscreen
bind = Super, F, fullscreen, 0
bind = Super, D, fullscreen, 1
bind = Super, J, togglesplit
bind = Super, O, plugin:uyani:organize # https://github.com/Uyanide/hyprplug
bind = Super, H, layoutmsg, orientationcycle left right
#!
##! Workspace navigation
# Switching
#/# bind = Super, Hash,, # Focus workspace # (1, 2, 3, 4, ...)
bind = Super, 1, workspace, 1 # [hidden]
bind = Super, 2, workspace, 2 # [hidden]
bind = Super, 3, workspace, 3 # [hidden]
bind = Super, 4, workspace, 4 # [hidden]
bind = Super, 5, workspace, 5 # [hidden]
bind = Super, 6, workspace, 6 # [hidden]
bind = Super, 7, workspace, 7 # [hidden]
bind = Super, 8, workspace, 8 # [hidden]
bind = Super, 9, workspace, 9 # [hidden]
bind = Super, 0, workspace, 10 # [hidden]
#/# bind = Ctrl+Super, ←/→,, # Workspace: focus left/right
bind = Ctrl+Super, Right, workspace, +1 # [hidden]
bind = Ctrl+Super, Left, workspace, -1 # [hidden]
#/# bind = Super, Scroll ↑/↓,, # Workspace: focus left/right
bind = Super, mouse_up, workspace, +1 # [hidden]
bind = Super, mouse_down, workspace, -1 # [hidden]
bind = Ctrl+Super, mouse_up, workspace, +1 # [hidden]
bind = Ctrl+Super, mouse_down, workspace, -1 # [hidden]
bind = Super, mouse_left, workspace, -1 # [hidden]
bind = Super, mouse_right, workspace, +1 # [hidden]
bind = Ctrl+Super, mouse_left, workspace, -1 # [hidden]
bind = Ctrl+Super, mouse_right, workspace, +1 # [hidden]
#/# bind = Super, Page_↑/↓,, # Workspace: focus left/right
bind = Super, Page_Down, workspace, +1 # [hidden]
bind = Super, Page_Up, workspace, -1 # [hidden]
bind = Ctrl+Super, Page_Down, workspace, +1 # [hidden]
bind = Ctrl+Super, Page_Up, workspace, -1 # [hidden]
## Special
bind = Super, S, togglespecialworkspace, s
bind = Super, mouse:275, togglespecialworkspace, s # [hidden]
##! Workspace management
# Move window to workspace Super + Alt + [0-9]
#/# bind = Super+Alt, Hash,, # Window: move to workspace # (1, 2, 3, 4, ...)
bind = Super+Alt, 1, movetoworkspacesilent, 1 # [hidden]
bind = Super+Alt, 2, movetoworkspacesilent, 2 # [hidden]
bind = Super+Alt, 3, movetoworkspacesilent, 3 # [hidden]
bind = Super+Alt, 4, movetoworkspacesilent, 4 # [hidden]
bind = Super+Alt, 5, movetoworkspacesilent, 5 # [hidden]
bind = Super+Alt, 6, movetoworkspacesilent, 6 # [hidden]
bind = Super+Alt, 7, movetoworkspacesilent, 7 # [hidden]
bind = Super+Alt, 8, movetoworkspacesilent, 8 # [hidden]
bind = Super+Alt, 9, movetoworkspacesilent, 9 # [hidden]
bind = Super+Alt, 0, movetoworkspacesilent, 10 # [hidden]
bind = Ctrl+Super+Shift, Right, movetoworkspace, +1 # [hidden]
bind = Ctrl+Super+Shift, Left, movetoworkspace, -1 # [hidden]
bind = Ctrl+Super, Up, workspace, -5 # [hidden]
bind = Ctrl+Super, Down, workspace, +5 # [hidden]
#/# bind = Super+Shift, Scroll ↑/↓,, # Window: move to workspace left/right
bind = Super+Shift, mouse_down, movetoworkspace, -1 # [hidden]
bind = Super+Shift, mouse_up, movetoworkspace, +1 # [hidden]
bind = Super+Shift, mouse_left, movetoworkspace, -1 # [hidden]
bind = Super+Shift, mouse_right, movetoworkspace, +1 # [
#/# bind = Super+Shift, Page_↑/↓,, # Window: move to workspace left/right
bind = Super+Shift, Page_Down, movetoworkspace, +1 # [hidden]
bind = Super+Shift, Page_Up, movetoworkspace, -1 # [hidden]
bind = Super+Alt, S, movetoworkspacesilent, special:s
bind = Super, P, pin
bind = Alt, Tab, cyclenext
# bind = Super, Tab, hyprexpo:expo, toggle # can be: toggle, select, off/disable or on/enable
bind = Super+Ctrl, T, exec, workspace-new # Create new workspace
bind = Super, M, exit
@@ -1,18 +0,0 @@
# MONITOR CONFIG
monitor=,preferred,auto,1
# monitor=eDP-1,2560x1600@240,auto,1.25,bitdepth,10
monitor=eDP-2,2560x1600@240,auto,1.25,bitdepth,10
monitorv2 {
output = eDP-1
mode = 2560x1600@240
scale = 1.25
bitdepth = 10
# # comment out following lines to disabled HDR
# supports_wide_color = true
# supports_hdr = true
# cm = hdr
# sdrbrightness = 1.4
}
@@ -1,93 +0,0 @@
# ######## Window rules ########
# Uncomment to apply global transparency to all windows:
# windowrulev2 = opacity 0.89 override 0.89 override, class:.*
# Disable blur for XWayland windows (or context menus with shadow would look weird)
windowrulev2 = noblur, xwayland:1
# Disable transparency
windowrulev2 = opacity 1 override 1 override, class:^(gimp)$
# Terminal(s)
windowrulev2 = float, class:^(com.mitchellh.ghostty)$
windowrulev2 = size 60%, class:^(com.mitchellh.ghostty)$
windowrulev2 = opacity 1 override 0.8 override, class:^(com.mitchellh.ghostty)$
windowrulev2 = opacity 1 override 0.8 override, class:^(kitty)$
# Floating
windowrulev2 = float, class:^(blueberry\.py)$
windowrulev2 = float, class:^(blueman-manager)$
windowrulev2 = size 45%, class:^(blueman-manager)$
windowrulev2 = float, class:^(pavucontrol)$
windowrulev2 = size 45%, class:^(pavucontrol)$
windowrulev2 = center, class:^(pavucontrol)$
windowrulev2 = float, class:^(org.pulseaudio.pavucontrol)$
windowrulev2 = size 45%, class:^(org.pulseaudio.pavucontrol)$
windowrulev2 = center, class:^(org.pulseaudio.pavucontrol)$
windowrulev2 = float, class:^(Waydroid)$
windowrulev2 = float, class:^(org.kde.kcalc)$
windowrulev2 = float, class:^(org.kde.kalk)$
windowrulev2 = float, class:^(org.gnome.NautilusPreviewer)$ # Sushi in Nautilus
windowrulev2 = float, class:^(coin)$
windowrulev2 = noblur, class:^(coin)$
windowrulev2 = bordersize 0, class:^(coin)$
windowrulev2 = noshadow, class:^(coin)
windowrulev2 = float, class:^(wallpaper-chooser)$
windowrulev2 = float, class:^(be.alexandervanhee.gradia)$
windowrulev2 = float, title:^(图片查看器)$ # QQ
# Picture-in-Picture
windowrulev2 = float, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$
windowrulev2 = keepaspectratio, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$
windowrulev2 = move 73% 72%, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$
windowrulev2 = size 25%, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$
windowrulev2 = float, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$
windowrulev2 = pin, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$
# Dialog windows float+center these windows.
windowrulev2 = center, title:^(Open File)(.*)$
windowrulev2 = center, title:^(Select a File)(.*)$
windowrulev2 = center, title:^(Choose wallpaper)(.*)$
windowrulev2 = center, title:^(Open Folder)(.*)$
windowrulev2 = center, title:^(Save As)(.*)$
windowrulev2 = center, title:^(Library)(.*)$
windowrulev2 = center, title:^(File Upload)(.*)$
windowrulev2 = float, title:^(Open File)(.*)$
windowrulev2 = float, title:^(Select a File)(.*)$
windowrulev2 = float, title:^(Choose wallpaper)(.*)$
windowrulev2 = float, title:^(Open Folder)(.*)$
windowrulev2 = float, title:^(Save As)(.*)$
windowrulev2 = float, title:^(Library)(.*)$
windowrulev2 = float, title:^(File Upload)(.*)$
# --- Tearing ---
windowrulev2 = immediate, title:.*\.exe
windowrulev2 = immediate, class:^(steam_app)
# No shadow for tiled windows (matches windows that are not floating).
windowrulev2 = noshadow, floating:0
# ######## Workspace rules ########
workspace = special:special, gapsout:30
# ######## Layer rules ########
layerrule = xray 1, .*
# layerrule = noanim, .*
layerrule = noanim, walker
layerrule = noanim, selection
layerrule = noanim, overview
layerrule = noanim, anyrun
layerrule = noanim, indicator.*
layerrule = noanim, osk
layerrule = noanim, hyprpicker
layerrule = noanim, noanim
layerrule = blur, gtk-layer-shell
layerrule = ignorezero, gtk-layer-shell
layerrule = blur, launcher
layerrule = ignorealpha 0.5, launcher
layerrule = blur, notifications
layerrule = ignorealpha 0.69, notifications
layerrule = blur, logout_dialog # wlogout
-319
View File
@@ -1,319 +0,0 @@
# #######################################################################################
# AUTOGENERATED HYPRLAND CONFIG.
# EDIT THIS CONFIG ACCORDING TO THE WIKI INSTRUCTIONS.
# #######################################################################################
# This is an example Hyprland config file.
# Refer to the wiki for more information.
# https://wiki.hypr.land/Configuring/
# Please note not all available settings / options are set here.
# For a full list, see the wiki
# You can split this configuration into multiple files
# Create your files separately and then link them to this file like this:
# source = ~/.config/hypr/myColors.conf
################
### MONITORS ###
################
# See https://wiki.hypr.land/Configuring/Monitors/
monitor=,preferred,auto,auto
###################
### MY PROGRAMS ###
###################
# See https://wiki.hypr.land/Configuring/Keywords/
# Set programs that you use
$terminal = kitty
$fileManager = dolphin
$menu = wofi --show drun
#################
### AUTOSTART ###
#################
# Autostart necessary processes (like notifications daemons, status bars, etc.)
# Or execute your favorite apps at launch like this:
# exec-once = $terminal
# exec-once = nm-applet &
# exec-once = waybar & hyprpaper & firefox
#############################
### ENVIRONMENT VARIABLES ###
#############################
# See https://wiki.hypr.land/Configuring/Environment-variables/
env = XCURSOR_SIZE,24
env = HYPRCURSOR_SIZE,24
###################
### PERMISSIONS ###
###################
# See https://wiki.hypr.land/Configuring/Permissions/
# Please note permission changes here require a Hyprland restart and are not applied on-the-fly
# for security reasons
# ecosystem {
# enforce_permissions = 1
# }
# permission = /usr/(bin|local/bin)/grim, screencopy, allow
# permission = /usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland, screencopy, allow
# permission = /usr/(bin|local/bin)/hyprpm, plugin, allow
#####################
### LOOK AND FEEL ###
#####################
# Refer to https://wiki.hypr.land/Configuring/Variables/
# https://wiki.hypr.land/Configuring/Variables/#general
general {
gaps_in = 5
gaps_out = 20
border_size = 2
# https://wiki.hypr.land/Configuring/Variables/#variable-types for info about colors
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.inactive_border = rgba(595959aa)
# Set to true enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false
# Please see https://wiki.hypr.land/Configuring/Tearing/ before you turn this on
allow_tearing = false
layout = dwindle
}
# https://wiki.hypr.land/Configuring/Variables/#decoration
decoration {
rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows
active_opacity = 1.0
inactive_opacity = 1.0
shadow {
enabled = true
range = 4
render_power = 3
color = rgba(1a1a1aee)
}
# https://wiki.hypr.land/Configuring/Variables/#blur
blur {
enabled = true
size = 3
passes = 1
vibrancy = 0.1696
}
}
# https://wiki.hypr.land/Configuring/Variables/#animations
animations {
enabled = yes, please :)
# Default curves, see https://wiki.hypr.land/Configuring/Animations/#curves
# NAME, X0, Y0, X1, Y1
bezier = easeOutQuint, 0.23, 1, 0.32, 1
bezier = easeInOutCubic, 0.65, 0.05, 0.36, 1
bezier = linear, 0, 0, 1, 1
bezier = almostLinear, 0.5, 0.5, 0.75, 1
bezier = quick, 0.15, 0, 0.1, 1
# Default animations, see https://wiki.hypr.land/Configuring/Animations/
# NAME, ONOFF, SPEED, CURVE, [STYLE]
animation = global, 1, 10, default
animation = border, 1, 5.39, easeOutQuint
animation = windows, 1, 4.79, easeOutQuint
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
animation = windowsOut, 1, 1.49, linear, popin 87%
animation = fadeIn, 1, 1.73, almostLinear
animation = fadeOut, 1, 1.46, almostLinear
animation = fade, 1, 3.03, quick
animation = layers, 1, 3.81, easeOutQuint
animation = layersIn, 1, 4, easeOutQuint, fade
animation = layersOut, 1, 1.5, linear, fade
animation = fadeLayersIn, 1, 1.79, almostLinear
animation = fadeLayersOut, 1, 1.39, almostLinear
animation = workspaces, 1, 1.94, almostLinear, fade
animation = workspacesIn, 1, 1.21, almostLinear, fade
animation = workspacesOut, 1, 1.94, almostLinear, fade
animation = zoomFactor, 1, 7, quick
}
# Ref https://wiki.hypr.land/Configuring/Workspace-Rules/
# "Smart gaps" / "No gaps when only"
# uncomment all if you wish to use that.
# workspace = w[tv1], gapsout:0, gapsin:0
# workspace = f[1], gapsout:0, gapsin:0
# windowrule = bordersize 0, floating:0, onworkspace:w[tv1]
# windowrule = rounding 0, floating:0, onworkspace:w[tv1]
# windowrule = bordersize 0, floating:0, onworkspace:f[1]
# windowrule = rounding 0, floating:0, onworkspace:f[1]
# See https://wiki.hypr.land/Configuring/Dwindle-Layout/ for more
dwindle {
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = true # You probably want this
}
# See https://wiki.hypr.land/Configuring/Master-Layout/ for more
master {
new_status = master
}
# https://wiki.hypr.land/Configuring/Variables/#misc
misc {
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
}
#############
### INPUT ###
#############
# https://wiki.hypr.land/Configuring/Variables/#input
input {
kb_layout = de
kb_variant =
kb_model =
kb_options =
kb_rules =
follow_mouse = 1
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
touchpad {
natural_scroll = false
}
}
# https://wiki.hypr.land/Configuring/Variables/#gestures
gestures {
workspace_swipe = false
}
# Example per-device config
# See https://wiki.hypr.land/Configuring/Keywords/#per-device-input-configs for more
device {
name = epic-mouse-v1
sensitivity = -0.5
}
###################
### KEYBINDINGS ###
###################
# See https://wiki.hypr.land/Configuring/Keywords/
$mainMod = Alt # Sets "Windows" key as main modifier
# Example binds, see https://wiki.hypr.land/Configuring/Binds/ for more
bind = $mainMod, Q, exec, $terminal
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, $fileManager
bind = $mainMod, V, togglefloating,
bind = $mainMod, R, exec, $menu
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle
# Move focus with mainMod + arrow keys
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
# Switch workspaces with mainMod + [0-9]
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
# Move active window to a workspace with mainMod + SHIFT + [0-9]
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Example special workspace (scratchpad)
bind = $mainMod, S, togglespecialworkspace, magic
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
# Laptop multimedia keys for volume and LCD brightness
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
bindel = ,XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%-
# Requires playerctl
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previous
##############################
### WINDOWS AND WORKSPACES ###
##############################
# See https://wiki.hypr.land/Configuring/Window-Rules/ for more
# See https://wiki.hypr.land/Configuring/Workspace-Rules/ for workspace rules
# Example windowrule
# windowrule = float,class:^(kitty)$,title:^(kitty)$
# Ignore maximize requests from apps. You'll probably like this.
windowrule = suppressevent maximize, class:.*
# Fix some dragging issues with XWayland
windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
debug {
disable_logs = false
overlay = true
disable_time = false
enable_stdout_logs = true
}
-24
View File
@@ -1,24 +0,0 @@
#!/bin/bash
[ -f "$HOME/.local/snippets/apply-color-helper" ] || {
echo "Missing helper script: $HOME/.local/snippets/apply-color-helper"
exit 1
}
. "$HOME/.local/snippets/apply-color-helper"
file="$path"/config
entry="border-color"
sed -i -E "0,/^($entry\s*=\s*#)([0-9A-Fa-f]{6})/s//\1${colorHex}/" "$file" || {
log_error "Failed to edit ${file} for entry ${entry}"
exit 1
}
if pgrep -x "mako" -u "$USER" >/dev/null; then
makoctl reload || {
log_error "Failed to reload mako"
exit 1
}
fi
log_success "mako"
-37
View File
@@ -1,37 +0,0 @@
max-visible=10
layer=top
font=Noto Sans 12
border-radius=12
max-icon-size=48
default-timeout=5000
anchor=top-right
margin=20
background-color=#1e1e2e
text-color=#cdd6f4
border-color=#89b4fa
progress-color=over #313244
[urgency=high]
border-color=#fab387
[app-name=wp-vol]
layer=overlay
history=0
anchor=top-center
# Group all volume notifications together
group-by=app-name
# Hide the group-index
format=<b>%s</b>\n%b
[app-name=volume group-index=0]
# Only show last notification
invisible=0
[app-name=spotify-lyrics]
history=0
group-by=app-name
format=<b>%s</b>\n%b
[app-name=spotify-lyrics group-index=0]
invisible=0
@@ -69,6 +69,7 @@ Singleton {
}
function _scheduleCycle(secondsFromNow) {
if (!enabled) return;
const seconds = Math.max(1, Math.floor(secondsFromNow));
timeUntilNextCycle = seconds;
nextCycleDeadlineMs = Date.now() + (seconds * 1000);
@@ -1,194 +0,0 @@
#!/usr/bin/env bash
# Description:
# Change the desktop wallpaper and generate a blurred version.
#
# Requirs:
# - zenity (for file selection dialog)
# - imagemagick (for image processing)
# - swww (wallpaper daemon)
# - notify-send (for notifications)
# - change-colortheme (from scripts/change-colortheme)
# - flock (usually part of util-linux)
set -euo pipefail
# Lock
exec {LOCK_FD}>/tmp/"$(basename "$0")".lock
flock -n "$LOCK_FD" || {
echo "Another instance is running. Exiting."
# notify-send -a "change-wallpaper" "Error" "Another instance is running. Exiting."
exit 1
}
# Open a file selection dialog if no argument is provided
if [ -z "${1-}" ]; then
image=$(zenity --file-selection --title="Open File" --file-filter="*.jpg *.jpeg *.png *.webp *.bmp *.jfif *.tiff *.avif *.heic *.heif")
else
image="$1"
fi
[ -z "$image" ] && exit 1
[ ! -f "$image" ] && exit 1
# Obtain screen resolution
screen_width=${2-}
screen_height=${3-}
[ -z "$screen_width" ] && {
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
screen_width=$(hyprctl -j monitors | jq '.[0].resolution.x')
elif [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
screen_width=$(niri msg focused-output | grep 'Current mode' | awk '{print $3}' | cut -d'x' -f1)
fi
}
[ -z "$screen_height" ] && {
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
screen_height=$(hyprctl -j monitors | jq '.[0].resolution.y')
elif [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
screen_height=$(niri msg focused-output | grep 'Current mode' | awk '{print $3}' | cut -d'x' -f2)
fi
}
## Default to 2k
screen_width=${screen_width:-2560}
screen_height=${screen_height:-1440}
# $HOME/.config/wallpaper-chooser/config.json:
# ```json
# "sort": {
# "type": "date",
# "reverse": true
# }
# ```
# So in order to let the most recently used wallpapers appear first:
touch "$image" 2>/dev/null || true # ignore errors
# Copy image to local wallpaper directory
## Format of current and cached wallpaper
wallpaper_ext="png"
## Generate a random name for the current wallpaper
set +o pipefail # SIGPIPE is expected here
random_name=$(tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 16)
set -o pipefail
## Directory to store current wallpaper
current_dir="$HOME/.local/share/wallpaper/current"
## Path to current wallpaper image
wallpaper_image="$current_dir/wallpaper-${random_name}.${wallpaper_ext}"
mkdir -p "$current_dir"
## Batch copy using a temporary file to avoid incomplete file being used
temp_img=$(mktemp --suffix=."$wallpaper_ext")
trap 'rm -f "$temp_img"' EXIT
magick "$image" -resize "${screen_width}x${screen_height}^" -gravity center -extent "${screen_width}x${screen_height}" "$temp_img"
cp "$temp_img" "$wallpaper_image"
## Generate hash for caching,
## based on content of the source image and resolution of the resized image
hash="$(md5sum "$image" | awk '{print $1}')-${screen_width}x${screen_height}"
# Clean up old wallpapers in the same directory of current wallpaper.
# Only keep the newly added one so the wallpaper-daemon can pick it up directly
find "$current_dir" -type f -name "wallpaper-*" ! -name "$(basename "$wallpaper_image")" -delete
# Generate blurred wallpaper
## Similarly, store blurred version of current wallpaper in separate directory
blur_dir="$HOME/.local/share/wallpaper/blurred"
## Directory to cache blurred wallpapers, so that we don't need to regenerate
## them every time when switching wallpapers. This makes it possible to have
## an auto-played slideshow with blurred wallpapers without noticeable delay.
blur_cache_dir="$HOME/.local/share/wallpaper/blurred-cache"
mkdir -p "$blur_dir" "$blur_cache_dir"
blurred_image="$blur_dir/blurred-${random_name}.${wallpaper_ext}"
blurred_cache_image="$blur_cache_dir/${hash}.${wallpaper_ext}"
## Time consuming task (magick -blur) in background
(
# notify-send -a "change-wallpaper" "Generating Blurred Wallpaper" "This may take a few seconds..."
function apply_blured {
find "$blur_dir" -type f -name "blurred-*" ! -name "$(basename "$blurred_image")" -delete
if [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
swww img -n backdrop "$blurred_image" --transition-type fade --transition-duration 2 >/dev/null 2>/dev/null
fi
# notify-send -a "change-wallpaper" "Blurred Wallpaper Applied" "$blurred_image" -i "$blurred_image"
}
### Check if cached blurred image exists
if [ -f "$blurred_cache_image" ]; then
# sleep 1 # Some ugly workaround
if ! cp -f "$blurred_cache_image" "$blurred_image"; then
echo "Could not copy cached blurred image"
# exit 1 # Non-critical error
else
apply_blured
exit 0
fi
fi
sigma=$(magick identify -format "%w %h" "$wallpaper_image" | awk -v f=0.01 '{
m=($1>$2)?$1:$2;
s=m*f;
if(s<2) s=2;
if(s>200) s=200;
printf "%.2f", s
}')
### Batch processing using a temporary file to avoid incomplete file being used
temp_blurred=$(mktemp --suffix=."$wallpaper_ext") || exit 1
trap 'rm -f "${temp_blurred}"' EXIT
magick "$wallpaper_image" -blur 0x"$sigma" "$temp_blurred" || {
echo "Could not create blurred image"
exit 1
}
mv -f "$temp_blurred" "$blurred_image" || {
echo "Could not move blurred image to cache directory"
exit 1
}
cp -f "$blurred_image" "$blurred_cache_image" || {
echo "Could not cache blurred image"
# exit 1 # Non-critical error
}
apply_blured
) &
# Apply wallpaper
skip_colortheme=0
if [ "${4-}" = "--skip-colortheme" ]; then
skip_colortheme=1
fi
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
swww img -n background "$wallpaper_image" --transition-type fade --transition-duration 2 >/dev/null 2>/dev/null
# notify-send -a "change-wallpaper" "Wallpaper Changed" "$image" -i "$wallpaper_image"
if [ "$skip_colortheme" = 0 ]; then
change-colortheme -i "$wallpaper_image" || exit 1
fi
elif [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
### Handled in wallpaper-daemon
# swww img -n background "$wallpaper_image" --transition-type fade --transition-duration 2 > /dev/null 2> /dev/null
# notify-send -a "change-wallpaper" "Wallpaper Changed" "$image" -i "$wallpaper_image"
if [ "$skip_colortheme" = 0 ]; then
change-colortheme -i "$wallpaper_image" || exit 1
fi
else
echo "Unsupported desktop environment: $XDG_CURRENT_DESKTOP"
exit 1
fi
-166
View File
@@ -1,166 +0,0 @@
#!/usr/bin/env bash
# Description:
# Fetch and cache current weather data using OpenWeather API for use in eww widgets.
#
# Requirements:
# - Environment variables:
# - OPENWEATHER_API_KEY
# - OPENWEATHER_LAT
# - OPENWEATHER_LON
## Collect data
cache_dir="$HOME/.cache/eww/weather"
cache_weather_stat=${cache_dir}/weather-stat
cache_weather_degree=${cache_dir}/weather-degree
cache_weather_hex=${cache_dir}/weather-hex
cache_weather_icon=${cache_dir}/weather-icon
cache_weather_updatetime=${cache_dir}/weather-updatetime
if [[ -z "$OPENWEATHER_API_KEY" ]]; then
echo "Please set the OPENWEATHER_API_KEY environment variable."
exit 1
fi
if [[ -z "$OPENWEATHER_LAT" ]]; then
echo "Please set the OPENWEATHER_LAT environment variable."
exit 1
fi
if [[ -z "$OPENWEATHER_LON" ]]; then
echo "Please set the OPENWEATHER_LON environment variable."
exit 1
fi
## Weather data
KEY=$OPENWEATHER_API_KEY
LAT=$OPENWEATHER_LAT
LON=$OPENWEATHER_LON
UNITS=metric
## Make cache dir
if [[ ! -d "$cache_dir" ]]; then
mkdir -p ${cache_dir}
fi
## Get data
get_weather_data() {
weather=`curl -sf "http://api.openweathermap.org/data/3.0/onecall?lat=${LAT}&lon=${LON}&exclude=minutely,hourly,daily&appid=${KEY}&units=${UNITS}"`
echo ${weather} >&2
weather=$(echo "$weather" | jq -r ".current")
if [ ! -z "$weather" ]; then
weather_temp=`echo "$weather" | jq ".temp" | cut -d "." -f 1`
weather_icon_code=`echo "$weather" | jq -r ".weather[].icon" | head -1`
weather_description=`echo "$weather" | jq -r ".weather[].description" | head -1 | sed -e "s/\b\(.\)/\u\1/g"`
#Big long if statement of doom
if [ "$weather_icon_code" == "50d" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "50n" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "01d" ]; then
weather_icon=" "
weather_hex="#e0af68"
elif [ "$weather_icon_code" == "01n" ]; then
weather_icon=" "
weather_hex="#c0caf5"
elif [ "$weather_icon_code" == "02d" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "02n" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "03d" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "03n" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "04d" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "04n" ]; then
weather_icon=" "
weather_hex="#7aa2f7"
elif [ "$weather_icon_code" == "09d" ]; then
weather_icon=""
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "09n" ]; then
weather_icon=""
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "10d" ]; then
weather_icon=""
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "10n" ]; then
weather_icon=""
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "11d" ]; then
weather_icon=""
weather_hex="#ff9e64"
elif [ "$weather_icon_code" == "11n" ]; then
weather_icon=""
weather_hex="#ff9e64"
elif [ "$weather_icon_code" == "13d" ]; then
weather_icon=" "
weather_hex="#c0caf5"
elif [ "$weather_icon_code" == "13n" ]; then
weather_icon=" "
weather_hex="#c0caf5"
elif [ "$weather_icon_code" == "40d" ]; then
weather_icon=" "
weather_hex="#7dcfff"
elif [ "$weather_icon_code" == "40n" ]; then
weather_icon=" "
weather_hex="#7dcfff"
else
weather_icon=" "
weather_hex="#c0caf5"
fi
echo "$weather_icon" > ${cache_weather_icon}
echo "$weather_description" > ${cache_weather_stat}
echo "$weather_temp""°C" > ${cache_weather_degree}
echo "$weather_hex" > ${cache_weather_hex}
date "+%Y-%m-%d %H:%M:%S" | tee ${cache_weather_updatetime} >/dev/null
else
echo "Weather Unavailable" > ${cache_weather_stat}
echo " " > ${cache_weather_icon}
echo "-" > ${cache_weather_degree}
echo "#adadff" > ${cache_weather_hex}
date "+%Y-%m-%d %H:%M:%S" | tee ${cache_weather_updatetime} >/dev/null
fi
}
check_network() {
local max=12
local cnt=0
while [ $cnt -lt $max ]; do
if ping -c1 8.8.8.8 &>/dev/null || ping -c1 1.1.1.1 &>/dev/null; then
return 0
fi
echo "Waiting for network connection... (attempt: $((cnt + 1))/$max)" >&2
sleep 5
((cnt++))
done
echo "Network connection failed after $max attempts." >&2
return 1
}
## Execute
if [[ -z "$1" ]]; then
if check_network; then
get_weather_data
fi
elif [[ "$1" == "--icon" ]]; then
cat ${cache_weather_icon}
elif [[ "$1" == "--temp" ]]; then
cat ${cache_weather_degree}
elif [[ "$1" == "--hex" ]]; then
tail -F ${cache_weather_hex}
elif [[ "$1" == "--stat" ]]; then
cat ${cache_weather_stat}
elif [[ "$1" == "--updatetime" ]]; then
cat ${cache_weather_updatetime}
fi
@@ -1,36 +0,0 @@
#!/bin/sh
# Description:
# Toggle the visibility of lyrics widgets in eww.
# - Ensure only one of the two widgets (lyrics or lyrics-single) is open at a time.
# - Cycle through the following states:
# 1. Both widgets closed -> Open 'lyrics'
# 2. 'lyrics' open -> Close 'lyrics' and open 'lyrics-single' (if waybar is running)
# 3. 'lyrics-single' open -> Close 'lyrics-single'
# 4. Both widgets open -> Close both
LYRICS=$(eww active-windows | grep "lyrics:")
LYRICS_SINGLE=$(eww active-windows | grep "lyrics-single:")
# both are closed
if [ -z "$LYRICS" ] && [ -z "$LYRICS_SINGLE" ]; then
eww open lyrics
# only lyrics is open
elif [ -n "$LYRICS" ] && [ -z "$LYRICS_SINGLE" ]; then
eww close lyrics
# if waybar is running, open lyrics-single
if pgrep -x "waybar" -u "$USER" > /dev/null; then
sleep 0.5
eww open lyrics-single
fi
# only lyrics-single is open
elif [ -z "$LYRICS" ] && [ -n "$LYRICS_SINGLE" ]; then
eww close lyrics-single
# both are open
elif [ -n "$LYRICS" ] && [ -n "$LYRICS_SINGLE" ]; then
eww close lyrics
eww close lyrics-single
fi
@@ -1,64 +0,0 @@
#!/usr/bin/env bash
# Description:
# Script to record screen.
# Inspired by https://github.com/end-4/dots-hyprland
#
# Requirements:
# - wf-recorder
# - slurp
[ -z "$codec" ] && codec="av1_nvenc"
[ -z "$pixel_format" ] && pixel_format="p010le"
[ -z "$frame_rate" ] && frame_rate="60"
[ -z "$codec_params" ] && codec_params=\
"preset=p4 rc=constqp qp=18 \
color_range=tv"
[ -z "$filter_args" ] && filter_args=""
getdate() {
date '+%Y-%m-%d_%H.%M.%S'
}
getaudiooutput() {
pactl list sources | grep 'Name' | grep 'monitor' | cut -d ' ' -f2
}
getactivemonitor() {
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name'
elif [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
niri msg focused-output | head -n 1 | sed -n 's/.*(\(.*\)).*/\1/p'
fi
}
recorder_args=(
--codec "$codec"
--pixel-format "$pixel_format"
--framerate "$frame_rate"
-f './recording_'"$(getdate)"'.mkv'
)
for param in $codec_params; do
recorder_args+=(-p "$param")
done
for filter in $filter_args; do
recorder_args+=(-F "$filter")
done
mkdir -p "$(xdg-user-dir VIDEOS)"
cd "$(xdg-user-dir VIDEOS)" || exit
if pgrep -x wf-recorder -u "$USER" > /dev/null; then
notify-send "Recording Stopped" "Stopped" -a 'record-script' &
pkill -x wf-recorder -u "$USER"
else
notify-send "Starting recording" 'recording_'"$(getdate)"'.mkv' -a 'record-script' &
if [[ "$1" == "--sound" ]]; then
wf-recorder --geometry "$(slurp)" --audio="$(getaudiooutput)" "${recorder_args[@]}" & disown
elif [[ "$1" == "--fullscreen-sound" ]]; then
wf-recorder -o "$(getactivemonitor)" --audio="$(getaudiooutput)" "${recorder_args[@]}" & disown
elif [[ "$1" == "--fullscreen" ]]; then
wf-recorder -o "$(getactivemonitor)" "${recorder_args[@]}" & disown
else
wf-recorder --geometry "$(slurp)" "${recorder_args[@]}" & disown
fi
fi
@@ -1,390 +0,0 @@
#!/usr/bin/env python3
# Description:
# A wallpaper daemon script that integrates with swww and Niri/Hyprland to
# automatically switch between normal and blurred wallpapers based on window focus.
#
# Requirements:
# - swww (or awww case you are from the future)
# - niri/hyprland (obviously)
# - watchdog (python3 package)
import socket
import json
import subprocess
import threading
from sys import exit
from time import sleep
from os import environ, getuid
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
NORMAL_WALLPAPER_DIR = Path("~/.local/share/wallpaper/current").expanduser()
BLURRED_WALLPAPER_DIR = Path("~/.local/share/wallpaper/blurred").expanduser()
def getFirstFile(dir: Path, pattern: str = "*") -> Path | None:
"""`find $dir -type f | head -n 1`"""
return next(dir.glob(pattern), None)
def getNiriSocket():
return environ["NIRI_SOCKET"]
def _log(msg: str):
# print(msg)
# logFile = Path("/tmp/niri-autoblur.log")
# try:
# with logFile.open("a") as f:
# f.write(msg + "\n")
# except Exception:
# pass
pass
def swwwLoadImg(namespace: str, wallpaper: Path):
cmd = [
"swww",
"img",
"-n",
namespace,
str(wallpaper),
"--transition-type",
"fade",
"--transition-duration",
"0.5",
]
_log(f"[SWWW] {' '.join(cmd)}")
ret = 0
try:
ret = subprocess.run(cmd, check=True).returncode
except Exception as e:
_log(f"[SWWW] failed to set wallpaper: {e}")
return False
if ret != 0:
_log(f"[SWWW] failed to set wallpaper, exit code: {ret}")
return False
return True
def swwwStartDaemon(namespace: str):
# Check if daemon is already running
cmd = ["pgrep", "-f", f"swww-daemon -n {namespace}", "-u", str(getuid())]
try:
output = subprocess.check_output(cmd, text=True)
pids = output.strip().splitlines()
if pids:
_log(f"[SWWW] daemon already running with PIDs: {', '.join(pids)}")
return True
except subprocess.CalledProcessError:
# pgrep returns non-zero exit code if no process is found
pass
except Exception as e:
_log(f"[SWWW] failed to check if daemon is running: {e}")
pass
try:
subprocess.Popen(
["swww-daemon", "-n", namespace],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
_log(f"[SWWW] daemon started for namespace: {namespace}")
return True
except Exception as e:
_log(f"[SWWW] failed to start daemon non-blockingly: {e}")
return False
class AutoBlur:
_interval: float
_normalDir: Path
_blurredDir: Path
_isBlurred = threading.Event()
_thread: threading.Thread | None = None
_lastWallpaper: Path | None = None
_isFirst = True
_applyLock: threading.Lock
def __init__(self, normalDir, blurredDir, interval=0.2):
self._interval = interval
self._normalDir = normalDir
self._blurredDir = blurredDir
self._applyLock = threading.Lock()
# Niri will send "WindowsChanged" event on connect, so no need to init here
# init state
# self.setBlurred(AutoBlur.initIsBlurred())
# Start watching dirs
self.addWatchDir()
class WatchdogHandler(FileSystemEventHandler):
_callback = None
def __init__(self, callback):
if callback is None:
raise ValueError("callback cannot be None")
super().__init__()
self._callback = callback
def on_created(self, event):
if not event.is_directory:
src_path = str(event.src_path)
path = Path(src_path)
_log(f"[Watchdog] file created: {path}")
self._callback(path) # type: ignore
def on_moved(self, event):
if not event.is_directory:
dest_path = str(event.dest_path)
path = Path(dest_path)
_log(f"[Watchdog] file moved to: {path}")
self._callback(path) # type: ignore
def addWatchDir(self):
normalHandler = self.WatchdogHandler(self._onNormalDirEvent)
blurredHandler = self.WatchdogHandler(self._onBlurredDirEvent)
observer = Observer()
observer.schedule(normalHandler, str(self._normalDir), recursive=False)
observer.schedule(blurredHandler, str(self._blurredDir), recursive=False)
observer.start()
_log(f"[Watchdog] watching dirs: {self._normalDir}, {self._blurredDir}")
def _onNormalDirEvent(self, path: Path):
if not self._isBlurred.is_set():
self._apply(path)
def _onBlurredDirEvent(self, path: Path):
if self._isBlurred.is_set():
self._apply(path)
@staticmethod
def initIsBlurred() -> bool:
"""[ $(niri msg focused-window | wc -l) -gt 1 ]"""
cmd = ["niri", "msg", "focused-window"]
try:
output = subprocess.check_output(cmd, text=True)
lines = output.strip().splitlines()
return len(lines) > 1
except Exception as e:
_log(f"[initIsBlurred] failed to check focused window, assuming none: {e}")
return False
def setBlurred(self, isBlurred: bool) -> None:
# Cache state, avoid starting thread unnecessarily
if not self._isFirst and self._isBlurred.is_set() == isBlurred:
_log("[AutoBlur] state unchanged")
return
self._isFirst = False
if isBlurred:
self._isBlurred.set()
_log("[AutoBlur] set to blurred")
else:
self._isBlurred.clear()
_log("[AutoBlur] set to normal")
if self._thread is None or not self._thread.is_alive():
self._thread = threading.Thread(target=self._run, daemon=True)
self._thread.start()
def _run(self) -> None:
"""Wait until wallpapers are ready & apply the correct one according to the current state"""
while True:
setBlurred = self._isBlurred.is_set()
if setBlurred:
wallpaper = getFirstFile(self._blurredDir)
else:
wallpaper = getFirstFile(self._normalDir)
if wallpaper is not None and wallpaper.exists():
success = self._apply(wallpaper)
if setBlurred != self._isBlurred.is_set():
# State changed during apply, loop again immediately
continue
if success:
# Applied successfully
break
sleep(self._interval)
def _apply(self, wallpaper: Path) -> bool:
with self._applyLock:
if wallpaper == self._lastWallpaper:
return True
if not swwwLoadImg("background", wallpaper):
return False
self._lastWallpaper = wallpaper
return True
autoBlurInst = AutoBlur(NORMAL_WALLPAPER_DIR, BLURRED_WALLPAPER_DIR)
def handleEvent(event_name, payload):
if event_name == "WindowFocusChanged":
_log(f"[EventHandler] WindowFocusChanged event received")
id = payload.get("id", "")
if isinstance(id, int):
_log(f"[EventHandler] focused window id: {id}")
autoBlurInst.setBlurred(True)
elif isinstance(id, str) and id == "None":
_log("[EventHandler] no focused window")
autoBlurInst.setBlurred(False)
else:
_log(f"[EventHandler] unknown id: {id}, assuming no focused window")
autoBlurInst.setBlurred(False)
elif event_name == "WindowsChanged":
_log(f"[EventHandler] WindowsChanged event received")
windows = payload.get("windows", [])
for window in windows:
if window.get("is_focused", False):
_log(f"[EventHandler] found focused window")
autoBlurInst.setBlurred(True)
return
_log("[EventHandler] no focused window found")
autoBlurInst.setBlurred(False)
elif event_name == "WindowOpenedOrChanged":
_log(f"[EventHandler] WindowOpenedOrChanged event received")
window = payload.get("window", {})
if window.get("is_focused", False):
_log(f"[EventHandler] opened/changed focused window")
autoBlurInst.setBlurred(True)
else:
_log(f"[EventHandler] unhandled event: {event_name}")
def printEvent(eventName, payload):
_log(
f"[EventHandler] event: {eventName}, payload:\n{json.dumps(payload, indent=2, ensure_ascii=False)}"
)
def connectNiri(niriSocket: str, handler) -> bool:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
sock.connect(niriSocket)
except Exception as e:
sock.close()
_log(f"[Socket] failed to connect to {niriSocket}: {e}")
return False
f = sock.makefile("rwb")
try:
f.write(b'"EventStream"\n')
f.flush()
first = f.readline()
if not first:
# raise RuntimeError("connection closed by server before handshake")
_log("[Socket] connection closed by server before handshake")
return False
try:
resp = json.loads(first.decode())
except Exception:
resp = first.decode().strip()
_log(f"[Socket] handshake response: {resp}")
while True:
line = f.readline()
if not line:
_log("[Socket] socket closed by server")
break
s = line.decode().strip()
if s == "":
continue
try:
obj = json.loads(s)
except Exception as e:
_log(f"[Socket] failed to parse line as JSON: {s}, error: {e}")
continue
keys = list(obj.keys())
if keys:
event_name = keys[0]
payload = obj[event_name]
else:
event_name = "<unknown>"
payload = obj
handler(event_name, payload)
finally:
try:
f.close()
except Exception:
pass
try:
sock.close()
except Exception:
return False
return True
if __name__ == "__main__":
# connectNiri(getNiriSocket(), printEvent)
# exit(0)
desktop = environ.get("XDG_CURRENT_DESKTOP", "")
if desktop == "niri":
_log("[Main] running in Niri")
_log("[Main] starting swww daemons")
if not swwwStartDaemon("background"):
exit(1)
if not swwwStartDaemon("backdrop"):
exit(1)
sleep(1) # give some time to start
_log("[Main] loading initial wallpapers")
# Init wallpaper for backdrop
blurred = getFirstFile(BLURRED_WALLPAPER_DIR)
if blurred:
swwwLoadImg("backdrop", blurred)
# Init wallpaper for background
normal = getFirstFile(NORMAL_WALLPAPER_DIR)
if normal:
swwwLoadImg("background", normal)
# Connect to Niri socket
_log("[Main] connecting to Niri socket")
niri_socket = getNiriSocket()
if not niri_socket:
_log("[Main] NIRI_SOCKET environment variable is not set.")
exit(1)
while True:
try:
if not connectNiri(niri_socket, handleEvent):
_log("[Main] Connection lost or failed.")
except Exception as e:
_log(f"[Main] Exception in connection loop: {e}")
_log("[Main] Retrying in 3 seconds...")
sleep(3)
niri_socket = getNiriSocket() or niri_socket
elif desktop == "Hyprland":
_log("[Main] running in Hyprland")
_log("[Main] starting swww daemon")
if not swwwStartDaemon("background"):
exit(1)
sleep(1) # similarly
_log("[Main] loading initial wallpaper")
normal = getFirstFile(NORMAL_WALLPAPER_DIR)
if normal:
swwwLoadImg("background", normal)
# Wait indefinitely
while True:
sleep(3600)
else:
_log(f"[Main] unsupported desktop environment: {desktop}")
exit(1)
@@ -1,51 +0,0 @@
#!/usr/bin/env bash
# Description:
# Script to toggle Waybar (start/stop/restart).
# Also manages the lyrics widget state.
#
# Requirements:
# - waybar
# - eww (for lyrics widget)
lyrics_widget_closed=0
function close() {
killall -q waybar
# Also close the lyrics widget if open
if eww active-windows | grep -q "lyrics-single"; then
eww close lyrics-single
lyrics_widget_closed=1
fi
}
function open() {
# the system tray will not work with kded6 started
if killall -q -9 "kded6"; then
while pgrep -u "$USER" -x "kded6" >/dev/null; do
sleep 0.2
done
fi
nohup waybar >/dev/null 2>/dev/null &
# Reopen the lyrics widget if it was previously closed
if [ $lyrics_widget_closed -eq 1 ]; then
eww open lyrics-single
fi
}
if [ "$1" = "restart" ]; then
close
while pgrep -u "$USER" -x "waybar" >/dev/null; do
sleep 0.2
done
open
elif pgrep -u "$USER" -x "waybar" >/dev/null; then
close
elif ! pgrep -u "$USER" -x "waybar" >/dev/null; then
open
else
echo "Usage: $0 [restart]"
exit 1
fi
@@ -1,18 +0,0 @@
#!/usr/bin/env bash
# Description:
# Create and switch to a new workspace in Hyprland.
# e.g. if current workspaces are 1,2,4, this will create and switch to workspace 5.
#
# Requirements:
# - hyprctl
# get highest workspace ID
max_id=$(hyprctl workspaces | grep '^workspace ID ' | awk '{print $3}' | sort -n | tail -1)
# case not found default to 0
if [ -z "$max_id" ]; then
max_id=0
fi
hyprctl dispatch workspace $((max_id + 1))
-16
View File
@@ -1,16 +0,0 @@
#!/bin/sh
# Description:
# Show current volume level with notification.
# Made for mako, and is one of mako's official examples.
#
# Requirements:
# - wpctl
# - notify-send
# Get the volume level and convert it to a percentage
volume=$(wpctl get-volume @DEFAULT_AUDIO_SINK@)
volume=$(echo "$volume" | awk '{print $2}')
volume=$(echo "( $volume * 100 ) / 1" | bc)
notify-send -t 1000 -a 'wp-vol' -h int:value:$volume "Volume: ${volume}%"
@@ -1,11 +0,0 @@
[Unit]
Description=Fetch Weather
After=network.target
[Service]
Type=oneshot
ExecStart=/home/Username_PLACEHOLDER/.config/eww/Main/scripts/weather --getdata
WorkingDirectory=/home/Username_PLACEHOLDER/.config/eww/Main/scripts
Environment=OPENWEATHER_API_KEY="Onecall_3.0_APIKey_PLACEHOLDER"
Environment=OPENWEATHER_LAT="Latitude_PLACEHOLDER"
Environment=OPENWEATHER_LON="Longitude_PLACEHOLDER"
@@ -1,10 +0,0 @@
[Unit]
Description=Fetch weather information every hour
Requires=fetch-weather.service
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
-20
View File
@@ -1,20 +0,0 @@
#!/bin/bash
[ -f "$HOME/.local/snippets/apply-color-helper" ] || {
echo "Missing helper script: $HOME/.local/snippets/apply-color-helper"
exit 1
}
. "$HOME/.local/snippets/apply-color-helper"
file="$path"/style.css
sed -i -E "s/^(@define-color\s+flavor\s+#)([0-9A-Fa-f]{6})(;)/\1${colorHex}\3/" "$file" || {
log_error "Failed to edit ${file}"
exit 1
}
if pgrep -x "waybar" -u "$USER" >/dev/null; then
waybar-toggle restart || log_error "Failed to restart waybar"
fi
log_success "waybar"
-291
View File
@@ -1,291 +0,0 @@
{
// -------------------------------------------------------------------------
// Global configuration
// -------------------------------------------------------------------------
"layer": "bottom",
"position": "top",
"margin-left": 0,
"margin-bottom": 0,
"margin-right": 0,
"spacing": 2, // Gaps between modules (px)
"modules-left": [
"custom/rofi",
"custom/separator",
"group/workspaceactions",
"custom/separator",
"hyprland/window",
"custom/mediaplayer"
],
"modules-center": [
"clock"
],
"modules-right": [
"group/monitors",
"custom/separator",
"group/tray-expander",
"idle_inhibitor",
"custom/power"
],
// -------------------------------------------------------------------------
// Modules
// -------------------------------------------------------------------------
// Separators
"custom/separator": {
"format": "|"
},
// Buttons
"custom/power": {
"format": "󰐥",
"tooltip": false,
"on-click": "wlogout",
"min-length": 2,
"max-length": 2
},
"custom/rofi": {
"format": "󰣇",
"tooltip": false,
// "on-click-right": "fuzzel -l 0 -p '>> ' | xargs -r sh -c",
// "on-click": "fuzzel",
// "on-click-middle": "pkill -9 fuzzel",
"on-click": "eww open main --toggle",
"on-click-right": "pkill rofi || rofi -show drun",
"min-length": 2,
"max-length": 2
},
"idle_inhibitor": {
"format": "{icon}",
"format-icons": {
"activated": "",
"deactivated": ""
},
"min-length": 2,
"max-length": 2
},
// Time and Date
"clock": {
"format": "{:%H:%M | %e %b}",
"tooltip-format": "<big>{:%Y %B}</big>\n<tt>{calendar}</tt>",
"today-format": "<b>{}</b>"
},
// System monitors
"group/monitors": {
"modules": [
"network#speed",
"custom/publicip",
"temperature",
"memory",
"cpu",
"battery",
"backlight",
"wireplumber"
],
"orientation": "inherit"
},
"network#speed": {
"interval": 1,
"format": "{ifname}",
"format-wifi": " {bandwidthDownBytes}  {bandwidthUpBytes} ",
"format-ethernet": " {bandwidthDownBytes}  {bandwidthUpBytes} ",
"format-disconnected": "󰌙",
"tooltip-format": "{ipaddr}",
"format-linked": "󰈁 {ifname} (No IP)",
"tooltip-format-wifi": "{essid} {signalStrength}%",
"tooltip-format-ethernet": "{ifname} 󰌘",
"tooltip-format-disconnected": "󰌙 Disconnected",
"min-length": 20
},
"custom/publicip": {
"interval": 30,
"return-type": "json",
"format": " {text}",
"tooltip-format": "{alt}",
"max-length": 6,
"min-length": 6,
"exec": "$HOME/.config/waybar/modules/publicip.sh",
"on-click": "rm -f $HOME/.config/waybar/modules/publicip.cache && sleep 0.1"
},
"temperature": {
"interval": 5,
"thermal-zone": 6,
"hwmon-path": "/sys/class/hwmon/hwmon6/temp1_input",
"critical-threshold": 80,
// "format-critical": " {temperatureC}°C",
"format-critical": " {temperatureC}°C",
"format": "{icon} {temperatureC}°C",
"format-icons": [
"",
"",
""
],
"max-length": 6,
"min-length": 6
},
"memory": {
"interval": 11,
// "format": " {used:0.2f} / {total:0.0f} GB",
"format": "󰍛 {percentage}%",
"on-click": "killall btop || ghostty -e btop",
"max-length": 6,
"min-length": 6
},
"cpu": {
"interval": 3,
//"format": " {}%", // Icon: microchip
"format": "󰘚 {usage}%",
"max-length": 6,
"min-length": 6,
"on-click": "killall btop || ghostty -e btop"
},
"battery": {
"interval": 30,
"states": {
"good": 95,
"warning": 30,
"critical": 15
},
"format": "{icon} {capacity}%",
"format-charging": " {capacity}%",
"format-plugged": " {capacity}%",
"format-icons": [
"",
"",
"",
"",
""
],
"max-length": 6,
"min-length": 6
},
"backlight": {
"device": "$DISPLAY_DEVICE",
"format": "{icon} {percent}%",
"format-alt": "{percent}% {icon}",
"format-alt-click": "click-right",
//"format-icons": ["", ""],
"format-icons": [
""
],
"on-scroll-down": "brightnessctl -d $BRIGHTNESSCTL_DEVICE set -5%",
"on-scroll-up": "brightnessctl -d $BRIGHTNESSCTL_DEVICE set +5%",
"max-length": 6,
"min-length": 6
},
"wireplumber": {
"on-click": "pwvucontrol",
//on-click: "${wpctl} set-mute @DEFAULT_AUDIO_SINK@ toggle";
"on-scroll-down": "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 0.04-",
"on-scroll-up": "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 0.04+",
"format": "{icon} {volume}%",
"format-muted": "",
"format-source": "",
"format-source-muted": "",
//"format-muted": "<span foreground='#fab387'> </span>",
//"format-icons": [ "<span foreground='#fab387'></span>" ]
"format-icons": {
"headphone": "",
"phone": "",
"portable": "",
"car": "",
"default": [
"",
"",
"",
"",
"",
""
]
},
"max-length": 6,
"min-length": 6
},
// Hyprland
"group/workspaceactions": {
"modules": [
"hyprland/workspaces#special",
"hyprland/workspaces",
"custom/workspacenew"
],
"orientation": "inherit"
},
"hyprland/workspaces": {
"all-outputs": true,
"format": "{id}",
"on-scroll-up": "hyprctl dispatch workspace e+1 1>/dev/null",
"on-scroll-down": "hyprctl dispatch workspace e-1 1>/dev/null",
"sort-by-number": true,
"active-only": false //,
// "window-rewrite-default": "",
// "window-rewrite": {
// "class<kitty>": "",
// "class<code>": "󰨞",
// "class<zen-browser>": "󰈹",
// "class<firefox>": "󰈹",
// "class<ghostty>": "",
// "class<spotify>": "󰓇"
// }
},
"hyprland/workspaces#special": {
"persistent-workspaces": {
"special:s": []
},
"persistent-only": true,
"show-special": true,
"special-visible-only": false,
"format": "S",
"window-rewrite-default": "" //,
// "window-rewrite": {
// "class<kitty>": "",
// "class<code>": "󰨞",
// "class<zen-browser>": "󰈹",
// "class<firefox>": "󰈹",
// "class<ghostty>": "",
// "class<spotify>": "󰓇"
// }
},
"custom/workspacenew": {
"format": "+",
"tooltip": false,
"on-click": "workspace-new"
},
"hyprland/window": {
"format": "",
"max-length": 100,
"separate-outputs": true,
"icon": true,
"on-click-middle": "hyprctl dispatch killactive",
"icon-size": 14
},
"custom/mediaplayer": {
"format": "{text}",
"return-type": "json",
"max-length": 100,
"escape": true,
"exec": "$HOME/.config/waybar/modules/mediaplayer.py 2> /dev/null",
"on-click": "playerctl play-pause",
"on-click-right": "lyrics-widgets",
"on-scroll-up": "playerctl next",
"on-scroll-down": "playerctl previous"
},
"group/tray-expander": {
"orientation": "inherit",
"drawer": {
"transition-duration": 600,
"children-class": "tray-group-item"
},
"modules": [
"custom/expand-icon",
"tray",
"custom/separator"
]
},
"custom/expand-icon": {
"format": "",
"tooltip": false,
"min-length": 2,
"max-length": 2
},
"tray": {
"icon-size": 15,
"spacing": 5
}
}
-26
View File
@@ -1,26 +0,0 @@
@define-color rosewater #f5e0dc;
@define-color flamingo #f2cdcd;
@define-color pink #f5c2e7;
@define-color mauve #cba6f7;
@define-color red #f38ba8;
@define-color maroon #eba0ac;
@define-color peach #fab387;
@define-color yellow #f9e2af;
@define-color green #a6e3a1;
@define-color teal #94e2d5;
@define-color sky #89dceb;
@define-color sapphire #74c7ec;
@define-color blue #89b4fa;
@define-color lavender #b4befe;
@define-color text #cdd6f4;
@define-color subtext1 #bac2de;
@define-color subtext0 #a6adc8;
@define-color overlay2 #9399b2;
@define-color overlay1 #7f849c;
@define-color overlay0 #6c7086;
@define-color surface2 #585b70;
@define-color surface1 #45475a;
@define-color surface0 #313244;
@define-color base #1e1e2e;
@define-color mantle #181825;
@define-color crust #11111b;
-3
View File
@@ -1,3 +0,0 @@
publicip.conf
publicip.cache
publicip.log
@@ -1,221 +0,0 @@
#!/usr/bin/env python3
from gi.repository.Playerctl import Player
from gi.repository import Playerctl, GLib
from typing import List
import os
import json
import signal
import sys
import logging
import argparse
import gi
gi.require_version("Playerctl", "2.0")
logger = logging.getLogger(__name__)
def signal_handler(sig, frame):
logger.info("Received signal to stop, exiting")
sys.stdout.write("\n")
sys.stdout.flush()
# loop.quit()
sys.exit(0)
class PlayerManager:
def __init__(self, selected_player=None, excluded_player=[]):
self.manager = Playerctl.PlayerManager()
self.loop = GLib.MainLoop()
self.manager.connect(
"name-appeared", lambda *args: self.on_player_appeared(*args)
)
self.manager.connect(
"player-vanished", lambda *args: self.on_player_vanished(*args)
)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
self.selected_player = selected_player
self.excluded_player = excluded_player.split(",") if excluded_player else []
self.init_players()
def init_players(self):
for player in self.manager.props.player_names:
if player.name in self.excluded_player:
continue
if self.selected_player is not None and self.selected_player != player.name:
logger.debug(f"{player.name} is not the filtered player, skipping it")
continue
self.init_player(player)
def run(self):
logger.info("Starting main loop")
self.loop.run()
def init_player(self, player):
logger.info(f"Initialize new player: {player.name}")
player = Playerctl.Player.new_from_name(player)
player.connect("playback-status", self.on_playback_status_changed, None)
player.connect("metadata", self.on_metadata_changed, None)
self.manager.manage_player(player)
self.on_metadata_changed(player, player.props.metadata)
def get_players(self) -> List[Player]:
return self.manager.props.players
def write_output(self, text, player):
logger.debug(f"Writing output: {text}")
output = {
"text": text,
"class": "custom-" + player.props.player_name,
"alt": player.props.player_name,
}
sys.stdout.write(json.dumps(output) + "\n")
sys.stdout.flush()
def clear_output(self):
sys.stdout.write("\n")
sys.stdout.flush()
def on_playback_status_changed(self, player, status, _=None):
logger.debug(
f"Playback status changed for player {player.props.player_name}: {status}"
)
self.on_metadata_changed(player, player.props.metadata)
def get_first_playing_player(self):
players = self.get_players()
logger.debug(f"Getting first playing player from {len(players)} players")
if len(players) > 0:
# if any are playing, show the first one that is playing
# reverse order, so that the most recently added ones are preferred
for player in players[::-1]:
if player.props.status == "Playing":
return player
# if none are playing, show the first one
return players[0]
else:
logger.debug("No players found")
return None
def show_most_important_player(self):
logger.debug("Showing most important player")
# show the currently playing player
# or else show the first paused player
# or else show nothing
current_player = self.get_first_playing_player()
if current_player is not None:
self.on_metadata_changed(current_player, current_player.props.metadata)
else:
self.clear_output()
def on_metadata_changed(self, player, metadata, _=None):
logger.debug(f"Metadata changed for player {player.props.player_name}")
player_name = player.props.player_name
artist = player.get_artist()
title = player.get_title()
title = title.replace("&", "&amp;")
track_info = ""
if (
player_name == "spotify"
and "mpris:trackid" in metadata.keys()
and ":ad:" in player.props.metadata["mpris:trackid"]
):
track_info = "Advertisement"
elif artist is not None and title is not None:
track_info = f"{artist} - {title}"
else:
track_info = title
if track_info:
if player.props.status == "Playing":
track_info = "" + track_info
else:
track_info = "" + track_info
# only print output if no other player is playing
current_playing = self.get_first_playing_player()
if (
current_playing is None
or current_playing.props.player_name == player.props.player_name
):
self.write_output(track_info, player)
else:
logger.debug(
f"Other player {current_playing.props.player_name} is playing, skipping"
)
def on_player_appeared(self, _, player):
logger.info(f"Player has appeared: {player.name}")
if player.name in self.excluded_player:
logger.debug(
"New player appeared, but it's in exclude player list, skipping"
)
return
if player is not None and (
self.selected_player is None or player.name == self.selected_player
):
self.init_player(player)
else:
logger.debug(
"New player appeared, but it's not the selected player, skipping"
)
def on_player_vanished(self, _, player):
logger.info(f"Player {player.props.player_name} has vanished")
self.show_most_important_player()
def parse_arguments():
parser = argparse.ArgumentParser()
# Increase verbosity with every occurrence of -v
parser.add_argument("-v", "--verbose", action="count", default=0)
parser.add_argument("-x", "--exclude", "- Comma-separated list of excluded player")
# Define for which player we"re listening
parser.add_argument("--player")
parser.add_argument("--enable-logging", action="store_true")
return parser.parse_args()
def main():
arguments = parse_arguments()
# Initialize logging
if arguments.enable_logging:
logfile = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "media-player.log"
)
logging.basicConfig(
filename=logfile,
level=logging.DEBUG,
format="%(asctime)s %(name)s %(levelname)s:%(lineno)d %(message)s",
)
# Logging is set by default to WARN and higher.
# With every occurrence of -v it's lowered by one
logger.setLevel(max((3 - arguments.verbose) * 10, 0))
logger.info("Creating player manager")
if arguments.player:
logger.info(f"Filtering for player: {arguments.player}")
if arguments.exclude:
logger.info(f"Exclude player {arguments.exclude}")
player = PlayerManager(arguments.player, arguments.exclude)
player.run()
if __name__ == "__main__":
main()
@@ -1,62 +0,0 @@
#!/usr/bin/env bash
# shellcheck disable=SC1091,SC1090
# Entries in publicip.conf:
# IP_QUERY_URL: URL to query public IP of the system.
# return: JSON object with "ip" field.
# note: This URL will be queried with short intervals (60s for example),
# therefore it may not be a good idea to use a public API with
# a limited number of calls.
# IP_INFO_URL: URL to query IP location.
# placeholder: <ip>
# return: JSON object with "country_code" field.
# note: This URL will only be quetried when public IP changes or when "force" is given as parameter.
path="$(dirname "$(readlink -f "$0")")"
cache_file="$path/publicip.cache"
config_file="$path/publicip.conf"
time_log="$path/publicip.log"
[ -f "$config_file" ] || exit 1
. "$config_file"
[ -z "$IP_QUERY_URL" ] && exit 1
[ -z "$IP_INFO_URL" ] && exit 1
[ "$1" == "force" ] && rm -f "$cache_file"
[ -f "$cache_file" ] && . "$cache_file"
# Try to check network connectivity before querying
if ! ping -c 1 -W 2 1.1.1.1 >/dev/null 2>&1; then
# No network, return cached values if available
[ -z "$CACHED_IP" ] && CACHED_IP="N/A"
[ -z "$CACHED_CODE" ] && CACHED_CODE="N/A"
echo "$(date +%Y-%m-%dT%H:%M:%S) - Waiting for network" >>"$time_log"
jq -n --unbuffered --compact-output \
--arg ip "$CACHED_IP" \
--arg country "$CACHED_CODE" \
'{alt: $ip, text: $country}'
exit 0
fi
ip_current=$(curl -s -L -4 "$IP_QUERY_URL" | jq -r '.ip')
[ -z "$ip_current" ] && exit 1
if [ "$ip_current" != "$CACHED_IP" ]; then
echo "$(date +%Y-%m-%dT%H:%M:%S) - IP changed: $CACHED_IP -> $ip_current" >>"$time_log"
CACHED_IP="$ip_current"
ip_info_url=${IP_INFO_URL//<ip>/$ip_current}
CACHED_CODE=$(curl -s -L "$ip_info_url" | jq -r '.country_code')
[ -z "$CACHED_CODE" ] && CACHED_CODE="N/A"
echo "CACHED_IP=$CACHED_IP" >"$cache_file"
echo "CACHED_CODE=$CACHED_CODE" >>"$cache_file"
notify-send "New Public IP detected" "New IP: $ip_current\nCountry: $CACHED_CODE"
fi
jq -n --unbuffered --compact-output \
--arg ip "$CACHED_IP" \
--arg country "$CACHED_CODE" \
'{alt: $ip, text: $country}'
-217
View File
@@ -1,217 +0,0 @@
@import 'mocha.css';
@define-color flavor #89b4fa;
/* @define-color archlinux #1793d1; */
@define-color archlinux @sapphire;
/* Font(s) */
* {
/* main font icons CJK fallback */
font-family: 'Sour Gummy Light', 'Meslo LGM Nerd Font Mono', 'Sarasa UI SC', 'Noto Sans', sans-serif;
font-size: 16px;
}
/* Reset all styles */
* {
border: none;
border-radius: 14px;
min-height: 0;
margin: 2px 1px 2px 1px;
padding: 0;
transition-property: background-color;
transition-duration: 0.5s;
}
/* The whole bar */
#waybar {
background: linear-gradient(to bottom, alpha(@base, 0.8), alpha(@base, 0));
/* background: transparent; */
color: @text;
border-radius: 0px;
margin: 0px;
}
tooltip {
background: @base;
border: 2px solid @overlay0;
}
#workspaceactions,
#window,
#clock,
#monitors,
#custom-mediaplayer,
#custom-power-menu,
#tray,
#custom-rofi,
#idle_inhibitor,
#custom-power {
padding: 0px 10px;
}
#custom-separator {
padding: 0px 5px;
font-size: 20px;
}
#custom-rofi,
#idle_inhibitor,
#custom-power,
#custom-expand-icon {
padding: 0px 6px;
font-size: 18px;
}
#custom-workspacenew,
#workspaces button {
padding: 0px 5px;
margin: 3px 3px;
border-radius: 8px;
color: @flavor;
background-color: transparent;
transition: all 0.3s ease-in-out;
}
#workspaces button:hover {
background-color: alpha(@flavor, 0.3);
}
#workspaces button.active {
color: @base;
background: @flavor;
}
#workspaces button.urgent {
color: @base;
background-color: @red;
}
#workspaceactions {
padding-left: 1px;
padding-right: 1px;
}
#workspaces {
padding: 0px;
margin: 0px;
}
#window {
transition: none; /* Disable background transition */
}
window#waybar.empty #window {
background-color: transparent;
padding: 0;
margin: 0;
}
#custom-mediaplayer {
color: @flavor;
}
#network.speed {
color: @flavor;
}
#custom-publicip {
color: @peach;
}
#temperature {
color: @yellow;
}
#memory {
color: @green;
}
#cpu {
color: @teal;
}
#battery {
color: @sapphire;
}
#battery.charging,
#battery.full,
#battery.plugged {
color: @green;
}
#backlight {
color: @blue;
}
#wireplumber {
color: @lavender;
}
#custom-power {
color: @maroon;
}
#custom-power:hover {
background-color: alpha(@maroon, 0.3);
}
#custom-rofi {
color: @archlinux;
}
#custom-rofi:hover {
background-color: alpha(@archlinux, 0.3);
}
#custom-expand-icon {
color: @green;
}
#idle_inhibitor {
color: @yellow;
}
#idle_inhibitor:hover {
background-color: alpha(@yellow, 0.3);
}
#idle_inhibitor.activated {
color: @peach;
}
#clock {
color: @flavor;
}
@keyframes blink {
to {
background-color: alpha(@red, 0.5);
}
}
#battery.critical:not(.charging) {
color: @red;
animation-name: blink;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#network.disconnected {
color: @red;
}
#temperature.critical {
background-color: #eb4d4b;
}
#tray > .passive {
-gtk-icon-effect: dim;
}
#tray > .needs-attention {
-gtk-icon-effect: highlight;
background-color: #eb4d4b;
}
-10
View File
@@ -1,10 +0,0 @@
#!/usr/bin/env sh
# Terminate already running bar instances
killall -q waybar
# Wait until the processes have been shut down
while pgrep -x waybar -u "$USER" >/dev/null; do sleep 1; done
# Launch main
waybar &