Add eww-hyprland package definition
This commit is contained in:
parent
c8965eb754
commit
9301993582
69
pkgs/eww-hyprland/README.md
Normal file
69
pkgs/eww-hyprland/README.md
Normal file
|
@ -0,0 +1,69 @@
|
|||
# Eww configuration
|
||||
|
||||
This configuration aims to provide a shell replacement for compositors/window
|
||||
managers. Features constantly get added and existing ones get improved.
|
||||
|
||||
## 🗃️ Components
|
||||
|
||||
The same daemon runs multiple windows which interact with each other:
|
||||
|
||||
### bar
|
||||
|
||||
![bar](https://github.com/fufexan/dotfiles/assets/36706276/c3339908-029c-4e56-88c5-e620dc8ce00d)
|
||||
|
||||
### music window
|
||||
|
||||
![music](https://github.com/fufexan/dotfiles/assets/36706276/4260362b-8c69-417e-94c0-1436dc9febf9)
|
||||
|
||||
### calendar
|
||||
|
||||
![calendar](https://github.com/fufexan/dotfiles/assets/36706276/ddf2a40d-f758-4072-ac14-2c254cb9393a)
|
||||
|
||||
### system info
|
||||
|
||||
![system](https://github.com/fufexan/dotfiles/assets/36706276/723fd8fe-538c-41a5-bcbf-218304dc3bdf)
|
||||
|
||||
## ❔ Usage
|
||||
|
||||
### Home Manager
|
||||
|
||||
If you use Home Manager, installing is as simple as adding my flake to your
|
||||
inputs, passing `inputs` to `extraSpecialArgs` and importing the relevant
|
||||
module:
|
||||
```nix
|
||||
{inputs, pkgs, ...}: {
|
||||
imports = [inputs.fufexan.homeManagerModules.eww-hyprland];
|
||||
|
||||
programs.eww-hyprland = {
|
||||
enable = true;
|
||||
|
||||
# default package
|
||||
package = pkgs.eww-wayland;
|
||||
|
||||
# if you want to change colors
|
||||
colors = builtins.readFile ./latte.scss;
|
||||
|
||||
# set to true to reload on change
|
||||
autoReload = false;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to also add the fonts listed below. You can simply search where
|
||||
they are in my config.
|
||||
|
||||
### Other distros
|
||||
|
||||
To quickly install this config, grab all the files in this directory and put
|
||||
them in `~/.config/eww`. Then run `eww daemon` and `eww open bar`. Enjoy!
|
||||
|
||||
Dependencies:
|
||||
- Icon fonts: [Material Symbols Outlined](https://github.com/google/material-design-icons/tree/master/variablefont)
|
||||
(any variation can be used as long as you change the `font-family` property of `.icon`)
|
||||
- Text font: [Product Sans](https://befonts.com/product-sans-font.html)
|
||||
- Script deps: everything in `default.nix`'s `dependencies` list.
|
||||
|
||||
## 🎨 Theme
|
||||
|
||||
The theme colors can be changed in `css/_colors.scss`. Currently the theme used
|
||||
is [Catppuccin Mocha](https://github.com/catppuccin/catppuccin).
|
29
pkgs/eww-hyprland/css/_calendar.scss
Normal file
29
pkgs/eww-hyprland/css/_calendar.scss
Normal file
|
@ -0,0 +1,29 @@
|
|||
.calendar-win {
|
||||
padding: .2em;
|
||||
@include window;
|
||||
}
|
||||
|
||||
calendar {
|
||||
padding: 5px;
|
||||
|
||||
:selected {
|
||||
color: $mauve;
|
||||
}
|
||||
|
||||
.header {
|
||||
color: $subtext1;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: $maroon;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.button {
|
||||
color: $sapphire;
|
||||
}
|
||||
|
||||
:indeterminate {
|
||||
color: $overlay0;
|
||||
}
|
||||
}
|
35
pkgs/eww-hyprland/css/_colors.scss
Normal file
35
pkgs/eww-hyprland/css/_colors.scss
Normal file
|
@ -0,0 +1,35 @@
|
|||
$rosewater: #f5e0dc;
|
||||
$flamingo: #f2cdcd;
|
||||
$pink: #f5c2e7;
|
||||
$mauve: #cba6f7;
|
||||
$red: #f38ba8;
|
||||
$maroon: #eba0ac;
|
||||
$peach: #fab387;
|
||||
$yellow: #f9e2af;
|
||||
$green: #a6e3a1;
|
||||
$teal: #94e2d5;
|
||||
$sky: #89dceb;
|
||||
$sapphire: #74c7ec;
|
||||
$blue: #89b4fa;
|
||||
$lavender: #b4befe;
|
||||
|
||||
$text: #cdd6f4;
|
||||
$subtext1: #bac2de;
|
||||
$subtext0: #a6adc8;
|
||||
$overlay2: #9399b2;
|
||||
$overlay1: #7f849c;
|
||||
$overlay0: #6c7086;
|
||||
|
||||
$surface2: #585b70;
|
||||
$surface1: #45475a;
|
||||
$surface0: #313244;
|
||||
|
||||
$base: #1e1e2e;
|
||||
$mantle: #181825;
|
||||
$crust: #11111b;
|
||||
|
||||
$fg: $text;
|
||||
$bg: rgba(30, 30, 46, 0.6);
|
||||
$bg1: rgba(49, 50, 68, 0.6);
|
||||
$border: #28283d;
|
||||
$shadow: $crust;
|
26
pkgs/eww-hyprland/css/_indicators.scss
Normal file
26
pkgs/eww-hyprland/css/_indicators.scss
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* screenshare & mic share indicators */
|
||||
.indicators {
|
||||
margin: .3rem;
|
||||
transition: 500ms ease-out;
|
||||
|
||||
:first-child {
|
||||
border-radius: 1rem 0 0 1rem;
|
||||
}
|
||||
|
||||
:last-child {
|
||||
border-radius: 0 1rem 1rem 0;
|
||||
}
|
||||
|
||||
:only-child {
|
||||
border-radius: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.indicator {
|
||||
color: $base;
|
||||
padding: 0 .3rem;
|
||||
}
|
||||
|
||||
.screenshare { background: $red; }
|
||||
.micshare { background: $green; }
|
||||
.camerashare { background: $blue; }
|
71
pkgs/eww-hyprland/css/_music.scss
Normal file
71
pkgs/eww-hyprland/css/_music.scss
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* module cover art */
|
||||
.song-cover-art {
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
margin: 4px 5px 4px 0;
|
||||
min-height: 24px;
|
||||
min-width: 24px;
|
||||
@include rounding;
|
||||
}
|
||||
|
||||
/* music window */
|
||||
.music-window {
|
||||
border: 1px solid $border;
|
||||
@include window;
|
||||
}
|
||||
|
||||
/* cover, left child */
|
||||
.music-cover-art {
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 2px -1px rgba(0,0,0,0.4);
|
||||
margin: 1em;
|
||||
min-height: 170px;
|
||||
min-width: 170px;
|
||||
}
|
||||
|
||||
/* info box, right child */
|
||||
.music-box {
|
||||
margin: 1rem 1rem 1rem 0;
|
||||
}
|
||||
|
||||
.music-title {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin: .5rem;
|
||||
}
|
||||
|
||||
.dark { color: $base; }
|
||||
.light { color: $text; }
|
||||
|
||||
.music-artist {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.music-button-box {
|
||||
margin: 1rem 0 0;
|
||||
}
|
||||
|
||||
.music-button label {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.music-time {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.music-bar scale {
|
||||
highlight {
|
||||
background-image: linear-gradient(to right, $teal, $sky);
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
trough {
|
||||
background-color: $bg1;
|
||||
border-radius: 24px;
|
||||
margin-top: 0;
|
||||
min-height: 10px;
|
||||
min-width: 170px;
|
||||
}
|
||||
}
|
36
pkgs/eww-hyprland/css/_osd.scss
Normal file
36
pkgs/eww-hyprland/css/_osd.scss
Normal file
|
@ -0,0 +1,36 @@
|
|||
.osd-part {
|
||||
margin: 0 .5rem .5rem;
|
||||
@include window;
|
||||
|
||||
label {
|
||||
color: $text;
|
||||
font-size: 2rem;
|
||||
margin: 0 .1rem 0 .2rem;
|
||||
}
|
||||
|
||||
scale {
|
||||
margin: -.2rem 0;
|
||||
}
|
||||
|
||||
trough {
|
||||
@include rounding;
|
||||
background-color: $bg1;
|
||||
margin: 1rem 0 .5rem;
|
||||
min-height: 10rem;
|
||||
min-width: .7rem;
|
||||
|
||||
highlight {
|
||||
@include rounding;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* scale highlight gradients for volume & brightness */
|
||||
.osd-volume highlight {
|
||||
background-image: linear-gradient(to top, $teal, $sky);
|
||||
}
|
||||
|
||||
.osd-brightness highlight {
|
||||
background-image: linear-gradient(to top, $yellow, $peach);
|
||||
}
|
137
pkgs/eww-hyprland/css/_sidebar.scss
Normal file
137
pkgs/eww-hyprland/css/_sidebar.scss
Normal file
|
@ -0,0 +1,137 @@
|
|||
/* system menu */
|
||||
.system-menu-box { @include window; }
|
||||
|
||||
/* between net/bt and their arrows */
|
||||
.separator {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* date & time */
|
||||
.top-row {
|
||||
margin: 1rem 1.5rem 0;
|
||||
|
||||
.time { font-size: 2rem; }
|
||||
|
||||
.date-box {
|
||||
margin: 0 1rem;
|
||||
|
||||
label { font-size: 1.1rem; }
|
||||
|
||||
.date {
|
||||
background: unset;
|
||||
margin: 0 .5rem 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* wifi/bt/airplane button boxes */
|
||||
.system-row {
|
||||
margin: .5rem .7rem;
|
||||
|
||||
/* the airplane icon is not properly spaced */
|
||||
.airplane-box button {
|
||||
padding: 1rem 3rem;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 1rem;
|
||||
margin: 0 .1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* wifi/bt/airplane buttons */
|
||||
.element {
|
||||
@include rounding;
|
||||
background-color: $bg1;
|
||||
margin: .3rem;
|
||||
|
||||
button {
|
||||
@include rounding;
|
||||
padding: 1rem;
|
||||
|
||||
label {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* volume & brightness sliders */
|
||||
.sliders {
|
||||
@include rounding;
|
||||
background-color: $bg1;
|
||||
margin: .5rem 1rem;
|
||||
padding: .6rem 1rem;
|
||||
|
||||
scale {
|
||||
margin-right: -1rem;
|
||||
min-width: 21.5rem;
|
||||
|
||||
trough { margin-right: 0; }
|
||||
}
|
||||
|
||||
box { margin: .2rem 0; }
|
||||
label { font-size: 1.2rem; }
|
||||
}
|
||||
|
||||
.volume-slider-box,
|
||||
.brightness-slider-box {
|
||||
trough { background-color: $base; }
|
||||
}
|
||||
|
||||
.volume-bar highlight {
|
||||
@include rounding;
|
||||
background-image: linear-gradient(to right, $teal, $sky);
|
||||
}
|
||||
|
||||
.brightness-slider-box scale highlight {
|
||||
@include rounding;
|
||||
background-image: linear-gradient(to right, $yellow, $peach);
|
||||
}
|
||||
|
||||
/* battery & power button */
|
||||
.bottom-row {
|
||||
margin: .5rem 1rem;
|
||||
|
||||
.battery-icon {
|
||||
color: $green;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.battery-icon .low { color: $red; }
|
||||
.battery-rate { color: $mauve; }
|
||||
|
||||
.battery-status {
|
||||
color: $subtext0;
|
||||
margin: 0 .5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: $bg1;
|
||||
border-radius: 50%;
|
||||
margin-bottom: .1rem;
|
||||
padding: 0 .5rem;
|
||||
|
||||
label { font-size: 1.5rem; }
|
||||
&:hover { background-color: $bg1; }
|
||||
}
|
||||
}
|
||||
|
||||
/* set wifi/bt colors and dim buttons when hovering */
|
||||
.element {
|
||||
button:hover { background-color: rgba(0, 0, 0, .1); }
|
||||
}
|
||||
|
||||
.bt-connected {
|
||||
background-color: $blue;
|
||||
color: $crust;
|
||||
}
|
||||
|
||||
.net-connected {
|
||||
background-color: $mauve;
|
||||
color: $crust;
|
||||
}
|
64
pkgs/eww-hyprland/css/_system.scss
Normal file
64
pkgs/eww-hyprland/css/_system.scss
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* right modules (circular-progress) */
|
||||
.cpubar { color: $blue; }
|
||||
.membar { color: $peach; }
|
||||
.batbar { color: $green; }
|
||||
.batbar .low { color: $red; }
|
||||
|
||||
.cpubar,
|
||||
.membar,
|
||||
.batbar { background-color: $bg1; }
|
||||
|
||||
.iconmem { color: $peach; }
|
||||
.iconcpu { color: $blue; }
|
||||
|
||||
.icon-text {
|
||||
font-size: 3rem;
|
||||
padding: .7rem;
|
||||
}
|
||||
|
||||
/* system box cpu & memory info */
|
||||
.sys-text-sub {
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.sys-text-mem,
|
||||
.sys-text-cpu {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sys-icon-mem,
|
||||
.sys-icon-cpu {
|
||||
font-size: 1.5rem;
|
||||
margin: 1.5rem;
|
||||
}
|
||||
|
||||
.system-info-box {
|
||||
@include rounding;
|
||||
background-color: $bg1;
|
||||
margin: .5rem 1rem;
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
.sys-mem,
|
||||
.sys-cpu {
|
||||
background-color: $bg;
|
||||
}
|
||||
|
||||
.sys-icon-mem,
|
||||
.sys-text-mem,
|
||||
.sys-mem {
|
||||
color: $peach;
|
||||
}
|
||||
|
||||
.sys-icon-cpu,
|
||||
.sys-text-cpu,
|
||||
.sys-cpu {
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
.sys-box {
|
||||
margin: .3em;
|
||||
|
||||
box { margin-left: 1rem; }
|
||||
}
|
6
pkgs/eww-hyprland/css/_volume.scss
Normal file
6
pkgs/eww-hyprland/css/_volume.scss
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* bar volume module */
|
||||
.vol-icon { color: $green; }
|
||||
.volbar highlight {
|
||||
background-image: linear-gradient(to right, $teal, $sky);
|
||||
border-radius: 10px;
|
||||
}
|
127
pkgs/eww-hyprland/default.nix
Normal file
127
pkgs/eww-hyprland/default.nix
Normal file
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.programs.eww-hyprland;
|
||||
|
||||
dependencies = with pkgs; [
|
||||
cfg.package
|
||||
|
||||
config.wayland.windowManager.hyprland.package
|
||||
|
||||
bash
|
||||
blueberry
|
||||
bluez
|
||||
brillo
|
||||
coreutils
|
||||
dbus
|
||||
findutils
|
||||
gawk
|
||||
gnome.gnome-control-center
|
||||
gnused
|
||||
imagemagick
|
||||
jaq
|
||||
jc
|
||||
libnotify
|
||||
material-symbols
|
||||
networkmanager
|
||||
pavucontrol
|
||||
playerctl
|
||||
procps
|
||||
pulseaudio
|
||||
ripgrep
|
||||
socat
|
||||
udev
|
||||
upower
|
||||
util-linux
|
||||
wget
|
||||
wireplumber
|
||||
wlogout
|
||||
];
|
||||
|
||||
reload_script = pkgs.writeShellScript "reload_eww" ''
|
||||
windows=$(eww windows | rg '\*' | tr -d '*')
|
||||
|
||||
systemctl --user restart eww.service
|
||||
|
||||
echo $windows | while read -r w; do
|
||||
eww open $w
|
||||
done
|
||||
'';
|
||||
in {
|
||||
options.programs.eww-hyprland = {
|
||||
enable = lib.mkEnableOption "eww Hyprland config";
|
||||
|
||||
package = lib.mkOption {
|
||||
type = with lib.types; nullOr package;
|
||||
default = pkgs.eww-wayland;
|
||||
defaultText = lib.literalExpression "pkgs.eww-wayland";
|
||||
description = "Eww package to use.";
|
||||
};
|
||||
|
||||
autoReload = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
defaultText = lib.literalExpression "false";
|
||||
description = "Whether to restart the eww daemon and windows on change.";
|
||||
};
|
||||
|
||||
colors = lib.mkOption {
|
||||
type = with lib.types; nullOr lines;
|
||||
default = null;
|
||||
defaultText = lib.literalExpression "null";
|
||||
description = ''
|
||||
SCSS file with colors defined in the same way as Catppuccin colors are,
|
||||
to be used by eww.
|
||||
|
||||
Defaults to Catppuccin Mocha.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages = [cfg.package];
|
||||
|
||||
# remove nix files
|
||||
xdg.configFile."eww" = {
|
||||
source = lib.cleanSourceWith {
|
||||
filter = name: _type: let
|
||||
baseName = baseNameOf (toString name);
|
||||
in
|
||||
!(lib.hasSuffix ".nix" baseName) && (baseName != "_colors.scss");
|
||||
src = lib.cleanSource ./.;
|
||||
};
|
||||
|
||||
# links each file individually, which lets us insert the colors file separately
|
||||
recursive = true;
|
||||
|
||||
onChange =
|
||||
if cfg.autoReload
|
||||
then reload_script.outPath
|
||||
else "";
|
||||
};
|
||||
|
||||
# colors file
|
||||
xdg.configFile."eww/css/_colors.scss".text =
|
||||
if cfg.colors != null
|
||||
then cfg.colors
|
||||
else (builtins.readFile ./css/_colors.scss);
|
||||
|
||||
systemd.user.services.eww = {
|
||||
Unit = {
|
||||
Description = "Eww Daemon";
|
||||
# not yet implemented
|
||||
# PartOf = ["tray.target"];
|
||||
PartOf = ["graphical-session.target"];
|
||||
};
|
||||
Service = {
|
||||
Environment = "PATH=/run/wrappers/bin:${lib.makeBinPath dependencies}";
|
||||
ExecStart = "${cfg.package}/bin/eww daemon --no-daemonize";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
Install.WantedBy = ["graphical-session.target"];
|
||||
};
|
||||
};
|
||||
}
|
106
pkgs/eww-hyprland/eww.scss
Normal file
106
pkgs/eww-hyprland/eww.scss
Normal file
|
@ -0,0 +1,106 @@
|
|||
@import 'css/colors';
|
||||
|
||||
@mixin rounding {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
@mixin window {
|
||||
background-color: $bg;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
border: 1px solid rgba(0,0,0,0.3);
|
||||
color: $fg;
|
||||
margin: 5px 5px 10px;
|
||||
@include rounding;
|
||||
}
|
||||
|
||||
* {
|
||||
all: unset;
|
||||
font-family: "Product Sans", Roboto, sans-serif;
|
||||
transition: 200ms ease;
|
||||
}
|
||||
|
||||
@import 'css/calendar';
|
||||
@import 'css/indicators';
|
||||
@import 'css/music';
|
||||
@import 'css/osd';
|
||||
@import 'css/sidebar';
|
||||
@import 'css/system';
|
||||
@import 'css/volume';
|
||||
|
||||
.bar0,
|
||||
.bar1,
|
||||
.bar2 {
|
||||
background-color: $bg;
|
||||
color: $fg;
|
||||
|
||||
label {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-top: .2rem;
|
||||
}
|
||||
}
|
||||
|
||||
tooltip {
|
||||
background: $bg;
|
||||
border: 1px solid $border;
|
||||
border-radius: 8px;
|
||||
|
||||
label {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* icon font */
|
||||
.icon,
|
||||
.icon label { font-family: Material Symbols Outlined; }
|
||||
|
||||
.module { margin: 0 5px; }
|
||||
|
||||
/* date & time */
|
||||
.hour {
|
||||
font-weight: bold;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.minute {
|
||||
padding-right: .7rem;
|
||||
}
|
||||
|
||||
.date {
|
||||
color: $flamingo;
|
||||
|
||||
label {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* right-aligned modules */
|
||||
.bright-icon { color: $yellow; }
|
||||
.module-bt { font-size: 1.2rem; }
|
||||
|
||||
/* scales */
|
||||
scale trough {
|
||||
background-color: $bg1;
|
||||
border-radius: 24px;
|
||||
margin: 0 1rem;
|
||||
min-height: 10px;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
/* workspaces */
|
||||
.focused {
|
||||
background-color: $bg;
|
||||
border-radius: 1rem;
|
||||
margin: .3rem;
|
||||
padding: .25rem;
|
||||
}
|
||||
|
||||
.workspaces { margin-left: 10px; }
|
||||
|
||||
.ws {
|
||||
border-radius: 2rem;
|
||||
margin: .7rem .25rem;
|
||||
}
|
83
pkgs/eww-hyprland/eww.yuck
Normal file
83
pkgs/eww-hyprland/eww.yuck
Normal file
|
@ -0,0 +1,83 @@
|
|||
; all variables and listeners
|
||||
(include "./variables.yuck")
|
||||
|
||||
; various bar modules
|
||||
(include "./modules/bluetooth.yuck")
|
||||
(include "./modules/bright.yuck")
|
||||
(include "./modules/clock.yuck")
|
||||
(include "./modules/indicators.yuck")
|
||||
(include "./modules/music.yuck")
|
||||
(include "./modules/net.yuck")
|
||||
(include "./modules/sys.yuck")
|
||||
(include "./modules/volume.yuck")
|
||||
(include "./modules/workspaces.yuck")
|
||||
|
||||
; individual windows; bar is in this file
|
||||
(include "./windows/calendar.yuck")
|
||||
(include "./windows/music.yuck")
|
||||
(include "./windows/osd.yuck") ; on-screen-display (volume/brightness)
|
||||
(include "./windows/system-menu.yuck")
|
||||
|
||||
; bar modules alignment
|
||||
(defwidget left []
|
||||
(box
|
||||
:space-evenly false
|
||||
:halign "start"
|
||||
(workspaces)))
|
||||
|
||||
(defwidget center []
|
||||
(box
|
||||
:space-evenly false
|
||||
:halign "center"
|
||||
(music-module)))
|
||||
|
||||
(defwidget right []
|
||||
(box
|
||||
:space-evenly false
|
||||
:halign "end"
|
||||
(indicators)
|
||||
(bright)
|
||||
(volume-module)
|
||||
(bluetooth)
|
||||
(net)
|
||||
(sys)
|
||||
(clock_module)))
|
||||
|
||||
(defwidget bar-box []
|
||||
(centerbox
|
||||
(left)
|
||||
(center)
|
||||
(right)))
|
||||
|
||||
(defwindow bar0
|
||||
:monitor 0
|
||||
:geometry (geometry :x "0%"
|
||||
:y "0%"
|
||||
:width "100%"
|
||||
:height "32px"
|
||||
:anchor "top center")
|
||||
:stacking "fg"
|
||||
:exclusive true
|
||||
(bar-box))
|
||||
|
||||
(defwindow bar1
|
||||
:monitor 1
|
||||
:geometry (geometry :x "0%"
|
||||
:y "0%"
|
||||
:width "100%"
|
||||
:height "32px"
|
||||
:anchor "top center")
|
||||
:stacking "fg"
|
||||
:exclusive true
|
||||
(bar-box))
|
||||
|
||||
(defwindow bar2
|
||||
:monitor 2
|
||||
:geometry (geometry :x "0%"
|
||||
:y "0%"
|
||||
:width "100%"
|
||||
:height "32px"
|
||||
:anchor "top center")
|
||||
:stacking "fg"
|
||||
:exclusive true
|
||||
(bar-box))
|
8
pkgs/eww-hyprland/modules/bluetooth.yuck
Normal file
8
pkgs/eww-hyprland/modules/bluetooth.yuck
Normal file
|
@ -0,0 +1,8 @@
|
|||
(defwidget bluetooth []
|
||||
(button
|
||||
:class "module-bt module icon"
|
||||
:onclick "blueberry" ; clicking opens blueberry
|
||||
:onrightclick "scripts/bluetooth toggle" ; rightclick to turn bluetooth on/off
|
||||
:tooltip "${bluetooth.text} ${bluetooth.battery}"
|
||||
:style "color: ${bluetooth.color};"
|
||||
{bluetooth.icon}))
|
10
pkgs/eww-hyprland/modules/bright.yuck
Normal file
10
pkgs/eww-hyprland/modules/bright.yuck
Normal file
|
@ -0,0 +1,10 @@
|
|||
(defwidget bright []
|
||||
(box
|
||||
:class "module"
|
||||
(eventbox
|
||||
; scroll to change the brightness level
|
||||
:onscroll "echo {} | sed -e 's/up/-U 1/g' -e 's/down/-A 1/g' | xargs brillo -S"
|
||||
(label
|
||||
:text {brightness.icon}
|
||||
:class "bright-icon icon"
|
||||
:tooltip "brightness ${round(brightness.percent, 0)}%"))))
|
30
pkgs/eww-hyprland/modules/clock.yuck
Normal file
30
pkgs/eww-hyprland/modules/clock.yuck
Normal file
|
@ -0,0 +1,30 @@
|
|||
(defvar date_rev false)
|
||||
|
||||
(defwidget clock_module []
|
||||
(eventbox
|
||||
:onhover "${EWW_CMD} update date_rev=true"
|
||||
:onhoverlost "${EWW_CMD} update date_rev=false"
|
||||
(overlay
|
||||
:class "module"
|
||||
; the styles make the clock invisible while hovered, and the date is shown instead
|
||||
(box
|
||||
:space-evenly false
|
||||
:class "text"
|
||||
(label
|
||||
:text {formattime(EWW_TIME, "%H")}
|
||||
:style {date_rev ? "color: rgba(0,0,0,0); text-shadow: none;" : ""}
|
||||
:class "hour")
|
||||
(label
|
||||
:style {date_rev ? "color: rgba(0,0,0,0); text-shadow: none;" : ""}
|
||||
:text ":")
|
||||
(label
|
||||
:text {formattime(EWW_TIME, "%M")}
|
||||
:style {date_rev ? "color: rgba(0,0,0,0); text-shadow: none;" : ""}
|
||||
:class "minute"))
|
||||
(revealer
|
||||
:reveal date_rev
|
||||
:transition "crossfade"
|
||||
(button
|
||||
:class "date text"
|
||||
:onclick "${EWW_CMD} open --toggle calendar"
|
||||
{formattime(EWW_TIME, "%d/%m")})))))
|
10
pkgs/eww-hyprland/modules/indicators.yuck
Normal file
10
pkgs/eww-hyprland/modules/indicators.yuck
Normal file
|
@ -0,0 +1,10 @@
|
|||
; screenshare & mic share indicators
|
||||
(defwidget indicators []
|
||||
(box
|
||||
:space-evenly: false
|
||||
:class "indicators"
|
||||
(for i in indicators
|
||||
(label
|
||||
:class "icon indicator ${i.class}"
|
||||
:tooltip "${i.name} is being shared"
|
||||
:text {i.icon}))))
|
24
pkgs/eww-hyprland/modules/music.yuck
Normal file
24
pkgs/eww-hyprland/modules/music.yuck
Normal file
|
@ -0,0 +1,24 @@
|
|||
(defwidget music-module []
|
||||
(eventbox
|
||||
:onhover "${EWW_CMD} update music_reveal=true"
|
||||
:onhoverlost "${EWW_CMD} update music_reveal=false"
|
||||
(box
|
||||
:class "module"
|
||||
:space-evenly false
|
||||
(box
|
||||
:class "song-cover-art"
|
||||
:style "background-image: url(\"${music.cover}\");")
|
||||
(button
|
||||
:class "module text"
|
||||
:onclick "${EWW_CMD} open --toggle music"
|
||||
{music.title})
|
||||
; show buttons when hovering
|
||||
(revealer
|
||||
:transition "slideright"
|
||||
:reveal music_reveal
|
||||
:duration "350ms"
|
||||
(box
|
||||
:class "icon text"
|
||||
(button :class "song-button" :onclick "playerctl previous" "")
|
||||
(button :class "song-button" :onclick "playerctl play-pause" {music.status})
|
||||
(button :class "song-button" :onclick "playerctl next" ""))))))
|
8
pkgs/eww-hyprland/modules/net.yuck
Normal file
8
pkgs/eww-hyprland/modules/net.yuck
Normal file
|
@ -0,0 +1,8 @@
|
|||
(defwidget net []
|
||||
(button
|
||||
:class "module icon"
|
||||
; forcefully open gnome-control-center in a non-GNOME environment
|
||||
:onclick "XDG_CURRENT_DESKTOP=GNOME gnome-control-center &"
|
||||
:tooltip {net.name}
|
||||
:style "color: ${net.color};"
|
||||
{net.icon}))
|
31
pkgs/eww-hyprland/modules/sys.yuck
Normal file
31
pkgs/eww-hyprland/modules/sys.yuck
Normal file
|
@ -0,0 +1,31 @@
|
|||
(defwidget sys []
|
||||
(box
|
||||
:class "module"
|
||||
:space-evenly false
|
||||
:spacing 5
|
||||
(circular-progress
|
||||
:value {EWW_CPU.avg}
|
||||
:class "cpubar"
|
||||
:thickness 3
|
||||
(button
|
||||
:tooltip "using ${round(EWW_CPU.avg,0)}% cpu"
|
||||
:onclick "${EWW_CMD} open --toggle system-menu"
|
||||
(label :class "icon-text" :text "")))
|
||||
|
||||
(circular-progress
|
||||
:value {EWW_RAM.used_mem_perc}
|
||||
:class "membar"
|
||||
:thickness 3
|
||||
(button
|
||||
:tooltip "using ${round(EWW_RAM.used_mem_perc,0)}% ram"
|
||||
:onclick "${EWW_CMD} open --toggle system-menu"
|
||||
(label :class "icon-text" :text "")))
|
||||
|
||||
(circular-progress
|
||||
:value {EWW_BATTERY.total_avg}
|
||||
:class "batbar ${EWW_BATTERY.total_avg > 20 ? '' : 'low'}"
|
||||
:thickness 3
|
||||
(button
|
||||
:tooltip "battery on ${round(EWW_BATTERY.total_avg,0)}%"
|
||||
:onclick "${EWW_CMD} open --toggle system-menu"
|
||||
(label :class "icon-text" :text "")))))
|
13
pkgs/eww-hyprland/modules/volume.yuck
Normal file
13
pkgs/eww-hyprland/modules/volume.yuck
Normal file
|
@ -0,0 +1,13 @@
|
|||
(defwidget volume-module []
|
||||
(box
|
||||
:class "module icon"
|
||||
(eventbox
|
||||
; scroll over the icon to change volume
|
||||
; low increment so that scrolling with a touchpad doesn't shatter your eardrums
|
||||
:onscroll "echo {} | sed -e 's/up/-/g' -e 's/down/+/g' | xargs -I% wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.005%"
|
||||
:onclick "pavucontrol &" ; open pavucontrol on click
|
||||
:onrightclick "scripts/volume mute SINK" ; toggle mute on right click
|
||||
(label
|
||||
:class "vol-icon"
|
||||
:tooltip "volume ${volume.percent}%"
|
||||
:text {volume.icon}))))
|
15
pkgs/eww-hyprland/modules/workspaces.yuck
Normal file
15
pkgs/eww-hyprland/modules/workspaces.yuck
Normal file
|
@ -0,0 +1,15 @@
|
|||
(defwidget workspaces []
|
||||
(eventbox
|
||||
; scroll to change workspace
|
||||
:onscroll "echo {} | sed -e \"s/up/-1/g\" -e \"s/down/+1/g\" | xargs hyprctl dispatch workspace"
|
||||
(box
|
||||
:class "module workspaces"
|
||||
(for ws in {hyprland.workspaces}
|
||||
(button
|
||||
:onclick "hyprctl dispatch workspace ${ws.number}"
|
||||
:class "ws icon"
|
||||
:style "background-color: ${ws.color};"
|
||||
; :tooltip {ws.tooltip}
|
||||
(box
|
||||
:class `${ws.focused ? "focused" : ""}`
|
||||
:height 3))))))
|
40
pkgs/eww-hyprland/scripts/airplane
Executable file
40
pkgs/eww-hyprland/scripts/airplane
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$(dirname "$0")"/utils
|
||||
|
||||
STATUS="$(rfkill list | sed -n 2p | awk '{print $3}')"
|
||||
|
||||
icon() {
|
||||
[ "$STATUS" = "no" ] && echo "" || echo ""
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if [ "$STATUS" = "no" ]; then
|
||||
rfkill block all
|
||||
notify-send --urgency=normal -i airplane-mode-symbolic "Airplane Mode" "Airplane mode has been turned on!"
|
||||
else
|
||||
rfkill unblock all
|
||||
notify-send --urgency=normal -i airplane-mode-disabled-symbolic "Airplane Mode" "Airplane mode has been turned off!"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$1" = "toggle" ]; then
|
||||
toggle
|
||||
else
|
||||
last_time=$(get_time_ms)
|
||||
STATUS="$(rfkill list | sed -n 2p | awk '{print $3}')"
|
||||
icon
|
||||
|
||||
rfkill event | while read -r _; do
|
||||
current_time=$(get_time_ms)
|
||||
delta=$((current_time - last_time))
|
||||
# 50ms debounce
|
||||
if [[ $delta -gt 50 ]]; then
|
||||
STATUS="$(rfkill list | sed -n 2p | awk '{print $3}')"
|
||||
icon
|
||||
# reset debounce timer
|
||||
last_time=$(get_time_ms)
|
||||
fi
|
||||
done
|
||||
fi
|
66
pkgs/eww-hyprland/scripts/bluetooth
Executable file
66
pkgs/eww-hyprland/scripts/bluetooth
Executable file
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$(dirname "$0")"/utils
|
||||
|
||||
toggle() {
|
||||
status=$(rfkill -J | jaq -r '.rfkilldevices[] | select(.type == "bluetooth") | .soft' | head -1)
|
||||
|
||||
if [ "$status" = "unblocked" ]; then
|
||||
rfkill block bluetooth
|
||||
else
|
||||
rfkill unblock bluetooth
|
||||
fi
|
||||
}
|
||||
|
||||
gen_output() {
|
||||
powered=$(bluetoothctl show | rg Powered | cut -f 2- -d ' ')
|
||||
status=$(bluetoothctl info)
|
||||
name=$(echo "$status" | rg Name | cut -f 2- -d ' ')
|
||||
mac=$(echo "$status" | head -1 | awk '{print $2}' | tr ':' '_')
|
||||
|
||||
if [[ "$(echo "$status" | rg Percentage)" != "" ]]; then
|
||||
battery="$(upower -i /org/freedesktop/UPower/devices/headset_dev_"$mac" | rg percentage | awk '{print $2}' | cut -f 1 -d '%')%"
|
||||
else
|
||||
battery=""
|
||||
fi
|
||||
|
||||
if [ "$powered" = "yes" ]; then
|
||||
if [ "$status" != "Missing device address argument" ]; then
|
||||
icon=""
|
||||
text="$name"
|
||||
color="#89b4fa"
|
||||
class="bt-connected"
|
||||
else
|
||||
icon=""
|
||||
text="Disconnected"
|
||||
color="#45475a"
|
||||
class=""
|
||||
fi
|
||||
else
|
||||
icon=""
|
||||
text="Bluetooth off"
|
||||
color="#45475a"
|
||||
class=""
|
||||
fi
|
||||
|
||||
echo '{ "icon": "'"$icon"'", "battery": "'"$battery"'", "text": "'"$text"'", "color": "'"$color"'", "class": "'"$class"'" }'
|
||||
}
|
||||
|
||||
if [ "$1" = "toggle" ]; then
|
||||
toggle
|
||||
else
|
||||
gen_output
|
||||
last_time=$(get_time_ms)
|
||||
|
||||
udevadm monitor | while read -r _; do
|
||||
current_time=$(get_time_ms)
|
||||
delta=$((current_time - last_time))
|
||||
# 50ms debounce
|
||||
if [[ $delta -gt 50 ]]; then
|
||||
gen_output
|
||||
# reset debounce timer
|
||||
last_time=$(get_time_ms)
|
||||
fi
|
||||
done
|
||||
fi
|
33
pkgs/eww-hyprland/scripts/brightness
Executable file
33
pkgs/eww-hyprland/scripts/brightness
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$(dirname "$0")"/utils
|
||||
|
||||
icons=("" "" "")
|
||||
date="$XDG_CACHE_HOME/eww/osd_brightness.date"
|
||||
|
||||
gen_output() {
|
||||
percent="$(brillo)"
|
||||
icon="${icons[$(awk -v n="$percent" 'BEGIN{print int(n/34)}')]}"
|
||||
|
||||
echo '{"percent": "'"$percent"'", "icon": "'"$icon"'"}'
|
||||
}
|
||||
|
||||
if [ "$1" = "osd" ]; then
|
||||
osd "$date"
|
||||
else
|
||||
# initial
|
||||
last_time=$(get_time_ms)
|
||||
gen_output
|
||||
osd_handler "osd-brightness" &
|
||||
|
||||
udevadm monitor | rg --line-buffered "backlight" | while read -r _; do
|
||||
current_time=$(get_time_ms)
|
||||
delta=$((current_time - last_time))
|
||||
if [[ $delta -gt 50 ]]; then
|
||||
gen_output
|
||||
# reset debounce timer
|
||||
last_time=$(get_time_ms)
|
||||
fi
|
||||
done
|
||||
fi
|
94
pkgs/eww-hyprland/scripts/hyprland
Executable file
94
pkgs/eww-hyprland/scripts/hyprland
Executable file
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# define colors
|
||||
# red peach green blue
|
||||
colors=("#f38ba8" "#fab387" "#a6e3a1" "#89b4fa")
|
||||
empty="rgba(30, 30, 46, 0.6)"
|
||||
|
||||
# get initial focused workspace
|
||||
focusedws=$(hyprctl -j monitors | jaq -r '.[] | select(.focused == true) | .activeWorkspace.id')
|
||||
|
||||
declare -A o=([1]=0 [2]=0 [3]=0 [4]=0 [5]=0 [6]=0 [7]=0 [8]=0 [9]=0 [10]=0)
|
||||
declare -A monitormap
|
||||
declare -A workspaces
|
||||
|
||||
# set color for each workspace
|
||||
status() {
|
||||
if [ "${o[$1]}" -eq 1 ]; then
|
||||
mon=${monitormap[${workspaces[$1]}]}
|
||||
echo -n "${colors[$mon]}"
|
||||
else
|
||||
echo -n "$empty"
|
||||
fi
|
||||
}
|
||||
|
||||
# handle workspace create/destroy
|
||||
workspace_event() {
|
||||
while read -r k v; do workspaces[$k]="$v"; done < <(hyprctl -j workspaces | jaq -jr '.[] | .id, " ", .monitor, "\n"')
|
||||
}
|
||||
# handle monitor (dis)connects
|
||||
monitor_event() {
|
||||
while read -r k v; do monitormap["$k"]=$v; done < <(hyprctl -j monitors | jaq -jr '.[] | .name, " ", .id, "\n"')
|
||||
}
|
||||
|
||||
# get all apps titles in a workspace
|
||||
applist() {
|
||||
ws="$1"
|
||||
|
||||
apps=$(hyprctl -j clients | jaq -jr '.[] | select(.workspace.id == '"$ws"') | .title + "\\n"')
|
||||
echo -En "${apps%"\n"}"
|
||||
}
|
||||
|
||||
# generate the json for eww
|
||||
generate() {
|
||||
echo -n '{"workspaces": ['
|
||||
|
||||
for i in {1..10}; do
|
||||
echo -n ''"$([ "$i" -eq 1 ] || echo ,)" '{"number": '"$i"', "color": "'"$(status "$i")"'", "focused": '"$([ "$focusedws" = "$i" ] && echo "true" || echo "false")"'}' #, "tooltip": "'$(applist "$i")'" }'
|
||||
done
|
||||
|
||||
echo '], "screencast": '"$screencast"'}'
|
||||
}
|
||||
|
||||
# setup
|
||||
|
||||
# add monitors
|
||||
monitor_event
|
||||
|
||||
# add workspaces
|
||||
workspace_event
|
||||
|
||||
# screen is not shared by default
|
||||
screencast=false
|
||||
|
||||
# check occupied workspaces
|
||||
for num in "${!workspaces[@]}"; do
|
||||
o[$num]=1
|
||||
done
|
||||
# generate initial widget
|
||||
generate
|
||||
|
||||
# main loop
|
||||
socat -u UNIX-CONNECT:/tmp/hypr/"$HYPRLAND_INSTANCE_SIGNATURE"/.socket2.sock - | rg --line-buffered "workspace|mon(itor)?|screencast" | while read -r line; do
|
||||
case ${line%>>*} in
|
||||
"workspace")
|
||||
focusedws=${line#*>>}
|
||||
;;
|
||||
"focusedmon")
|
||||
focusedws=${line#*,}
|
||||
;;
|
||||
"createworkspace")
|
||||
o[${line#*>>}]=1
|
||||
;;
|
||||
"destroyworkspace")
|
||||
o[${line#*>>}]=0
|
||||
;;
|
||||
"monitor"*)
|
||||
monitor_event
|
||||
;;
|
||||
"screencast")
|
||||
screencast=$([ "$(echo "${line#*>>}" | awk -F, '{print $1}')" -eq 1 ] && echo true || echo false)
|
||||
;;
|
||||
esac
|
||||
generate
|
||||
done
|
41
pkgs/eww-hyprland/scripts/indicators
Executable file
41
pkgs/eww-hyprland/scripts/indicators
Executable file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
prevMic=""
|
||||
prevScreen=""
|
||||
|
||||
gen_output() {
|
||||
mic=$(eww get volume)
|
||||
# no standard way of getting camera info
|
||||
# camerareveal=$(eww get camerareveal)
|
||||
screen=$(eww get hyprland)
|
||||
|
||||
if [ "$screen" != "$prevScreen" ] || [ "$mic" != "$prevMic" ]; then
|
||||
micreveal=$(echo "$mic" | jaq -r '.in_use')
|
||||
screenreveal=$(echo "$screen" | jaq -r '.screencast')
|
||||
|
||||
json='['
|
||||
|
||||
if [ "$micreveal" -ge 1 ]; then
|
||||
json+='{"name": "Microphone", "icon": "", "class": "micshare"}'
|
||||
fi
|
||||
if [ "$screenreveal" = "true" ]; then
|
||||
json+="$([ "$json" == "[" ] || echo ',')"'{"name": "Screen", "icon": "", "class": "screenshare"}'
|
||||
fi
|
||||
# if [ "$camerareveal" = "true" ]; then
|
||||
# json+='{"name": "Camera", "icon": "", "class": "camerashare"}'
|
||||
# fi
|
||||
|
||||
json+=']'
|
||||
|
||||
echo "$json"
|
||||
prevMic="$mic"
|
||||
prevScreen="$screen"
|
||||
fi
|
||||
}
|
||||
|
||||
gen_output
|
||||
sleep 1
|
||||
while true; do
|
||||
gen_output
|
||||
sleep 1
|
||||
done
|
86
pkgs/eww-hyprland/scripts/net
Executable file
86
pkgs/eww-hyprland/scripts/net
Executable file
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Script to listen for networkmanager updates and return an appriopriate icon and tooltip.
|
||||
# This script runs until it's manually terminated.
|
||||
|
||||
# Requires: NetworkManager, gawk
|
||||
# Usage: networkmanager
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$(dirname "$0")"/utils
|
||||
|
||||
# get initialize network device info and states
|
||||
nm="$(nmcli d | jc --nmcli | jaq -r '.[] | select(.type | test("^(wifi|ethernet)$", "ix"))')"
|
||||
icons=("" "" "" "" "")
|
||||
|
||||
function toggle() {
|
||||
status=$(rfkill -J | jaq -r '.rfkilldevices[] | select(.type == "wlan") | .soft' | head -1)
|
||||
|
||||
if [ "$status" = "unblocked" ]; then
|
||||
rfkill block wlan
|
||||
else
|
||||
rfkill unblock wlan
|
||||
fi
|
||||
}
|
||||
|
||||
function gen_wifi() {
|
||||
signal=$(nmcli -t -f in-use,ssid,signal dev wifi | rg '\*' | sed 's/\"/\\"/g' | awk -F: '{print $3}')
|
||||
level=$(awk -v n="$signal" 'BEGIN{print int((n-1)/20)}')
|
||||
if [ "$level" -gt 4 ]; then
|
||||
level=4
|
||||
fi
|
||||
|
||||
icon=${icons[$level]}
|
||||
color="#cba6f7"
|
||||
class="net-connected"
|
||||
name=$(echo "$nm" | jaq -r 'select(.type == "wifi") .connection')
|
||||
}
|
||||
|
||||
function gen_ethernet() {
|
||||
icon=""
|
||||
class="net-connected"
|
||||
color="#cba6f7"
|
||||
name=$(echo "$nm" | jaq -r 'select(.type == "ethernet") .connection')
|
||||
}
|
||||
|
||||
function make_content() {
|
||||
local ethernet wifi
|
||||
ethernet=$(echo "$nm" | jaq -r 'select(.type == "ethernet") .state')
|
||||
wifi=$(echo "$nm" | jaq -r 'select(.type == "wifi") .state')
|
||||
|
||||
# test ethernet first
|
||||
if [[ $ethernet == "connected" ]]; then
|
||||
gen_ethernet
|
||||
elif [[ $wifi == "connected" ]]; then
|
||||
gen_wifi
|
||||
else
|
||||
icon=""
|
||||
color="#988ba2"
|
||||
class="net-disconnected"
|
||||
name="Disconnected"
|
||||
fi
|
||||
|
||||
jaq --null-input -r -c \
|
||||
--arg icon "$icon" \
|
||||
--arg name "$name" \
|
||||
--arg color "$color" \
|
||||
--arg class "$class" \
|
||||
'{"icon": $icon, "name": $name, "color": $color, "class": $class}'
|
||||
}
|
||||
|
||||
# first run
|
||||
make_content
|
||||
last_time=$(get_time_ms)
|
||||
|
||||
nmcli monitor | while read -r _; do
|
||||
current_time=$(get_time_ms)
|
||||
delta=$((current_time - last_time))
|
||||
# 50ms debounce
|
||||
if [[ $delta -gt 50 ]]; then
|
||||
sleep 0.5
|
||||
nm="$(nmcli d | jc --nmcli | jaq -r '.[] | select(.type | test("^(wifi|ethernet)$", "ix"))')"
|
||||
make_content
|
||||
# reset debounce timer
|
||||
last_time=$(get_time_ms)
|
||||
fi
|
||||
done
|
52
pkgs/eww-hyprland/scripts/utils
Normal file
52
pkgs/eww-hyprland/scripts/utils
Normal file
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ ! "$XDG_CACHE_HOME" ]; then
|
||||
XDG_CACHE_HOME="/home/mihai/.local/cache"
|
||||
fi
|
||||
|
||||
function get_time_ms {
|
||||
date -u +%s%3N
|
||||
}
|
||||
|
||||
function osd {
|
||||
date="$1"
|
||||
if [ ! -f "$date" ]; then
|
||||
mkdir -p "$XDG_CACHE_HOME/eww"
|
||||
fi
|
||||
date +%s >"$date"
|
||||
}
|
||||
|
||||
function osd_handler {
|
||||
lock=0
|
||||
rundate=0
|
||||
OBJ="$1"
|
||||
|
||||
if [ ! -f "$date" ]; then
|
||||
mkdir -p "$XDG_CACHE_HOME/eww"
|
||||
echo 0 >"$date"
|
||||
fi
|
||||
|
||||
while true; do
|
||||
# get dates
|
||||
rundate=$(cat "$date")
|
||||
currentdate=$(date +%s)
|
||||
|
||||
# handle showing
|
||||
if [ "$rundate" = "$currentdate" ] && [ "$lock" -eq 0 ]; then
|
||||
eww open osd >/dev/null 2>&1
|
||||
eww update "$OBJ"=true >/dev/null 2>&1
|
||||
lock=1
|
||||
elif [ "$((currentdate - rundate))" = "2" ] && [ "$lock" -eq 1 ]; then
|
||||
eww update "$OBJ"=false >/dev/null 2>&1
|
||||
lock=0
|
||||
if [ "$(eww get osd-volume)" = "false" ] && [ "$(eww get osd-brightness)" = "false" ]; then
|
||||
sleep 1
|
||||
eww close osd >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
eww close osd >/dev/null 2>&1
|
||||
}
|
87
pkgs/eww-hyprland/scripts/volume
Executable file
87
pkgs/eww-hyprland/scripts/volume
Executable file
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$(dirname "$0")"/utils
|
||||
|
||||
volicons=("" "" "")
|
||||
date="$XDG_CACHE_HOME/eww/osd_vol.date"
|
||||
|
||||
vol() {
|
||||
wpctl get-volume @DEFAULT_AUDIO_"$1"@ | awk '{print int($2*100)}'
|
||||
}
|
||||
ismuted() {
|
||||
wpctl get-volume @DEFAULT_AUDIO_"$1"@ | rg -qi muted
|
||||
echo -n $?
|
||||
}
|
||||
setvol() {
|
||||
wpctl set-volume @DEFAULT_AUDIO_"$1"@ "$(awk -v n="$2" 'BEGIN{print (n / 100)}')"
|
||||
}
|
||||
setmute() {
|
||||
wpctl set-mute @DEFAULT_AUDIO_"$1"@ toggle
|
||||
}
|
||||
|
||||
gen_output() {
|
||||
percent="$(vol "SINK")"
|
||||
if [[ "$event" == *source* ]]; then
|
||||
pactl list sources | rg -q RUNNING
|
||||
[ $? -eq 1 ] && in_use=0 || in_use=1
|
||||
else
|
||||
lvl=$(awk -v n="$percent" 'BEGIN{print int(n/34)}')
|
||||
ismuted=$(ismuted "SINK")
|
||||
|
||||
if [ "$ismuted" = 1 ]; then
|
||||
icon="${volicons[$lvl]}"
|
||||
else
|
||||
icon=""
|
||||
fi
|
||||
fi
|
||||
|
||||
echo '{"icon": "'"$icon"'", "percent": "'"$percent"'", "microphone": "'"$(vol "SOURCE")"'", "in_use": "'"$in_use"'"}'
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
"mute")
|
||||
if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then
|
||||
echo "Can only mute SINK or SOURCE"
|
||||
exit 1
|
||||
fi
|
||||
setmute "$2"
|
||||
;;
|
||||
|
||||
"setvol")
|
||||
if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then
|
||||
echo "Can only set volume for SINK or SOURCE"
|
||||
exit 1
|
||||
elif [ "$3" -lt 0 ] || [ "$3" -gt 100 ]; then
|
||||
echo "Volume must be between 0 and 100"
|
||||
exit 1
|
||||
fi
|
||||
setvol "$2" "$3"
|
||||
;;
|
||||
|
||||
"osd")
|
||||
osd "$date"
|
||||
;;
|
||||
|
||||
"")
|
||||
# initial values
|
||||
in_use=0
|
||||
last_time=$(get_time_ms)
|
||||
gen_output
|
||||
osd_handler "osd-volume" &
|
||||
|
||||
# event loop
|
||||
pactl subscribe | rg --line-buffered ".*(source|sink).*" | while read -r event; do
|
||||
current_time=$(get_time_ms)
|
||||
delta=$((current_time - last_time))
|
||||
# 50ms debounce
|
||||
if [[ $delta -gt 50 ]]; then
|
||||
gen_output
|
||||
# reset debounce timer
|
||||
last_time=$(get_time_ms)
|
||||
fi
|
||||
done
|
||||
;;
|
||||
|
||||
*) echo "wrong usage" ;;
|
||||
esac
|
20
pkgs/eww-hyprland/variables.yuck
Normal file
20
pkgs/eww-hyprland/variables.yuck
Normal file
|
@ -0,0 +1,20 @@
|
|||
(defvar bright_reveal false)
|
||||
(defvar bt_rev false)
|
||||
(defvar music_reveal false)
|
||||
(defvar net_rev false)
|
||||
(defvar time_rev false)
|
||||
(defvar vol_reveal false)
|
||||
(defvar osd-brightness false)
|
||||
(defvar osd-volume false)
|
||||
(defvar battery_icons `["","","","","","","",""]`)
|
||||
|
||||
(deflisten airplane "scripts/airplane")
|
||||
(deflisten battery "gross battery")
|
||||
(deflisten bluetooth "scripts/bluetooth")
|
||||
(deflisten brightness "scripts/brightness")
|
||||
(deflisten indicators "scripts/indicators")
|
||||
(deflisten music "gross music")
|
||||
(deflisten music_time "gross music-time")
|
||||
(deflisten net "scripts/net")
|
||||
(deflisten volume "scripts/volume")
|
||||
(deflisten hyprland "scripts/hyprland")
|
14
pkgs/eww-hyprland/windows/calendar.yuck
Normal file
14
pkgs/eww-hyprland/windows/calendar.yuck
Normal file
|
@ -0,0 +1,14 @@
|
|||
(defwidget calendar-win []
|
||||
(box
|
||||
:class "calendar-win text"
|
||||
(calendar)))
|
||||
|
||||
(defwindow calendar
|
||||
:monitor 0
|
||||
:geometry (geometry
|
||||
:x "0%"
|
||||
:y "0%"
|
||||
:anchor "top right"
|
||||
:width "0px"
|
||||
:height "0px")
|
||||
(calendar-win))
|
70
pkgs/eww-hyprland/windows/music.yuck
Normal file
70
pkgs/eww-hyprland/windows/music.yuck
Normal file
|
@ -0,0 +1,70 @@
|
|||
(defwidget music []
|
||||
(box
|
||||
:class "music-window"
|
||||
:space-evenly false
|
||||
; force background position/size, otherwise it is overridden
|
||||
:style "
|
||||
background-image: url('${music.background}');
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
/*border: 1px solid ${music.border};*/
|
||||
"
|
||||
(box ; cover art, first child
|
||||
:class "music-cover-art"
|
||||
:style "background-image: url('${music.cover}');")
|
||||
(box ; music info, second child
|
||||
:orientation "v"
|
||||
:space-evenly false
|
||||
:class "music-box"
|
||||
(scroll
|
||||
:hscroll true
|
||||
:vscroll false
|
||||
(label ; title
|
||||
:class "music-title text ${music.foreground}"
|
||||
:justify "center"
|
||||
:text {music.title}))
|
||||
(scroll
|
||||
:hscroll true
|
||||
:vscroll false
|
||||
(label ; artist
|
||||
:class "music-artist text ${music.foreground}"
|
||||
:justify "center"
|
||||
:text {music.artist}))
|
||||
(centerbox ; buttons
|
||||
:halign "center"
|
||||
:class "music-button-box icon text"
|
||||
(button :class "music-button ${music.foreground}" :onclick "playerctl previous" "")
|
||||
(button :class "music-button ${music.foreground}" :onclick "playerctl play-pause" {music.status})
|
||||
(button :class "music-button ${music.foreground}" :onclick "playerctl next" ""))
|
||||
(box ; time info
|
||||
:orientation "v"
|
||||
(box
|
||||
:class "text"
|
||||
(label
|
||||
:xalign 0
|
||||
:class "music-time ${music.foreground}"
|
||||
:text {music_time.position})
|
||||
(label
|
||||
:xalign 1
|
||||
:class "music-time ${music.foreground}"
|
||||
:text {music.duration}))
|
||||
(box ; clickable progress bar
|
||||
:class "music-bar"
|
||||
(scale
|
||||
; sadly we cannot access a child (highlight) from a parent using :style
|
||||
; :style "background: linear-gradient(to right, ${music.color1}, ${music.color2});"
|
||||
; transform scale position percentage into song position
|
||||
:onchange "playerctl position `awk -v len=$(playerctl metadata mpris:length) 'BEGIN{print {} * len / 1000000 / 100}'`"
|
||||
:value {music_time.position_percent}))))))
|
||||
|
||||
(defwindow music
|
||||
:stacking "fg"
|
||||
:focusable false
|
||||
:monitor 0
|
||||
:geometry (geometry
|
||||
:x "0%"
|
||||
:y "0%"
|
||||
:width "0%"
|
||||
:height "0%"
|
||||
:anchor "top center")
|
||||
(music))
|
47
pkgs/eww-hyprland/windows/osd.yuck
Normal file
47
pkgs/eww-hyprland/windows/osd.yuck
Normal file
|
@ -0,0 +1,47 @@
|
|||
; shared OSD code for volume/brightnes
|
||||
(defwidget osd-part [icon value class]
|
||||
(box
|
||||
:class "osd-part osd-${class}"
|
||||
:orientation "v"
|
||||
:space-evenly false
|
||||
(scale
|
||||
:flipped true
|
||||
:orientation "v"
|
||||
:value value)
|
||||
(label
|
||||
:class "text"
|
||||
:text icon)))
|
||||
|
||||
; osd window widget
|
||||
(defwidget osd []
|
||||
(box
|
||||
:class "osd-container"
|
||||
:space-evenly false
|
||||
; use revealers for both volume and brightness
|
||||
(revealer
|
||||
:reveal {osd-brightness}
|
||||
:transition "slideright"
|
||||
(osd-part
|
||||
:class "brightness"
|
||||
:icon {brightness.icon}
|
||||
:value {brightness.percent}))
|
||||
(revealer
|
||||
:reveal {osd-volume}
|
||||
:transition "slideright"
|
||||
(osd-part
|
||||
:class "volume"
|
||||
:icon {volume.icon}
|
||||
:value {volume.percent})))
|
||||
)
|
||||
|
||||
(defwindow osd
|
||||
:stacking "fg"
|
||||
:focusable false
|
||||
:monitor 0
|
||||
:geometry (geometry
|
||||
:x "1%"
|
||||
:y "0%"
|
||||
:width "0%"
|
||||
:height "0%"
|
||||
:anchor "center left")
|
||||
(osd))
|
218
pkgs/eww-hyprland/windows/system-menu.yuck
Normal file
218
pkgs/eww-hyprland/windows/system-menu.yuck
Normal file
|
@ -0,0 +1,218 @@
|
|||
(defvar GB 1024000000)
|
||||
(defvar MB 1024000)
|
||||
|
||||
(defwidget system-menu []
|
||||
(box ; time & date
|
||||
:class "system-menu-box"
|
||||
:space-evenly false
|
||||
:orientation "v"
|
||||
(box
|
||||
:class "top-row"
|
||||
:space-evenly false
|
||||
(label
|
||||
:class "time text"
|
||||
:text {formattime(EWW_TIME, "%H:%M")})
|
||||
(box
|
||||
:class "date-box"
|
||||
:space-evenly false
|
||||
(label
|
||||
:class "date"
|
||||
:text {formattime(EWW_TIME, "%d/%m")})
|
||||
(label
|
||||
:class "day"
|
||||
:text {formattime(EWW_TIME, "%A")})))
|
||||
|
||||
(centerbox ; wifi/bluetooth/airplane buttons
|
||||
:class "system-row"
|
||||
(box
|
||||
:class "net-box"
|
||||
:space-evenly false
|
||||
:orientation "v"
|
||||
(box
|
||||
:class "element icon ${net.class}"
|
||||
:space-evenly false
|
||||
(button
|
||||
:class "net-button"
|
||||
:onclick "scripts/net toggle"
|
||||
{net.icon})
|
||||
(label
|
||||
:class "separator"
|
||||
:text "│")
|
||||
(button
|
||||
:class "net-arrow-btn"
|
||||
:onclick "eww close system-menu && XDG_CURRENT_DESKTOP=GNOME gnome-control-center &"
|
||||
""))
|
||||
(label
|
||||
:class "text"
|
||||
:text {net.name}
|
||||
:xalign 0.5
|
||||
:justify "center"
|
||||
:wrap true))
|
||||
|
||||
(box
|
||||
:class "bluetooth-box"
|
||||
:space-evenly false
|
||||
:orientation "v"
|
||||
(box
|
||||
:class "element icon ${bluetooth.class}"
|
||||
:space-evenly false
|
||||
(button
|
||||
:class "bluetooth-button"
|
||||
:onclick "scripts/bluetooth toggle"
|
||||
{bluetooth.icon})
|
||||
(label
|
||||
:class "separator"
|
||||
:text "│")
|
||||
(button
|
||||
:class "bluetooth-arrow-btn"
|
||||
:onclick "eww close system-menu && blueberry"
|
||||
""))
|
||||
(label
|
||||
:class "text"
|
||||
:text {bluetooth.text}
|
||||
:xalign 0.5
|
||||
:justify "center"
|
||||
:tooltip {bluetooth.battery}
|
||||
:wrap true))
|
||||
|
||||
(box
|
||||
:class "airplane-box"
|
||||
:space-evenly false
|
||||
:orientation "v"
|
||||
(box
|
||||
:class "element"
|
||||
(button
|
||||
:class "airplane-button"
|
||||
:onclick "scripts/airplane toggle"
|
||||
airplane))
|
||||
(label
|
||||
:class "text"
|
||||
:text "Airplane Mode"
|
||||
:xalign 0.5
|
||||
:limit-width 16)))
|
||||
|
||||
(box ; brightness & volume sliders
|
||||
:class "sliders"
|
||||
:orientation "v"
|
||||
(box
|
||||
:class "volume-slider-box"
|
||||
:space-evenly false
|
||||
(button
|
||||
:class "volume-icon icon"
|
||||
:onclick "scripts/volume mute SINK"
|
||||
{volume.icon})
|
||||
(scale
|
||||
:class "volume-bar"
|
||||
:value {volume.percent}
|
||||
:tooltip "volume on ${volume.percent}%"
|
||||
:onchange "scripts/volume setvol SINK {}"))
|
||||
(box
|
||||
:class "brightness-slider-box"
|
||||
:space-evenly false
|
||||
(button
|
||||
:class "brightness-slider-icon icon"
|
||||
{brightness.icon})
|
||||
(scale
|
||||
:class "brightness-slider"
|
||||
:value {brightness.percent}
|
||||
:marks true
|
||||
:onchange "brillo -S {}")))
|
||||
|
||||
(box ; cpu & memory info
|
||||
:class "system-info-box"
|
||||
|
||||
; cpu
|
||||
(box
|
||||
:class "sys-box"
|
||||
:space-evenly false
|
||||
:halign "start"
|
||||
(circular-progress
|
||||
:value "${EWW_CPU.avg}"
|
||||
:class "sys-cpu"
|
||||
:thickness 3
|
||||
(label
|
||||
:text ""
|
||||
:class "sys-icon-cpu icon"))
|
||||
(box
|
||||
:class "text"
|
||||
:orientation "v"
|
||||
:vexpand false
|
||||
(label
|
||||
:text "cpu"
|
||||
:halign "start"
|
||||
:class "sys-text-cpu")
|
||||
(label
|
||||
:text "${round(EWW_CPU.avg,2)}%"
|
||||
:halign "start"
|
||||
:class "sys-text-sub")
|
||||
(label
|
||||
:text "${EWW_CPU.cores[0].freq} MHz"
|
||||
:halign "start"
|
||||
:class "sys-text-sub")))
|
||||
|
||||
; memory
|
||||
(box
|
||||
:class "sys-box"
|
||||
:space-evenly false
|
||||
:halign "end"
|
||||
(circular-progress
|
||||
:value {EWW_RAM.used_mem_perc}
|
||||
:class "sys-mem"
|
||||
:thickness 3
|
||||
(label
|
||||
:text ""
|
||||
:class "sys-icon-mem icon"))
|
||||
(box
|
||||
:class "text"
|
||||
:orientation "v"
|
||||
(label
|
||||
:text "memory"
|
||||
:halign "start"
|
||||
:class "sys-text-mem")
|
||||
(label
|
||||
:text {EWW_RAM.used_mem / GB < 1 ? "${round(EWW_RAM.used_mem / MB, 1)} M used" : "${round(EWW_RAM.used_mem / GB, 1)} G used"}
|
||||
:halign "start"
|
||||
:class "sys-text-sub")
|
||||
(label
|
||||
:text {EWW_RAM.total_mem / GB < 1 ? "${round(EWW_RAM.total_mem / MB, 1)} M total" : "${round(EWW_RAM.total_mem / GB, 1)} G total"}
|
||||
:halign "start"
|
||||
:class "sys-text-sub"))))
|
||||
|
||||
(centerbox ; battery info & power button
|
||||
:class "bottom-row"
|
||||
(box
|
||||
:class "battery-box"
|
||||
:space-evenly false
|
||||
:halign "start"
|
||||
(label
|
||||
:class "battery-icon icon ${EWW_BATTERY.total_avg > 20 ? '' : 'low'}"
|
||||
:text {battery_icons[round(EWW_BATTERY.total_avg / (100 / arraylength(battery_icons)) - 1,0)]})
|
||||
(label
|
||||
:class "text"
|
||||
:text {round(EWW_BATTERY.total_avg,0)})
|
||||
(label
|
||||
:class "battery-status text"
|
||||
:text {battery.status})
|
||||
(label
|
||||
:class "battery-rate text"
|
||||
:text {battery.rate}))
|
||||
(label) ; empty element; centerbox requires 3 children but we only need left/right
|
||||
(box ; power button
|
||||
:space-evenly false
|
||||
:halign "end"
|
||||
(button
|
||||
:halign "end"
|
||||
:class "power-button icon"
|
||||
:onclick "wlogout -p layer-shell &"
|
||||
"")))))
|
||||
|
||||
(defwindow system-menu
|
||||
:stacking "fg"
|
||||
:monitor 0
|
||||
:geometry (geometry
|
||||
:x "0"
|
||||
:y "0"
|
||||
:width "0%"
|
||||
:height "0%"
|
||||
:anchor "right top")
|
||||
(system-menu))
|
Loading…
Reference in a new issue