danshari!
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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/&/\&/g; s/</\</g; s/>/\>/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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 |
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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';
|
||||
@@ -1,2 +0,0 @@
|
||||
(include "./Main/eww.yuck")
|
||||
(include "./Lyrics/eww.yuck")
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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))
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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("&", "&")
|
||||
|
||||
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}'
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 &
|
||||
Reference in New Issue
Block a user