💥 eww(bar/workspaces): fix workspace indicator with a literal script

This commit is contained in:
retrozinndev
2024-12-10 10:41:06 -03:00
parent 75ce9fa8f9
commit cacc59cb8e
41 changed files with 377 additions and 782 deletions
+9 -19
View File
@@ -1,20 +1,10 @@
; Variables
(include "variables.yuck")
; Windows
(include "./windows/calendar.yuck")
(include "./windows/control-center.yuck")
(include "./windows/bar.yuck")
(include "./windows/powermenu.yuck")
(include "./windows/audio-popup.yuck")
; Bar widgets
(include "./widgets/bar/workspaces.yuck")
(include "./widgets/bar/clock.yuck")
(include "./widgets/bar/control-center.yuck")
(include "./widgets/bar/audio.yuck")
(include "./widgets/bar/media.yuck")
(include "./widgets/bar/logo.yuck")
(include "./widgets/bar/window.yuck")
(include "./widgets/bar/network.yuck")
(include "./widgets/bar/battery.yuck")
; Control Center widgets
(include "windows/calendar.yuck")
(include "windows/control-center.yuck")
(include "windows/bar.yuck")
(include "windows/powermenu.yuck")
(include "windows/audio-popup.yuck")
(include "windows/notification-popup.yuck")
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env
hyprctl -j activeworkspace | jq -c
handle() {
case $1 in
workspace*) hyprctl -j activeworkspace | jq -c ;;
esac
}
socat -U - UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | while read -r line; do handle "$line"; done
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
send_notification() {
notify-send -u normal -a "Color Picker" "$1" "$2"
}
# Check if user has hyprpicker installed
if ! [[ -f /bin/hyprpicker ]]; then
send_notification "An error occurred" "Looks like you don't have Hyprpicker installed! Try installing it before using the Color Picker tool."
exit 1
fi
selected_color=$(hyprpicker)
if ! [[ $selected_color == "" ]]; then
wl-copy $selected_color
send_notification "Selected Color" "The selected color is <span foreground='$selected_color'>$selected_color</span>, it was also copied to your clipboard!"
fi
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env python
# Original Script by vimjoyer, modified by retrozinndev
# Licensed under the MIT License, as in vimjoyer's repository and also in retrozinndev's Hyprland Dots.
# This script watches for notifications to display as a popup in eww.
import threading
import time
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
class Notification:
def __init__(self, app_name, summary, body, icon, replaces_id, timeout):
self.app_name = app_name
self.summary = summary
self.body = body
self.icon = icon
self.replaces_id = replaces_id
notifications_on_popup = []
notifications = []
notification_timeout = 10 # In seconds
def remove_popup_notification(notification):
time.sleep(notification_timeout)
notifications.remove(notification)
reload_output()
def add_popup_notification(notification):
notifications.insert(0, notification)
reload_output()
timer_thread = threading.Thread(target=remove_popup_notification, args=(notification,)) # Only used for notification popup, not history
timer_thread.start()
def reload_output():
lastItem_notifications = len(notifications) - 1
output = ""
for item in notifications:
if item is not notifications[lastItem_notifications]:
output = output + f"{{ \"applicationName\": \"{item.app_name}\", \"image\": \"{item.icon}\", \"summary\": \"{item.summary}\", \"body\": \"{item.body}\", \"id\": {item.replaces_id}, \"timeout\": {item.timeout} }}, "
else:
output = "["+ output + f"{{ \"applicationName\": \"{item.app_name}\", \"image\": \"{item.icon}\", \"summary\": \"{item.summary}\", \"body\": \"{item.body}\", \"id\": {item.replaces_id}, \"timeout\": {item.timeout} }} ]"
print(f"{output}", flush=True)
class NotificationServer(dbus.service.Object):
def __init__(self):
bus_name = dbus.service.BusName("org.freedesktop.Notifications", bus=dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, "/org/freedesktop/Notifications")
@dbus.service.method("org.freedesktop.Notifications", in_signature="susssasa{ss}i", out_signature="u")
def Notify(self, app_name, replaces_id, icon, summary, body, actions, hints, timeout):
add_popup_notification(Notification(app_name, summary, body, icon, replaces_id, timeout))
return 0
@dbus.service.method("org.freedesktop.Notifications", out_signature="ssss")
def GetServerInformation(self):
return ("Custom Notification Server", "ExampleNS", "1.0", "1.2")
DBusGMainLoop(set_as_default=True)
if __name__ == "__main__":
server = NotificationServer()
mainloop = GLib.MainLoop()
mainloop.run()
-10
View File
@@ -1,10 +0,0 @@
#!/usr/bin/env bash
prev_history=$(dunstctl history)
while true; do
if ! [[ $prev_history == $(dunstctl history) ]]; then
prev_history=$(dunstctl history)
echo "$(echo $prev_history | jq -c '.data.[]')"
fi
done
-61
View File
@@ -1,61 +0,0 @@
# Original Script by vimjoyer, modified by retrozinndev
# Licensed under the MIT License, as in vimjoyer's repository and also in retrozinndev's Hyprland Dots.
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
import threading
import time
class Notification:
def __init__(self, app_name, summary, body, icon):
self.app_name = app_name
self.summary = summary
self.body = body
self.icon = icon
notifications = []
def remove_notification(notification):
time.sleep(10)
notifications.remove(notification)
reload_output()
def add_notification(notification):
notifications.insert(0, notification)
reload_output()
timer_thread = threading.Thread(target=remove_notification, args=(notification,))
timer_thread.start()
def reload_output():
output = ""
for notification in notifications:
output = "aaaaaaaa"
output.replace('\n', ' ')
print(f"{ output }", flush=True)
class NotificationServer(dbus.service.Object):
def __init__(self):
bus_name = dbus.service.BusName("org.freedesktop.Notifications", bus=dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, "/org/freedesktop/Notifications")
@dbus.service.method("org.freedesktop.Notifications", in_signature="susssasa{ss}i", out_signature="u")
def Notify(self, app_name, replaces_id, app_icon, summary, body, actions, hints, timeout):
add_notification(Notification(app_name, summary, body, app_icon))
return 0
@dbus.service.method("org.freedesktop.Notifications", out_signature="ssss")
def GetServerInformation(self):
return ("Custom Notification Server", "ExampleNS", "1.0", "1.2")
DBusGMainLoop(set_as_default=True)
if __name__ == "__main__":
server = NotificationServer()
mainloop = GLib.MainLoop()
mainloop.run()
+29 -3
View File
@@ -1,11 +1,37 @@
#!/usr/bin/env bash
# display workspaces before checking for events
hyprctl -j workspaces | jq -c
#!/usr/bin/env bash
print_workspaces_literal() {
active_workspace_id=$(hyprctl -j activeworkspace | jq .id | xargs)
existing_workspaces=$(hyprctl -j workspaces | jq .[].id | xargs)
output="
(box :class \"workspaces\"
:space-evenly false
:orientation \"horizontal\""
for i in {1..10}; do
output=$output"
(button :onclick \"hyprctl dispatch workspace $i\"
:class { $active_workspace_id == $i ? \"active\" : \"\" }
:visible { \"$existing_workspaces\" =~ $i ? true : false }
\"\")"
if [ $i == 10 ]; then
output=$output")" # closes box if last
fi
done
echo "$(echo $output | xargs -0)"
}
# display workspaces on startup
print_workspaces_literal
handle() {
case $1 in
workspace* | destroyworkspace*) hyprctl -j workspaces | jq -c ;;
workspace*) print_workspaces_literal;;
esac
}
+28 -2
View File
@@ -8,8 +8,10 @@ box.audio-popup {
}
.audio-popup .separator {
box-shadow: 0 0 0 1px darken($color: $foreground, $amount: 25);
margin: 4px 0;
border-top: .5px solid rgba(darken($color: $foreground, $amount: 25), .7);
margin-bottom: 8px;
margin-left: 6px;
margin-right: 6px;
border-radius: 1px;
}
@@ -26,3 +28,27 @@ box.audio-popup {
color: $background;
}
}
.audio-popup {
trough {
background: darken($color: $foreground, $amount: 25);
border-radius: 6px;
}
trough highlight {
background: $foreground;
padding: 10px;
border-radius: inherit;
}
slider:active highlight {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
scale {
padding: 10px;
}
}
+7 -12
View File
@@ -33,26 +33,21 @@
}
}
.workspaces {
// Styles the literal script for workspace indicators
.workspaces {
padding: 2px 0px;
border-radius: 10px;
& > button {
padding: 0 0;
border-radius: 16px;
margin: 0 2px;
padding: 5px 12px;
background: $color1;
transition: ease-in 80ms;
transition-property: all;
&.active {
padding: 0 22px;
padding: 5px 22px;
background: $foreground;
}
&.default {
padding: 0 12px;
}
}
}
@@ -180,11 +175,11 @@
}
}
.notifications button {
.control-center-toggle button {
padding-left: 12px;
padding-right: 10px;
&.open, &:hover {
background: $color3;
&.open {
background: darken($color: $color3, $amount: 15);
}
}
+52
View File
@@ -27,6 +27,14 @@ box.cc {
.button-row {
margin: 7px 0;
}
.color-picker {
padding-right: 11px;
}
.powermenu {
padding-right: 11px;
}
}
.control-center .mediaplayer {
@@ -151,3 +159,47 @@ box.cc {
}
}
}
.toggle-grid {
.grid-toggle .toggle {
margin: 0 6px;
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
}
}
.grid-toggle {
&.active {
background: darken($color: $color1, $amount: 2);
}
& > .toggle {
padding: 8px;
border-radius: 18px;
label {
font-family: "Cantarell", "0xProto Nerd Font";
}
.icon {
margin-right: 6px;
font-size: 16px;
}
label.header {
font-weight: 700;
font-size: 12px;
}
label.body {
font-size: 11px;
}
}
}
+6 -3
View File
@@ -58,17 +58,20 @@ box.vertical-button-row {
}
}
button {
button,
.button {
padding: 6px 10px;
border-radius: 12px;
background: none;
}
button:hover {
button:hover,
.button:hover {
background: darken($color: $color2, $amount: 5);
}
button:active {
button:active,
.button:active {
background: darken($color: $color3, $amount: 10);
}
+31
View File
@@ -0,0 +1,31 @@
; All globally used variables are stored here
; Listeners
(deflisten json_notification_history :initial `[]`
`python scripts/notification-daemon.py`)
(deflisten json_volume :initial `{ "output": 60, "source": 80 }`
`sh scripts/get-volume-watch.sh`)
(deflisten literal_workspaces :initial ""
`sh scripts/workspaces.sh`)
; Date and time
(defpoll day-name :interval "5s"
`date +"%A"`)
(defpoll day :interval "5s"
`date +"%d"`)
(defpoll month :interval "5s"
`date +"%m"`)
(defpoll month-name :interval "5s"
`date +"%B"`)
(defpoll year :interval "5s"
`date +"%Y"`)
(defpoll time :interval "5s"
`date +"%H:%M"`)
+1 -1
View File
@@ -5,7 +5,7 @@
(overlay
(scale :min 0
:max 100
:value "${volume_json.output}"
:value "${json_volume.output}"
:orientation "horizontal"
:draw-value false
:flipped false
+1 -1
View File
@@ -5,7 +5,7 @@
(overlay
(scale :min 0
:max 100
:value "${volume_json.source}"
:value "${json_volume.source}"
:orientation "horizontal"
:draw-value false
:flipped false
+2 -5
View File
@@ -1,15 +1,12 @@
(deflisten json_audio :initial `{ "output": 35, "source": 80 }`
`sh ./scripts/get-volume-watch.sh`)
(defwidget audio []
(eventbox :onclick "eww open --toggle audio-popup"
:class "audio-eventbox"
(box :class "audio"
(eventbox :onscroll `[ {} == "up" ] && wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ || wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-`
(label :text "${ json_audio.output != 0 ? '󰕾' : '󰝟' } ${json_audio.output}%"))
(label :text "${ json_volume.output != 0 ? '󰕾' : '󰝟' } ${json_volume.output}%"))
(eventbox :onscroll `[ {} == "up" ] && wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%+ || wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%-`
(label :text "${ json_audio.source != 0 ? '󰍬' : '󰍭' } ${json_audio.source}%"))
(label :text "${ json_volume.source != 0 ? '󰍬' : '󰍭' } ${json_volume.source}%"))
)
)
)
@@ -1,5 +1,5 @@
(defwidget control-center-toggle []
(defwidget cc-toggle []
(box :class "control-center-toggle"
(button :onclick "eww open --toggle control-center"
" ")
+1 -5
View File
@@ -1,10 +1,6 @@
(defpoll datetime :interval "10s"
`date +"%A %d, %H:%M"`)
(defwidget clock []
(box :class "clock"
(button :onclick "eww open calendar-window --toggle"
"${datetime}")
"${day-name} ${day}, ${time}")
)
)
+1 -14
View File
@@ -1,19 +1,6 @@
(deflisten json_workspaces :initial '[{"id": "1"},{"id": "2"}]'
`sh ./scripts/workspaces.sh`)
(deflisten json_active_workspace :initial '{ "id": 1 }'
`sh ./scripts/active-workspace.sh`)
(defwidget workspaces []
(eventbox :onscroll "[[ {} == up ]] && hyprctl dispatch workspace e+1 >> /dev/null || hyprctl dispatch workspace e-1 >> /dev/null"
(box :class "workspaces"
:space-evenly false
(for workspace in json_workspaces
(button :onclick "hyprctl dispatch workspace ${workspace.id}"
:class "${ json_active_workspace.id == workspace.id ? "active" : "default" }"
"")
)
)
(literal :content literal_workspaces)
)
)
@@ -1,8 +1,5 @@
(include "widgets/control-center/notification.yuck")
(deflisten json_notification_history :initial "{[]}"
`python ./scripts/notification-watcher.py`)
(defwidget notifications []
(box :class "cc-notifications"
:space-evenly false
@@ -11,7 +8,7 @@
(scroll :class "vertical-scroll"
:hscroll false
:vscroll true
:height 400 ; Adjust according to your screen size
:height 400 ; Adjust according to control center size
:vexpand true
(box :class "notifications"
@@ -49,7 +46,7 @@
"󰒲")
(button :class "clear-all"
:onclick "dunstctl history-clear"
"Clear all ")
"Clear all")
)
)
)
+6 -2
View File
@@ -1,4 +1,5 @@
(deflisten hostname :initial "GNU/Linux"
(defpoll hostname :initial "GNU/Linux"
:interval "24h"
`cat /etc/hostname`)
(defpoll uptime_info :interval "50s"
@@ -13,7 +14,7 @@
:halign "start"
(label :xalign 0
:text " ${hostname}"
:text " ${hostname}"
:class "hostname")
(label :xalign 0
@@ -29,6 +30,9 @@
(button :class "lock"
:onclick "hyprctl dispatch exec hyprlock"
"󰌾")
(button :class "color-picker"
:onclick "sh $HOME/.config/eww/scripts/color-picker.sh"
"󰴱")
(button :class "powermenu"
:onclick "eww close-all; eww open powermenu"
"󰗽")
+50 -14
View File
@@ -1,36 +1,72 @@
(defwidget toggle-grid []
(box :class "toggle-grid"
(grid-toggle :class "network"
:icon "󰈀"
:header "Network"
:active true ; This sets if toggle is enabled or not, put condition check here
:body "Connected" ; Generally put state here
:visible true
:max-width 128
:max-height 48
:onclick "notify-send 'Network' 'toggle network with nmcli!'"
:orientation "vertical"
(box :orientation "horizontal"
:class "row"
(grid-toggle :class "network"
:icon "󰈀"
:header "Network"
:active true ; This sets if toggle is enabled or not, put condition check here
:body "Connected" ; Put state here (e.g.: enabled, disabled)
:visible true
:onclick "notify-send 'Network' 'toggle network with nmcli!'"
)
(grid-toggle :class "bluetooth"
:icon "󰂯"
:header "Bluetooth"
:active false
:body "Connected"
:visible true
:onclick "notify-send 'Network' 'toggle network with nmcli!'"
)
(grid-toggle :class "dnd"
:icon "󰍶"
:header "Do Not Disturb"
:active false
:body "Disabled"
:visible true
:onclick "notify-send 'Network' 'toggle network with nmcli!'"
)
)
(box :orientation "horizontal"
:class "row"
:space-evenly false
(grid-toggle :class "airplane"
:icon "󰀝"
:header "Airplane Mode"
:active false
:body "Disabled"
:visible true
:onclick "notify-send 'Network' 'toggle network with nmcli!'"
)
)
)
)
(defwidget grid-toggle [ class onclick active ?icon header body visible max-width max-height ]
(defwidget grid-toggle [ class onclick active ?icon header body visible ]
(eventbox :visible "${visible}"
:onclick "${onclick}"
:class "${class} ${ active ? 'active' : '' }"
:class "grid-toggle ${class} ${ active == true ? 'active' : '' } button"
(box :class "toggle"
:space-evenly false
:orientation "horizontal"
:width 142
:height 52
(label :class "icon"
:visible { icon != "" ? true : false }
:valign "center"
"${icon}")
:text "${icon}")
(box :orientation "vertical"
:space-evenly false
(label :class "header"
"${header}")
:text "${header}"
:xalign 0)
(label :class "body"
"${body}")
:text "${body}"
:xalign 0)
)
)
)
+1 -4
View File
@@ -1,9 +1,6 @@
(include "./widgets/audio-popup/output-slider.yuck")
(include "./widgets/audio-popup/source-slider.yuck")
(deflisten volume_json :initial `{ "output": 60, "source": 80 }`
`sh ./scripts/get-volume-watch.sh`)
(defwindow audio-popup []
:monitor 0
:namespace "eww-audio"
@@ -26,7 +23,7 @@
(box :class "vertical-button-row"
(button :class "more-settings"
:onclick "eww close audio-popup; hyprctl dispatch exec pavucontrol"
(label :text "Show on Volume Control"
(label :text "More devices"
:xalign 0))
)
)
+11 -1
View File
@@ -1,3 +1,13 @@
(include "./widgets/bar/workspaces.yuck")
(include "./widgets/bar/clock.yuck")
(include "./widgets/bar/cc-toggle.yuck")
(include "./widgets/bar/audio.yuck")
(include "./widgets/bar/media.yuck")
(include "./widgets/bar/logo.yuck")
(include "./widgets/bar/window.yuck")
(include "./widgets/bar/network.yuck")
(include "./widgets/bar/battery.yuck")
(defwindow bar
:monitor 0
:geometry (geometry :width "100%"
@@ -33,7 +43,7 @@
(audio)
(battery)
(network)
(control-center-toggle)
(cc-toggle)
)
)
)
+1 -1
View File
@@ -10,7 +10,7 @@
:orientation "vertical"
(label :class "calendar-header"
:text "Calendar")
:text "${month-name}")
(calendar :class "month-calendar"
:show-details true
:show-heading true
+1 -1
View File
@@ -18,6 +18,6 @@
(quickactions)
(toggle-grid)
(mediaplayer :album_background true)
(notifications)
(notifications :notification-history json_notification_history)
)
)
+47
View File
@@ -0,0 +1,47 @@
(defwindow floating-notification []
:monitor 0
:exclusive false
:focusable false
:namespace "eww-notification-popup"
:geometry (geometry :anchor "top right"
:width "128px"
:height "64px")
:stacking "overlay"
(box :class "floating-notifications"
(for item in json_notification_history
(floating-notification :summary "${item.summary}"
:body "${item.body}"
:image "${item.image}"
:app-name "${item.applicationName}")
)
)
)
(defwidget floating-notification [ summary body image app-name ]
(box :class "popup-notification"
:space-evenly false
:orientation "vertical"
(box :orientation "horizontal"
:class "top"
(label :text "${app-name}")
)
(box :orientation "horizontal"
(box :class "image"
:style "background-image: ${image};")
(box :class "content"
:orientation "vertical"
(label :class "summary"
:text "${summary}")
(label :class "body"
:text "${body}")
)
)
)
)