From 5313a2914ded544ba63e266740caed8ccaec7f8c Mon Sep 17 00:00:00 2001 From: Elias Renman Date: Thu, 30 Nov 2023 00:49:32 +0100 Subject: [PATCH] feat: waybar (broken workspaces) --- waybar/config | 231 +++++++++++++++++++++++++++++++ waybar/scripts/PBPbattery.sh | 21 +++ waybar/scripts/keyhint.sh | 2 + waybar/scripts/mediaplayer.py | 127 ++++++++++++++++++ waybar/scripts/weather.sh | 13 ++ waybar/style.css | 246 ++++++++++++++++++++++++++++++++++ 6 files changed, 640 insertions(+) create mode 100644 waybar/config create mode 100755 waybar/scripts/PBPbattery.sh create mode 100755 waybar/scripts/keyhint.sh create mode 100644 waybar/scripts/mediaplayer.py create mode 100755 waybar/scripts/weather.sh create mode 100644 waybar/style.css diff --git a/waybar/config b/waybar/config new file mode 100644 index 0000000..8102637 --- /dev/null +++ b/waybar/config @@ -0,0 +1,231 @@ +// Global +{ + "layer": "top", + "position": "top", + "margin": 5, + + // If height property would be not present, it'd be calculated dynamically + "height": 30, + + "modules-left": [ + "hyprland/workspaces", + ], + + "modules-center": [ + "clock", + ], + + "modules-right": [ + "tray", + // "idle_inhibitor", + "memory", + "cpu", + // "custom/keyboard-layout", + //"custom/PBPbattery", + // "backlight#icon", + "backlight#value", + "pulseaudio", + "pulseaudio#microphone", + "network", + "battery", + "custom/power", + ], + + // Modules + + "idle_inhibitor": { + "format": "{icon} ", + "format-icons":{ + "activated": "", + "deactivated": "" + } + }, + + "battery": { + "states": { + // "good": 95, + "warning": 30, + "critical": 15 + }, + "format": "{capacity}% {icon} ", + "format-charging": "{capacity}% 󰂄", + "format-plugged": "{capacity}% ", + // "format-good": "", // An empty format will hide the module + // "format-full": "", + "format-icons": ["", "", "", "", ""] + }, + + "custom/PBPbattery": { + "exec": "sh ~/.config/waybar/scripts/PBPbattery.sh", + "format": "{}", + }, + + "clock": { + "interval": 10, + // "format-alt": " {:%e %b %Y}", // Icon: calendar-alt + "format": "{:%e %b %Y %H:%M} ", + "tooltip-format": "{:%e %B %Y}" + }, + + "cpu": { + "interval": 5, + "format": " {usage}% ({load})", // Icon: microchip + "states": { + "warning": 70, + "critical": 90, + }, + "on-click": "alacritty -e 'btm'", + }, + + "custom/keyboard-layout": { + "exec": "swaymsg -t get_inputs | grep -m1 'xkb_active_layout_name' | cut -d '\"' -f4", + // Interval set only as a fallback, as the value is updated by signal + "interval": 30, + "format": " {}", // Icon: keyboard + // Signal sent by Sway key binding (~/.config/sway/key-bindings) + "signal": 1, // SIGHUP + "tooltip": false, + "on-click": "sh ~/.config/waybar/scripts/keyhint.sh", + }, + + "memory": { + "interval": 5, + "format": " {}%", // Icon: memory + "on-click": "alacritty -e 'btm'", + "states": { + "warning": 70, + "critical": 90 + } + }, + + "network": { + "interval": 5, + "format-wifi": " ", // Icon: wifi + "format-ethernet": " ", // Icon: ethernet + "format-disconnected": "⚠ Disconnected", + "tooltip-format": "{ifname}: {ipaddr}", + "on-click": "alacritty -e 'nmtui'", + }, + "network#vpn": { + "interface": "tun0", + "format": " ", + "format-disconnected": "⚠ Disconnected", + "tooltip-format": "{ifname}: {ipaddr}/{cidr}", + }, + + "hyprland/mode": { + "format": "{}", + "tooltip": false + }, + + "hyprland/window": { + "format": "{}", + "max-length": 120 + }, + + "hyprland/workspaces": { + "format": "{icon}", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1" + }, + + "pulseaudio": { + "scroll-step": 1, // %, can be a float + "format": "{icon} {volume}%", + "format-bluetooth": "{volume}% {icon}  {format_source}", + "format-bluetooth-muted": " {icon}  {format_source}", + "format-muted": "󰸈", + "format-icons": { + "headphone": "󰋋", + "hands-free": "וֹ", + "headset": "  ", + "phone": "", + "portable": "", + "car": "", + "default": [""] + }, + "on-click": "pactl set-sink-mute @DEFAULT_SINK@ toggle", + "on-click-right": "pavucontrol", + "on-scroll-up": "pactl set-sink-volume @DEFAULT_SINK@ +2%", + "on-scroll-down": "pactl set-sink-volume @DEFAULT_SINK@ -2%", + }, + + "pulseaudio#microphone": { + "format": "{format_source}", + "format-source": " {volume}%", + "format-source-muted": " ", + "on-click": "pamixer --default-source -t", + "on-click-right": "pavucontrol", + "on-scroll-up": "pamixer --default-source -i 5", + "on-scroll-down": "pamixer --default-source -d 5", + "scroll-step": 5 + }, + + // to use the weather module replace with your city or town + // note: do not use spaces: new york would be newyork + "custom/weather": { + "exec": "sh ~/.config/waybar/scripts/weather.sh tampa", + "return-type": "json", + "interval": 600, + }, + + "tray": { + "icon-size": 18, + "spacing":10, + }, + + "backlight#icon": { + "format": "{icon}", + "on-scroll-down": "brightnessctl -c backlight set 1%-", + "on-scroll-up": "brightnessctl -c backlight set +1%" + }, + + "backlight#value" :{ + "format": "{icon} {percent}%", + "format-icons": [" "], + "on-scroll-down": "brightnessctl -c backlight set 1%-", + "on-scroll-up": "brightnessctl -c backlight set +1%" + }, + + "custom/firefox": { + "format": " ", + "on-click": "exec firefox", + "tooltip": false + }, + + "custom/terminal": { + "format": " ", + "on-click": "exec alacritty", + "tooltip": false + }, + + "custom/files": { + "format": " ", + "on-click": "exec nautilus", + "tooltip": false + }, + + "custom/launcher": { + "format":" ", + "on-click": "exec wofi -c ~/.config/wofi/config -I", + "tooltip": false, + }, + + "custom/power": { + "format":"⏻", + "on-click": "exec wlogout", + "tooltip": false, + }, + + "custom/media": { + "format": "{icon} {}", + "return-type": "json", + "max-length": 40, + "format-icons": { + "spotify": "", + "default": "󰗃" + }, + "escape": true, + "exec": "/usr/bin/python3 $HOME/.config/waybar/scripts/mediaplayer.py 2> /dev/null" // Script in resources folder + } +} diff --git a/waybar/scripts/PBPbattery.sh b/waybar/scripts/PBPbattery.sh new file mode 100755 index 0000000..1cf34da --- /dev/null +++ b/waybar/scripts/PBPbattery.sh @@ -0,0 +1,21 @@ + +#!/bin/bash +#simple Shellscript for waybar/i3blocks/polybar on Pinebook pro +#05012020 geri123@gmx.net Gerhard S. + +PERCENT=$(cat /sys/class/power_supply/cw2015-battery/capacity) +STATUS=$(cat /sys/class/power_supply/cw2015-battery/status) +case $(( + $PERCENT >= 0 && $PERCENT <= 20 ? 1 : + $PERCENT > 20 && $PERCENT <= 40 ? 2 : + $PERCENT > 40 && $PERCENT <= 60 ? 3 : + $PERCENT > 60 && $PERCENT <= 80 ? 4 : 5)) in +# + (1) echo $STATUS:"":$PERCENT%;; + (2) echo $STATUS:"":$PERCENT%;; + (3) echo $STATUS:"":$PERCENT%;; + (4) echo $STATUS:"":$PERCENT%;; + (5) echo $STATUS:"":$PERCENT%;; +esac + + diff --git a/waybar/scripts/keyhint.sh b/waybar/scripts/keyhint.sh new file mode 100755 index 0000000..01f3396 --- /dev/null +++ b/waybar/scripts/keyhint.sh @@ -0,0 +1,2 @@ +#!/bin/sh +yad --title="EndeavourOS Sway-WM keybindings:" --no-buttons --geometry=400x345-15-400 --list --column=key: --column=description: --column=command: "ESC" "close this app" "" "=" "modkey" "(set mod Mod4)" "+enter" "Terminal" "(xfce4-terminal)" "+d" "Application Menu" "(wofi)" "+p" "Activities" "(wofi)" "+o" "" "Open Broswer" "+n" "" "Open Files" "+q" "close focused app" "(kill)" "[Shift]+Print-key" "screenshot" "(grim)" "+Shift+e" "power-menu" "(wofi)" "+t" "open keybinding helper" "full list" diff --git a/waybar/scripts/mediaplayer.py b/waybar/scripts/mediaplayer.py new file mode 100644 index 0000000..5bf8f3b --- /dev/null +++ b/waybar/scripts/mediaplayer.py @@ -0,0 +1,127 @@ +import argparse +import logging +import sys +import signal +import gi +import json +gi.require_version('Playerctl', '2.0') +from gi.repository import Playerctl, GLib + +logger = logging.getLogger(__name__) + + +def write_output(text, player): + logger.info('Writing output') + + 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 on_play(player, status, manager): + logger.info('Received new playback status') + on_metadata(player, player.props.metadata, manager) + + +def on_metadata(player, metadata, manager): + logger.info('Received new metadata') + track_info = '' + + if player.props.player_name == 'spotify' and \ + 'mpris:trackid' in metadata.keys() and \ + ':ad:' in player.props.metadata['mpris:trackid']: + track_info = 'AD PLAYING' + elif player.get_artist() != '' and player.get_title() != '': + track_info = '{artist} - {title}'.format(artist=player.get_artist(), + title=player.get_title()) + else: + track_info = player.get_title() + + if player.props.status != 'Playing' and track_info: + track_info = ' ' + track_info + write_output(track_info, player) + + +def on_player_appeared(manager, player, selected_player=None): + if player is not None and (selected_player is None or player.name == selected_player): + init_player(manager, player) + else: + logger.debug("New player appeared, but it's not the selected player, skipping") + + +def on_player_vanished(manager, player): + logger.info('Player has vanished') + sys.stdout.write('\n') + sys.stdout.flush() + + +def init_player(manager, name): + logger.debug('Initialize player: {player}'.format(player=name.name)) + player = Playerctl.Player.new_from_name(name) + player.connect('playback-status', on_play, manager) + player.connect('metadata', on_metadata, manager) + manager.manage_player(player) + on_metadata(player, player.props.metadata, manager) + + +def signal_handler(sig, frame): + logger.debug('Received signal to stop, exiting') + sys.stdout.write('\n') + sys.stdout.flush() + # loop.quit() + sys.exit(0) + + +def parse_arguments(): + parser = argparse.ArgumentParser() + + # Increase verbosity with every occurrence of -v + parser.add_argument('-v', '--verbose', action='count', default=0) + + # Define for which player we're listening + parser.add_argument('--player') + + return parser.parse_args() + + +def main(): + arguments = parse_arguments() + + # Initialize logging + logging.basicConfig(stream=sys.stderr, level=logging.DEBUG, + format='%(name)s %(levelname)s %(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)) + + # Log the sent command line arguments + logger.debug('Arguments received {}'.format(vars(arguments))) + + manager = Playerctl.PlayerManager() + loop = GLib.MainLoop() + + manager.connect('name-appeared', lambda *args: on_player_appeared(*args, arguments.player)) + manager.connect('player-vanished', on_player_vanished) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + for player in manager.props.player_names: + if arguments.player is not None and arguments.player != player.name: + logger.debug('{player} is not the filtered player, skipping it' + .format(player=player.name) + ) + continue + + init_player(manager, player) + + loop.run() + + +if __name__ == '__main__': + main() diff --git a/waybar/scripts/weather.sh b/waybar/scripts/weather.sh new file mode 100755 index 0000000..b03cd1c --- /dev/null +++ b/waybar/scripts/weather.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +LOC="$1" +# HTML encode string as %20 +LOCATION=$(sed -e "s/ /%20/g" <<<"$LOC") +content=$(curl -sS "https://thisdavej.azurewebsites.net/api/weather/current?loc=$LOCATION°=C") +ICON=$(curl -s 'https://wttr.in/?format=1' | sed 's/[+0-9a-cA-Z°-]//g' ) +# echo $ICON +TEMP=$(echo $content | jq -r '. | "\(.temperature)°\(.degType)"' | sed 's/"//g') +TOOLTIP=$(echo $content | jq -r '. | "\(.temperature)°\(.degType)\n\(.skytext)"' | sed 's/"//g') +CLASS=$(echo $content | jq .skytext) +echo '{"text": "'$TEMP'", "tooltip": "'$ICON $TOOLTIP $LOC'", "class": '$CLASS' }' + diff --git a/waybar/style.css b/waybar/style.css new file mode 100644 index 0000000..1005a4b --- /dev/null +++ b/waybar/style.css @@ -0,0 +1,246 @@ +/* ============================================================================= + * + * Waybar configuration + * + * Configuration reference: https://github.com/Alexays/Waybar/wiki/Configuration + * + * =========================================================================== */ + +/* ----------------------------------------------------------------------------- + * Keyframes + * -------------------------------------------------------------------------- */ + +/* +Arc-Dark Color Scheme +*/ +@keyframes blink-warning { + 70% { + color: white; + } + + to { + color: white; + background-color: orange; + } +} + +@keyframes blink-critical { + 70% { + color: white; + } + + to { + color: white; + background-color: red; + } +} + +/* ----------------------------------------------------------------------------- + * Base styles + * -------------------------------------------------------------------------- */ + +/* Reset all styles */ +* { + border: none; + border-radius: 0; + min-height: 0; + margin: 1px; + padding: 0; + color: #66ACED; +} + + +/* The whole bar */ +window#waybar { + /* color: #dfdfdf; */ + /* background-color: rgba(0,0,0,0.8); */ + /* background-color: rgba(8,0,37,0.85); */ + background-color: rgba(0,0,0,0); + /* font-family: JetBrains Mono Nerd Font; */ + font-family: Intel One Mono Nerd Font; + font-size: 14px; + /* border-radius: 22px; */ +} + +/* Every modules */ +#battery, +#clock, +#backlight, +#cpu, +#custom-keyboard-layout, +#memory, +#mode, +#custom-weather, +#network, +#pulseaudio, +#temperature, +#tray, +#idle_inhibitor, +#window, +#custom-power, +#workspaces, +#custom-media, +#custom-PBPbattery { + padding:0.25rem 0.75rem; + margin: 1px 6px; + background-color: rgba(0,0,0,0.8); + border-radius: 20px; +} + +/* ----------------------------------------------------------------------------- + * Modules styles + * -------------------------------------------------------------------------- */ + +#clock { + /* color: #ff4499; */ + color: #73daca; +} + +#custom-weather { + color: #ff4499; +} + +#battery { + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +#battery.warning { + color: orange; +} + +#battery.critical { + color: red; +} + +#battery.warning.discharging { + animation-name: blink-warning; + animation-duration: 3s; +} + +#battery.critical.discharging { + animation-name: blink-critical; + animation-duration: 2s; +} + +#cpu { + color: #f7768e; +} + +#cpu.warning { + color: orange; +} + +#cpu.critical { + color: red; +} + +#memory { + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + color: #f7768e; +} + +#memory.warning { + color: orange; + } + +#memory.critical { + color: red; + animation-name: blink-critical; + animation-duration: 2s; + padding-left:5px; + padding-right:5px; +} + +#mode { + /* background: @highlight; */ + /* background: #dfdfdf; */ + border-bottom: 3px transparent; + color:#ff4499; + margin-left: 5px; + padding: 7px; +} + +#network.disconnected { + color: orange; +} + +#pulseaudio { + color: #bb9af7; + border-left: 0px; + border-right: 0px; + margin-right: 0; + border-radius: 20px 0 0 20px; +} + +/* #pulseaudio.muted { */ +/* color: #ff4499; */ +/* } */ +/**/ +#pulseaudio.microphone { + border-left: 0px; + border-right: 0px; + margin-left: 0; + padding-left: 0; + border-radius: 0 20px 20px 0; +} + +/* #pulseaudio.microphone.muted { */ +/* color: #ff4499; */ +/* } */ + + +#temperature.critical { + color: red; +} + +#window { + font-weight: bold; + color: #f7768e; +} + +#custom-media { + color: #bb9af7; +} + +#workspaces { + font-size:16px; + background-color: rgba(0,0,0,0.8); + border-radius: 20px; +} + +#workspaces button { + border-bottom: 3px solid transparent; + margin-bottom: 0px; + color: #dfdfdf; +} + +#workspaces button.active { + border-bottom: 1px solid #ff4499; + margin-bottom: 1px; + padding-left:0; +} + +#workspaces button.urgent { + border-color: #c9545d; + color: #c9545d; +} + +#custom-power { + font-size:18px; + padding-right: 1rem; +} + +#custom-launcher { + font-size:15px; + margin-left:15px; + margin-right:10px; +} + +#backlight.icon { + padding-right:1px; + font-size: 13px; +}