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