Add eww bar
This commit is contained in:
parent
17d95033f2
commit
38afdbb493
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
hyprctl activeworkspace -j | jq '.id'
|
||||||
|
|
||||||
|
socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - |
|
||||||
|
stdbuf -o0 awk -F '>>|,' -e '/^workspace>>/ {print $2}' -e '/^focusedmon>>/ {print $3}'
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
monitor="${1}"
|
||||||
|
|
||||||
|
spaces (){
|
||||||
|
hyprctl workspaces -j | tr -d '\n' | jq -c "[.[] | select(.monitor | contains(\"${monitor}\"))]"
|
||||||
|
}
|
||||||
|
|
||||||
|
spaces
|
||||||
|
socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | while read -r line; do
|
||||||
|
spaces
|
||||||
|
done
|
|
@ -0,0 +1,128 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
from string import Template
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def panic(err):
|
||||||
|
import traceback
|
||||||
|
print(traceback.format_exc())
|
||||||
|
print(f"error {err}")
|
||||||
|
os._exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
class Monitor:
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
width: int
|
||||||
|
height: int
|
||||||
|
def __init__(self, id: int, name: str, width: int, height: int):
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
|
||||||
|
|
||||||
|
def get_monitors() -> list[Monitor]:
|
||||||
|
ws = subprocess.run(
|
||||||
|
["hyprctl", "monitors", "-j"],
|
||||||
|
capture_output=True
|
||||||
|
)
|
||||||
|
_monitors = json.loads(ws.stdout)
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
for m in _monitors:
|
||||||
|
ret.append(Monitor(
|
||||||
|
id=m["id"],
|
||||||
|
name=m["name"],
|
||||||
|
width=m["width"],
|
||||||
|
height=m["height"],
|
||||||
|
))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def temlate(source: str, monitor: Monitor, bar_name: str, home: str, base_dir: str) -> str:
|
||||||
|
height = int(monitor.height * .02)
|
||||||
|
return Template(source) \
|
||||||
|
.safe_substitute({
|
||||||
|
"monitor": monitor.id,
|
||||||
|
"monitor_name": monitor.name,
|
||||||
|
"bar_name": bar_name,
|
||||||
|
"home": home,
|
||||||
|
"base_dir": base_dir,
|
||||||
|
"height": height,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def generate_bar_config(monitor: Monitor, bar_name: str, home: str, base_dir: str, source_dir: str, dest_dir: str):
|
||||||
|
items = os.listdir(source_dir)
|
||||||
|
for item in items:
|
||||||
|
if os.path.isdir(f"{source_dir}/{item}"):
|
||||||
|
os.makedirs(f"{dest_dir}/{item}")
|
||||||
|
generate_bar_config(monitor, bar_name, home, base_dir, f"{source_dir}/{item}", f"{dest_dir}/{item}")
|
||||||
|
elif os.path.isfile(f"{source_dir}/{item}"):
|
||||||
|
data = ""
|
||||||
|
try:
|
||||||
|
with open(f"{source_dir}/{item}", "r") as fp:
|
||||||
|
data = fp.read()
|
||||||
|
except Exception as e:
|
||||||
|
panic(e)
|
||||||
|
|
||||||
|
data = temlate(
|
||||||
|
data,
|
||||||
|
monitor,
|
||||||
|
bar_name,
|
||||||
|
home,
|
||||||
|
base_dir
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(f"{dest_dir}/{item}", "w") as fp:
|
||||||
|
fp.write(data)
|
||||||
|
except Exception as e:
|
||||||
|
panic(e)
|
||||||
|
|
||||||
|
|
||||||
|
def launch_bar(monitor: Monitor, wayland_display: str):
|
||||||
|
bar_name = f"bar-{wayland_display}-{monitor.id}"
|
||||||
|
dir = f"/tmp/vbar/{wayland_display}/{monitor.id}"
|
||||||
|
|
||||||
|
home = os.getenv("HOME", default=None)
|
||||||
|
if home == None:
|
||||||
|
panic("HOME environment variable is unset")
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs(dir)
|
||||||
|
except FileExistsError:
|
||||||
|
try:
|
||||||
|
subprocess.run(["rm", "-rf", dir])
|
||||||
|
os.makedirs(dir)
|
||||||
|
except Exception as e:
|
||||||
|
panic(e)
|
||||||
|
|
||||||
|
config = generate_bar_config(monitor, bar_name, home, dir, f"{home}/.config/eww/templates/bar", dir)
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.run(["eww", "-c", dir, "reload"])
|
||||||
|
subprocess.run(["eww", "-c", dir, "open", bar_name])
|
||||||
|
except Exception as e:
|
||||||
|
panic(e)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
wayland_display = os.getenv("WAYLAND_DISPLAY", default=None)
|
||||||
|
if wayland_display is None:
|
||||||
|
os.exit(1)
|
||||||
|
monitors = get_monitors()
|
||||||
|
for monitor in monitors:
|
||||||
|
launch_bar(
|
||||||
|
monitor=monitor,
|
||||||
|
wayland_display=wayland_display,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
swaylock \
|
||||||
|
--screenshots \
|
||||||
|
--clock \
|
||||||
|
--indicator \
|
||||||
|
--indicator-radius 100 \
|
||||||
|
--indicator-thickness 7 \
|
||||||
|
--effect-blur 7x5 \
|
||||||
|
--effect-vignette 0.5:0.5 \
|
||||||
|
--ring-color bb00cc \
|
||||||
|
--key-hl-color 880033 \
|
||||||
|
--line-color 00000000 \
|
||||||
|
--inside-color 00000088 \
|
||||||
|
--separator-color 00000000 \
|
||||||
|
--grace 2 \
|
||||||
|
--fade-in 0.2
|
|
@ -0,0 +1,20 @@
|
||||||
|
@import "$base_dir/modules/workspaces.scss";
|
||||||
|
@import "$base_dir/modules/clock.scss";
|
||||||
|
@import "$base_dir/modules/weather.scss";
|
||||||
|
@import "$base_dir/modules/widget.scss";
|
||||||
|
@import "$base_dir/modules/management.scss";
|
||||||
|
@import "$base_dir/variables.scss";
|
||||||
|
|
||||||
|
*{
|
||||||
|
all: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbar {
|
||||||
|
padding: .4rem;
|
||||||
|
font-family: "FiraCode Nerd Font";
|
||||||
|
font-size: 1.2rem;
|
||||||
|
background-color: rgba($background, 1);
|
||||||
|
color: rgba($foreground, 1);
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2px solid $b_cyan;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
; Args:
|
||||||
|
; home: The user home directory
|
||||||
|
; base_dir: The installation directory
|
||||||
|
; bar_name: The bar name (should be unique)
|
||||||
|
; monitor: The Hyprland monitor id
|
||||||
|
; monitor_name: The Hyprland monitor name
|
||||||
|
(include "$base_dir/modules/bar.yuck")
|
||||||
|
|
||||||
|
(defwindow $bar_name
|
||||||
|
:geometry (geometry :x "0" :y "15"
|
||||||
|
:anchor "bottom center"
|
||||||
|
:height "$height" :width "60%")
|
||||||
|
:exclusive true
|
||||||
|
:monitor $monitor
|
||||||
|
(bar ))
|
|
@ -0,0 +1,3 @@
|
||||||
|
(deflisten activeworkspaceid
|
||||||
|
:initial "2"
|
||||||
|
"$home/.config/eww/scripts/get-activeworkspace-id")
|
|
@ -0,0 +1,16 @@
|
||||||
|
(include "$base_dir/modules/workspaces.yuck")
|
||||||
|
(include "$base_dir/modules/activeworkspaceid.yuck")
|
||||||
|
(include "$base_dir/modules/widgets-panel.yuck")
|
||||||
|
(include "$base_dir/modules/management.yuck")
|
||||||
|
|
||||||
|
(defwidget bar[]
|
||||||
|
(box
|
||||||
|
:vexpand false
|
||||||
|
:hexpand false
|
||||||
|
:class "vbar"
|
||||||
|
(workspaces-widget)
|
||||||
|
(box
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
(widgets-panel)
|
||||||
|
(management))))
|
|
@ -0,0 +1,8 @@
|
||||||
|
@import "$base_dir/variables.scss";
|
||||||
|
|
||||||
|
.clock {
|
||||||
|
padding: .3rem;
|
||||||
|
margin: .3rem;
|
||||||
|
background-color: $black;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
(defpoll time
|
||||||
|
:interval "1s"
|
||||||
|
`date +'{"hour":"%H","min":"%M","sec":"%S"}'`)
|
||||||
|
(defwidget clock[]
|
||||||
|
(clock-h))
|
||||||
|
|
||||||
|
(defwidget clock-v[]
|
||||||
|
(box
|
||||||
|
:class "clock widget"
|
||||||
|
:orientation "vertical"
|
||||||
|
(label :text "${time.hour}")
|
||||||
|
(label :text "${time.min}")))
|
||||||
|
|
||||||
|
(defwidget clock-h[]
|
||||||
|
(box
|
||||||
|
:class "clock"
|
||||||
|
:orientation "horizontal"
|
||||||
|
(label :text "${time.hour}:${time.min}")))
|
|
@ -0,0 +1,29 @@
|
||||||
|
@import "$base_dir/variables.scss";
|
||||||
|
|
||||||
|
.management {
|
||||||
|
padding: .3rem;
|
||||||
|
margin: .3rem;
|
||||||
|
background-color: $black;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: .3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background-color: $b_black;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lock-btn {
|
||||||
|
color: $blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reboot-btn {
|
||||||
|
color: $yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shutdown-btn {
|
||||||
|
color: $red;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
(defwidget management[]
|
||||||
|
(box
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
:class "management"
|
||||||
|
(lock)
|
||||||
|
(reboot)
|
||||||
|
(shutdown)))
|
||||||
|
|
||||||
|
(defwidget lock[]
|
||||||
|
(button
|
||||||
|
:class "lock-btn btn"
|
||||||
|
:onclick "$home/.config/eww/scripts/lock"
|
||||||
|
""))
|
||||||
|
|
||||||
|
(defwidget reboot[]
|
||||||
|
(button
|
||||||
|
:class "reboot-btn btn"
|
||||||
|
:onclick "reboot"
|
||||||
|
""))
|
||||||
|
|
||||||
|
(defwidget shutdown[]
|
||||||
|
(button
|
||||||
|
:class "shutdown-btn btn"
|
||||||
|
:onclick "poweroff"
|
||||||
|
""))
|
|
@ -0,0 +1,12 @@
|
||||||
|
@import "$base_dir/variables.scss";
|
||||||
|
|
||||||
|
.weather {
|
||||||
|
padding: .3rem;
|
||||||
|
margin: .3rem;
|
||||||
|
background-color: $black;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-icon {
|
||||||
|
padding-right: .8rem;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
(defpoll weather
|
||||||
|
:interval "30m"
|
||||||
|
:default `curl 'https://api.open-meteo.com/v1/forecast?latitude=37.98&longitude=23.73¤t_weather=true'`
|
||||||
|
`curl 'https://api.open-meteo.com/v1/forecast?latitude=37.98&longitude=23.73¤t_weather=true'`)
|
||||||
|
|
||||||
|
(defwidget weather-widget[]
|
||||||
|
(weather-widget-h))
|
||||||
|
|
||||||
|
(defwidget weather-widget-v[]
|
||||||
|
(box
|
||||||
|
:class "weather widget"
|
||||||
|
:orientation "vertical"
|
||||||
|
(weather-type)
|
||||||
|
(temp)))
|
||||||
|
|
||||||
|
(defwidget weather-widget-h[]
|
||||||
|
(box
|
||||||
|
:class "weather"
|
||||||
|
:orientation "horizontal"
|
||||||
|
:space-evenly false
|
||||||
|
(weather-type)
|
||||||
|
(temp)))
|
||||||
|
|
||||||
|
(defwidget temp[]
|
||||||
|
(label :text "${weather.current_weather.temperature}°C"))
|
||||||
|
|
||||||
|
;; https://open-meteo.com/en/docs
|
||||||
|
;; 0 Clear sky
|
||||||
|
;; 1, 2, 3 Mainly clear, partly cloudy, and overcast
|
||||||
|
;; 45, 48 Fog and depositing rime fog
|
||||||
|
;; 51, 53, 55 Drizzle: Light, moderate, and dense intensity
|
||||||
|
;; 56, 57 Freezing Drizzle: Light and dense intensity
|
||||||
|
;; 61, 63, 65 Rain: Slight, moderate and heavy intensity
|
||||||
|
;; 66, 67 Freezing Rain: Light and heavy intensity
|
||||||
|
;; 71, 73, 75 Snow fall: Slight, moderate, and heavy intensity
|
||||||
|
;; 77 Snow grains
|
||||||
|
;; 80, 81, 82 Rain showers: Slight, moderate, and violent
|
||||||
|
;; 85, 86 Snow showers slight and heavy
|
||||||
|
;; 95 * Thunderstorm: Slight or moderate
|
||||||
|
;; 96, 99 * Thunderstorm with slight and heavy hail
|
||||||
|
(defwidget weather-type[]
|
||||||
|
(label
|
||||||
|
:class "weather-icon"
|
||||||
|
:text {weather.current_weather.weathercode == 1 ? "" :
|
||||||
|
weather.current_weather.weathercode < 4 ? "" :
|
||||||
|
weather.current_weather.weathercode == 45 || weather.current_weather.weathercode == 48 ? "" :
|
||||||
|
weather.current_weather.weathercode == 51 || weather.current_weather.weathercode == 53 ||
|
||||||
|
weather.current_weather.weathercode == 55 || weather.current_weather.weathercode == 56 ||
|
||||||
|
weather.current_weather.weathercode == 57 ? "" :
|
||||||
|
weather.current_weather.weathercode == 61 || weather.current_weather.weathercode == 63 ||
|
||||||
|
weather.current_weather.weathercode == 65 || weather.current_weather.weathercode == 66 ||
|
||||||
|
weather.current_weather.weathercode == 67 ? "" :
|
||||||
|
weather.current_weather.weathercode == 71 || weather.current_weather.weathercode == 73 ||
|
||||||
|
weather.current_weather.weathercode == 75 || weather.current_weather.weathercode == 77 ? "" :
|
||||||
|
weather.current_weather.weathercode == 80 || weather.current_weather.weathercode == 81 ||
|
||||||
|
weather.current_weather.weathercode == 82 ? "" :
|
||||||
|
weather.current_weather.weathercode == 85 || weather.current_weather.weathercode == 86 ? "":
|
||||||
|
weather.current_weather.weathercode == 95 || weather.current_weather.weathercode == 96 ||
|
||||||
|
weather.current_weather.weathercode == 99 ? "" : "err: ${weather.current_weather.weathercode}"}))
|
|
@ -0,0 +1,11 @@
|
||||||
|
@import "$base_dir/variables.scss";
|
||||||
|
|
||||||
|
.widget {
|
||||||
|
font-size: 1rem;
|
||||||
|
padding: .2rem;
|
||||||
|
margin-left: .4rem;
|
||||||
|
margin-right: .4rem;
|
||||||
|
background-color: rgba($black, 1);
|
||||||
|
border: 1px solid $magenta;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
(include "$base_dir/modules/clock.yuck")
|
||||||
|
(include "$base_dir/modules/weather.yuck")
|
||||||
|
|
||||||
|
(defwidget widgets-panel[]
|
||||||
|
(box
|
||||||
|
:halign "end"
|
||||||
|
:space-evenly false
|
||||||
|
(weather-widget)
|
||||||
|
(clock)))
|
|
@ -0,0 +1,28 @@
|
||||||
|
@import "$base_dir/variables.scss";
|
||||||
|
|
||||||
|
.workspaces-widget {
|
||||||
|
margin-left: .4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-entry {
|
||||||
|
padding-left: .6rem;
|
||||||
|
padding-right: .6rem;
|
||||||
|
background-color: rgba($black, 1);
|
||||||
|
border: 1px solid $magenta;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-entry:hover {
|
||||||
|
background-color: rgba($b_black, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-current {
|
||||||
|
background-color: rgba($yellow, 1);
|
||||||
|
color: rgba($b_black, 1);
|
||||||
|
border: 0px none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-current:hover {
|
||||||
|
background-color: rgba($yellow, 1);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
(deflisten workspaces
|
||||||
|
:initial "[]"
|
||||||
|
"$home/.config/eww/scripts/get-workspaces $monitor_name")
|
||||||
|
|
||||||
|
(defwidget workspaces-widget[]
|
||||||
|
(box
|
||||||
|
:space-evenly false
|
||||||
|
:class "wk-${activeworkspaceid} workspaces-widget"
|
||||||
|
:halign "start"
|
||||||
|
:hexpand true
|
||||||
|
:spacing 8
|
||||||
|
(for workspace in workspaces
|
||||||
|
(workspace-entry :workspace_id "${workspace.id}"))))
|
||||||
|
|
||||||
|
(defwidget workspace-entry[workspace_id]
|
||||||
|
(button :onclick "hyprctl dispatch workspace ${workspace_id}"
|
||||||
|
:class "workspace-entry ${workspace_id == activeworkspaceid ? "workspace-current" : ""}"
|
||||||
|
(label :text "${workspace_id}")))
|
|
@ -0,0 +1,20 @@
|
||||||
|
$background: #1a1b26;
|
||||||
|
$foreground: #c0caf5;
|
||||||
|
|
||||||
|
$black: #15161E;
|
||||||
|
$red: #f7768e;
|
||||||
|
$green: #9ece6a;
|
||||||
|
$yellow: #e0af68;
|
||||||
|
$blue: #7aa2f7;
|
||||||
|
$magenta: #bb9af7;
|
||||||
|
$cyan: #7dcfff;
|
||||||
|
$white: #a9b1d6;
|
||||||
|
|
||||||
|
$b_black: #414868;
|
||||||
|
$b_red: #f7768e;
|
||||||
|
$b_green: #9ece6a;
|
||||||
|
$b_yellow: #e0af68;
|
||||||
|
$b_blue: #7aa2f7;
|
||||||
|
$b_magenta: #bb9af7;
|
||||||
|
$b_cyan: #7dcfff;
|
||||||
|
$b_white: #c0caf5;
|
Loading…
Reference in New Issue