Moved bar to quickshell

This commit is contained in:
agryphus 2025-02-09 21:34:23 -05:00
parent ab0a71784e
commit 5a3a18f9f7
30 changed files with 971 additions and 206 deletions

View file

@ -3,7 +3,7 @@
# Wayland related environment variables. # Wayland related environment variables.
env = HYPRCURSOR_THEME,McMojave env = HYPRCURSOR_THEME,McMojave
env = HYPRCURSOR_SIZE,30 env = HYPRCURSOR_SIZE,30
env = TERMINAL,foot env = TERMINAL,st
env = QT_QPA_PLATFORM,wayland env = QT_QPA_PLATFORM,wayland
opengl { opengl {
@ -37,7 +37,7 @@ input {
sensitivity = 0 # -1.0 - 1.0, 0 means no modification. sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
kb_options = caps:swapescape # kb_options = caps:swapescape
} }
general { general {
@ -112,6 +112,7 @@ windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1] windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
windowrulev2 = bordersize 0, floating:0, onworkspace:f[1] windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
windowrulev2 = rounding 0, floating:0, onworkspace:f[1] windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
windowrulev2 = float, class:nm-tray
gestures { gestures {
# See https://wiki.hyprland.org/Configuring/Variables/ for more # See https://wiki.hyprland.org/Configuring/Variables/ for more
@ -122,7 +123,7 @@ misc {
# See https://wiki.hyprland.org/Configuring/Variables/ for more # See https://wiki.hyprland.org/Configuring/Variables/ for more
force_default_wallpaper = 0 # Set to 0 to disable the anime mascot wallpapers force_default_wallpaper = 0 # Set to 0 to disable the anime mascot wallpapers
# enable_swallow = true # enable_swallow = true
# swallow_regex = ^(st|foot|footclient)$ # swallow_regex = ^(st-256color)$
mouse_move_enables_dpms = true mouse_move_enables_dpms = true
} }
@ -140,29 +141,28 @@ layerrule = ignorezero, waybar
$mainMod = SUPER $mainMod = SUPER
# Program spawning hotkeys # Program spawning hotkeys
bind = CONTROL ALT, BACKSPACE, exec, foot -e zsh -c 'btop' bind = CONTROL ALT, BACKSPACE, exec, st -e zsh -c 'btop'
bind = $mainMod CONTROL, W, exec, [floating] foot -W 78x38 -e nmtui bind = $mainMod CONTROL, W, exec, [floating] foot -W 78x38 -e nmtui
bind = $mainMod, RETURN, exec, foot bind = $mainMod, RETURN, exec, st
bind = $mainMod, W, exec, firefox bind = $mainMod, W, exec, zen
bind = $mainMod, E, exec, foot -e zsh -c 'tmp="$(mktemp -t "yazi-cwd.XXXXX")"; yazi "$@" --cwd-file="$tmp"; printf "\033]0;foot\007"; if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then; cd -- "$cwd"; fi; rm -f -- "$tmp"; exec $SHELL' bind = $mainMod, E, exec, st -e zsh -c 'tmp="$(mktemp -t "yazi-cwd.XXXXX")"; yazi "$@" --cwd-file="$tmp"; printf "\033]0;st\007"; if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then; cd -- "$cwd"; fi; rm -f -- "$tmp"; exec $SHELL'
bind = $mainMod SHIFT, E, exec, emacsclient -c -a 'emacs' bind = $mainMod SHIFT, E, exec, emacsclient -c -a 'emacs'
bind = $mainMod, C, exec, foot -e zsh -c 'khal interactive' bind = $mainMod, C, exec, st -e zsh -c 'khal interactive'
bind = $mainMod, M, exec, foot -e zsh -c 'neomutt' bind = $mainMod, M, exec, st -e zsh -c 'neomutt'
# Menu hoykeys # Menu hoykeys
bind = $mainMod, R, exec, fuzzel bind = $mainMod, R, exec, fuzzel
# System control keybinds # System control keybinds
binde = $mainMod, MINUS, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%-; test -z "$(pidof waybar)" && notify-send -r 44 "$(wpctl get-volume @DEFAULT_AUDIO_SINK@)" binde = $mainMod, MINUS, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%-
binde = $mainMod SHIFT, MINUS, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-; test -z "$(pidof waybar)" && notify-send -r 44 "$(wpctl get-volume @DEFAULT_AUDIO_SINK@)" binde = $mainMod SHIFT, MINUS, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
binde = $mainMod, EQUAL, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+; test -z "$(pidof waybar)" && notify-send -r 44 "$(wpctl get-volume @DEFAULT_AUDIO_SINK@)" binde = $mainMod, EQUAL, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+
binde = $mainMod SHIFT, EQUAL, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+; test -z "$(pidof waybar)" && notify-send -r 44 "$(wpctl get-volume @DEFAULT_AUDIO_SINK@)" binde = $mainMod SHIFT, EQUAL, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
binde = ,F7, exec, change-brightness up binde = ,F7, exec, change-brightness up
binde = ,XF86MonBrightnessUp, exec, change-brightness up binde = ,XF86MonBrightnessUp, exec, change-brightness up
binde = ,F6, exec, change-brightness down binde = ,F6, exec, change-brightness down
binde = ,XF86MonBrightnessDown,exec, change-brightness down binde = ,XF86MonBrightnessDown,exec, change-brightness down
bind = $mainMod, L, exec, swaylock -e -c 000000 bind = $mainMod, L, exec, hyprlock
bind = $mainMod, L, exec, sleep 5; hyprctl dispatch dpms off
bind = $mainMod CONTROL SHIFT, R, exec, startw # Reload all graphical daemons bind = $mainMod CONTROL SHIFT, R, exec, startw # Reload all graphical daemons
@ -176,7 +176,9 @@ bind = $mainMod, D, exec, hyprctl dispatch submap menu-submap; sleep 2; hyprctl
submap = menu-submap submap = menu-submap
bind = ,A, exec, menu-accent bind = ,A, exec, menu-accent
bind = ,A, submap, reset bind = ,A, submap, reset
bind = ,M, exec, menu-man bind = ,B, exec, [floating] foot -W 80x17 -e dash -c -i 'menu-bookmark'
bind = ,B, submap, reset
bind = ,M, exec, [floating] foot -W 78x38 -e dash -c -i 'menu-man'
bind = ,M, submap, reset bind = ,M, submap, reset
bind = ,W, exec, networkmanager_dmenu bind = ,W, exec, networkmanager_dmenu
bind = ,W, submap, reset bind = ,W, submap, reset
@ -186,7 +188,7 @@ bind = ,I, exec, menu-wpio source
bind = ,I, submap, reset bind = ,I, submap, reset
bind = ,L, exec, hyprmonitors menu bind = ,L, exec, hyprmonitors menu
bind = ,L, submap, reset bind = ,L, submap, reset
bind = ,P, exec, menu-pass bind = ,P, exec, [floating] foot -W 80x17 -e zsh -c -i 'menu-pass'
bind = ,P, submap, reset bind = ,P, submap, reset
submap = reset submap = reset

View file

@ -1,29 +1,34 @@
version = "1.1.15" version = "1.1.15"
[title."(?i)foot"]
Yazi = "󰇥"
[class] [class]
DEFAULT = "{class}" DEFAULT = "{class}"
"(?i)Anki" = " " "(?i)anki" = " "
"(?i)blueman-manager-wrapped" = " " "(?i)blueman-manager-wrapped" = " "
"(?i)chromium" = " " "(?i)chromium" = " "
"(?i)discord" = "󰊴 " "(?i)discord" = "󰊴 "
"(?i)Element" = "󰘨 " "(?i)element" = " "
"(?i)emacs" = " " "(?i)emacs" = " "
"(?i)firefox" = " " "(?i)firefox" = " "
"(?i)foot" = " " "(?i)foot" = " "
"(?i)ghidra" = " " "(?i)ghidra" = " "
"(?i)Gimp" = " " "(?i)gimp" = " "
"(?i)Kitty" = " " "(?i)kitty" = " "
"(?i)libreoffice-draw" = "󰽉 " "(?i)libreoffice-draw" = "󰽉 "
"(?i)libreoffice-writer" = "󰷈 " "(?i)libreoffice-writer" = "󰷈 "
"(?i)mpv" = " " "(?i)mpv" = " "
"(?i)mullvad vpn" = " " "(?i)mullvad vpn" = " "
"(?i)Nsxiv" = " " "(?i)nsxiv" = " "
"(?i)signal" = "󰭹 "
"(?i)slack" = "󰒱 " "(?i)slack" = "󰒱 "
"(?i)spotify" = " " "(?i)spotify" = " "
"(?i)st" = " " "(?i)st" = " "
"(?i)steam" = " " "(?i)steam" = " "
"(?i)virtualbox" = " " "(?i)virtualbox" = " "
"(?i)zathura" = " " "(?i)zathura" = " "
"(?i)zen" = "󰇧 "
[class_active] [class_active]
@ -52,7 +57,7 @@ DEFAULT = "{class}"
"(?i)neomutt" = "neomutt" "(?i)neomutt" = "neomutt"
[title_in_class_active."(?i)firefox"] [title_in_class_active."(?i)firefox"]
"(?i)twitch" = "<span color='purple'>{icon}</span>" "(?i)twitch" = "<span style='color:purple'>{icon}</span>"
[title_in_initial_class] [title_in_initial_class]
@ -79,9 +84,9 @@ dedup_inactive_fullscreen = false
delim = "" delim = ""
workspace = "{id}:{delim}{clients}" workspace = "{id}:{delim}{clients}"
workspace_empty = "{id}" workspace_empty = "{id}"
client = "<span color='#999999'>{icon}</span>" client = "<span>{icon}</span>"
client_fullscreen = "[{icon}]" client_fullscreen = "[{icon}]"
client_active = "<span color='#FFFFFF'>{icon}</span>" client_active = "<span style='color:#FFFFFF'>{icon}</font>"
client_dup = "{icon}{counter_sup}" client_dup = "{icon}{counter_sup}"
client_dup_active = "*{icon}*{delim}{icon}{counter_unfocused_sup}" client_dup_active = "*{icon}*{delim}{icon}{counter_unfocused_sup}"
client_dup_fullscreen = "[{icon}]{delim}{icon}{counter_unfocused_sup}" client_dup_fullscreen = "[{icon}]{delim}{icon}{counter_unfocused_sup}"

View file

@ -3,10 +3,14 @@
"position": "top", "position": "top",
"height": 27, "height": 27,
"modules-left": ["hyprland/workspaces", "custom/scratch", "hyprland/mode", "hyprland/window"], "modules-left": ["custom/icon", "hyprland/workspaces", "custom/scratch", "hyprland/mode", "hyprland/window"],
"modules-center": [], "modules-center": [],
"modules-right": ["tray", "memory", "pulseaudio", "battery", "clock"], "modules-right": ["tray", "memory", "pulseaudio", "battery", "clock"],
"custom/icon": {
"format": "",
},
"hyprland/workspaces": { "hyprland/workspaces": {
"disable-scroll": true, "disable-scroll": true,
"disable-markup": true, "disable-markup": true,

View file

@ -29,9 +29,12 @@ button:hover {
} }
#custom-scratch { #custom-icon {
color: #b8b8b8; color: #ffffff;
padding: 0px 9px 0px 9px; padding: 0px 9px 0px 9px;
margin: 0px 0px 0px 0px;
border: none;
border-radius: 0;
} }
#workspaces button { #workspaces button {

View file

@ -5,24 +5,11 @@
swww kill swww kill
pkill fcitx5 pkill fcitx5
# Start daemons that can turn on asynchronously
(
foot --server &
systemctl --user restart network-manager-applet
pkill emacs; emacs --daemon
) &
# Rearrange monitors
hyprmonitors auto
systemctl --user restart hyprland-autoname-workspaces systemctl --user restart hyprland-autoname-workspaces
swww-daemon & swww-daemon &
fcitx5 & fcitx5 &
waybar & quickshell &
hypridle &
# Sometimes the monitor config does not want to apply properly on the first pkill emacs; emacs --daemo
# go. I then have to reload the configuration to make sure that the monitors
# are actually in their intended place.
hyprctl reload

View file

@ -1,8 +1,6 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
let let
# # Only allowing unfree for a useUasm yazi fix. Remove once patched.
# nixos-unstable = (import <nixos-unstable> {config.allowUnfree = true;});
flake-compat = builtins.fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz"; flake-compat = builtins.fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz";
in { in {
# Nix settings # Nix settings
@ -31,17 +29,17 @@ in {
]; ];
}; };
i18n.defaultLocale = "en_US.UTF-8"; i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = { i18n.extraLocaleSettings = {
LC_ADDRESS = "en_US.UTF-8"; LC_ADDRESS = "en_US.UTF-8";
LC_IDENTIFICATION = "en_US.UTF-8"; LC_IDENTIFICATION = "en_US.UTF-8";
LC_MEASUREMENT = "en_US.UTF-8"; LC_MEASUREMENT = "en_US.UTF-8";
LC_MONETARY = "en_US.UTF-8"; LC_MONETARY = "en_US.UTF-8";
LC_NAME = "en_US.UTF-8"; LC_NAME = "en_US.UTF-8";
LC_NUMERIC = "en_US.UTF-8"; LC_NUMERIC = "en_US.UTF-8";
LC_PAPER = "en_US.UTF-8"; LC_PAPER = "en_US.UTF-8";
LC_TELEPHONE = "en_US.UTF-8"; LC_TELEPHONE = "en_US.UTF-8";
LC_TIME = "en_US.UTF-8"; LC_TIME = "en_US.UTF-8";
}; };
fonts.packages = with pkgs; [ fonts.packages = with pkgs; [
@ -150,7 +148,6 @@ in {
openconnect # Connect to VPNs openconnect # Connect to VPNs
pass-nodmenu # CLI password store (without dmenu dependency) pass-nodmenu # CLI password store (without dmenu dependency)
pinentry-curses # Terminal-based pinentry program pinentry-curses # Terminal-based pinentry program
python311 # Python
socat # Interact with sockets socat # Interact with sockets
stow # Simlink farm (used for dotfile management) stow # Simlink farm (used for dotfile management)
tldr # Brief info about a command tldr # Brief info about a command
@ -179,10 +176,16 @@ in {
nix-prefetch-git # Like nix-prefetch-url, but for git nix-prefetch-git # Like nix-prefetch-url, but for git
nvd # See diffs between builds nvd # See diffs between builds
# Pop into an environment abiding by the Filesystem Hierarchy Standard to run # Custom overlays. See below for explanations
# applications which do not play nicely with NixOS. fhs-run
( python-common
let ];
nixpkgs.overlays = [
(self: super: {
# Pop into an environment abiding by the Filesystem Hierarchy Standard
# to run applications which do not play nicely with NixOS.
fhs-run = pkgs.buildFHSUserEnv { fhs-run = pkgs.buildFHSUserEnv {
name = "fhs-run"; name = "fhs-run";
targetPkgs = pkgs: []; targetPkgs = pkgs: [];
@ -192,35 +195,14 @@ in {
eval "$@" # Execute whatever arguments eval "$@" # Execute whatever arguments
''; '';
}; };
in
fhs-run
)
# Defining an environment to run "make" with the proper libraries installed # When evoking the command `python` from outside a shell, it runs the
# "make", in the main environment, references the script, which envokes the # commands inside a nix shell containing common python packages that I
# environment, and passes the args to gnumake. # always want to be available.
( python-common = pkgs.python3.withPackages (ps: with ps; [
let requests
make-shell = pkgs.buildEnv { ]);
name = "make-shell"; })
paths = with pkgs; [
# Tools
gnumake
pkg-config
# Libraries
harfbuzz
xorg.libX11.dev
xorg.libXft
xorg.libXinerama
];
};
in
(pkgs.writeScriptBin "make" ''
#!/usr/bin/env sh
nix-shell -p ${make-shell} --run "make $*"
'')
)
]; ];
nixpkgs.config.packageOverrides = pkgs: { nixpkgs.config.packageOverrides = pkgs: {

View file

@ -1,103 +0,0 @@
{ lib
, stdenv
, buildNpmPackage
, fetchFromGitLab
, nodePackages
, meson
, pkg-config
, ninja
, gobject-introspection
, gtk3
, libpulseaudio
, gjs
, wrapGAppsHook
, upower
, gnome
, gtk-layer-shell
, glib-networking
, networkmanager
, libdbusmenu-gtk3
, gvfs
, libsoup_3
, libnotify
, pam
, extraPackages ? [ ]
, version ? "git"
, buildTypes ? false
}:
let
gvc-src = fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "GNOME";
repo = "libgnome-volume-control";
rev = "8e7a5a4c3e51007ce6579292642517e3d3eb9c50";
sha256 = "sha256-FosJwgTCp6/EI6WVbJhPisokRBA6oT0eo7d+Ya7fFX8=";
};
in
stdenv.mkDerivation rec {
pname = "ags";
inherit version;
src = buildNpmPackage {
name = pname;
src = ../.;
dontBuild = true;
npmDepsHash = "sha256-ucWdADdMqAdLXQYKGOXHNRNM9bhjKX4vkMcQ8q/GZ20=";
installPhase = ''
mkdir $out
cp -r * $out
'';
};
mesonFlags = builtins.concatLists [
(lib.optional buildTypes "-Dbuild_types=true")
];
prePatch = ''
mkdir -p ./subprojects/gvc
cp -r ${gvc-src}/* ./subprojects/gvc
'';
postPatch = ''
chmod +x post_install.sh
patchShebangs post_install.sh
'';
nativeBuildInputs = [
pkg-config
meson
ninja
nodePackages.typescript
wrapGAppsHook
gobject-introspection
];
buildInputs = [
gjs
gtk3
libpulseaudio
upower
gnome.gnome-bluetooth
gtk-layer-shell
glib-networking
networkmanager
libdbusmenu-gtk3
gvfs
libsoup_3
libnotify
pam
] ++ extraPackages;
meta = with lib; {
description = "A customizable and extensible shell";
homepage = "https://github.com/Aylur/ags";
platforms = [ "x86_64-linux" "aarch64-linux" ];
license = licenses.gpl3;
meta.maintainers = [ lib.maintainers.Aylur ];
};
}

View file

@ -6,6 +6,7 @@ let
flake-compat = builtins.fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz"; flake-compat = builtins.fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz";
hyprland_nightly = (import flake-compat { hyprland_nightly = (import flake-compat {
src = builtins.fetchGit { src = builtins.fetchGit {
ref = "main";
url = "https://github.com/hyprwm/Hyprland.git"; url = "https://github.com/hyprwm/Hyprland.git";
submodules = true; submodules = true;
}; };
@ -24,11 +25,10 @@ in {
hyprland = { # Dynamic tiling window manager hyprland = { # Dynamic tiling window manager
enable = true; enable = true;
xwayland.enable = true; xwayland.enable = true;
package = nixos-unstable.hyprland.override(o: { # package = nixos-unstable.hyprland;
aquamarine = nixos-unstable.aquamarine;
});
# package = hyprland_nightly.packages.${pkgs.stdenv.hostPlatform.system}.hyprland; # package = hyprland_nightly.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
}; };
nm-applet.enable = true;
}; };
systemd.user.services = { systemd.user.services = {
@ -41,16 +41,16 @@ in {
serviceConfig.Restart = "always"; serviceConfig.Restart = "always";
serviceConfig.RestartSec = 1; serviceConfig.RestartSec = 1;
}; };
network-manager-applet = { # network-manager-applet = {
description = "Start the network manager applet"; # description = "Start the network manager applet";
after = [ "graphical-session.target" ]; # after = [ "graphical-session.target" ];
requires = [ "graphical-session.target" ]; # requires = [ "graphical-session.target" ];
wantedBy = [ "graphical-session.target" ]; # wantedBy = [ "graphical-session.target" ];
serviceConfig.Type = "forking"; # serviceConfig.Type = "forking";
serviceConfig.Restart = "always"; # serviceConfig.Restart = "always";
serviceConfig.RestartSec = 1; # serviceConfig.RestartSec = 1;
serviceConfig.ExecStart = "${pkgs.networkmanagerapplet}/bin/nm-applet"; # serviceConfig.ExecStart = "${pkgs.networkmanagerapplet}/bin/nm-applet";
}; # };
}; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
@ -63,6 +63,7 @@ in {
grimblast # Allows freezing screen grimblast # Allows freezing screen
grim # Screenshot tool grim # Screenshot tool
hicolor-icon-theme # Icons hicolor-icon-theme # Icons
hypridle # Do commands upon user idle
hyprland-autoname-workspaces # Add icons to workspace titles hyprland-autoname-workspaces # Add icons to workspace titles
hyprlock # Screen locking utility hyprlock # Screen locking utility
hyprpaper hyprpaper
@ -70,7 +71,7 @@ in {
kanshi # Autorandr substitute kanshi # Autorandr substitute
libnotify # Send messages to notification daemon libnotify # Send messages to notification daemon
libreoffice # MSOffice btfo libreoffice # MSOffice btfo
networkmanagerapplet # Wifi dropdown menu # networkmanagerapplet # Wifi dropdown menu
networkmanager_dmenu # Manage wifi with dmenu networkmanager_dmenu # Manage wifi with dmenu
nsxiv # Image viewer nsxiv # Image viewer
nwg-displays nwg-displays
@ -80,6 +81,7 @@ in {
rofi-pass # Rofi frontend for password store rofi-pass # Rofi frontend for password store
sassc # SCSS interpreter sassc # SCSS interpreter
slurp # Screen selection utility slurp # Screen selection utility
st
swaylock # Wayland session locker swaylock # Wayland session locker
swww # Sets background images swww # Sets background images
texlive.combined.scheme-full # LaTeX to create documents texlive.combined.scheme-full # LaTeX to create documents
@ -94,6 +96,7 @@ in {
xwaylandvideobridge # Allows screensharing from XWayland programs xwaylandvideobridge # Allows screensharing from XWayland programs
xorg.xcursorthemes xorg.xcursorthemes
zathura # Minimalist PDF reader zathura # Minimalist PDF reader
zen-browser
# GTK Themes # GTK Themes
lxappearance-gtk2 # Theme switcher lxappearance-gtk2 # Theme switcher
@ -101,10 +104,28 @@ in {
]; ];
nixpkgs.overlays = [ nixpkgs.overlays = [
(self: super: { (final: prev: {
hyprland-autoname-workspaces = nixos-unstable.hyprland-autoname-workspaces; hyprland-autoname-workspaces = nixos-unstable.hyprland-autoname-workspaces;
waybar = nixos-unstable.waybar; waybar = nixos-unstable.waybar;
typst = nixos-unstable.typst; typst = nixos-unstable.typst;
# typst = (import flake-compat {
# src = builtins.fetchGit {
# url = "https://github.com/typst/typst.git";
# };
# }).outputs.packages.${pkgs.stdenv.hostPlatform.system}.default;
zen-browser = (import flake-compat {
src = builtins.fetchGit {
url = "https://github.com/0xc000022070/zen-browser-flake.git";
};
}).outputs.packages.${pkgs.stdenv.hostPlatform.system}.default;
st = prev.st.overrideAttrs (o: {
src = /home/vince/.config/st;
buildInputs = o.buildInputs ++ (with pkgs; [
# Extra libraries needed to build patches
harfbuzz
imlib2
]);
});
}) })
]; ];
} }

View file

@ -0,0 +1,18 @@
pragma Singleton
import QtQuick
import Quickshell
Singleton {
id: root
property var popupContext: PopupContext {};
property var date: new Date()
Timer {
interval: 1000
repeat: true
running: true
onTriggered: root.date = new Date()
}
}

View file

@ -0,0 +1,6 @@
import QtQuick
// Tracks which popup of a set is active.
QtObject {
property var popup: null;
}

View file

@ -0,0 +1,57 @@
import Quickshell
import Quickshell.Io
import QtQuick
import QtQuick.Layouts
import "blocks" as Blocks
Scope {
Variants {
model: Quickshell.screens
PanelWindow {
property var modelData
screen: modelData
color: "#cc000000"
height: 27
anchors {
top: true
left: true
right: true
}
RowLayout {
spacing: 0
width: parent.width
height: parent.height
// Left side
RowLayout {
spacing: 0
Layout.alignment: Qt.AlignLeft
Blocks.Icon {}
Blocks.Workspaces {}
Blocks.ActiveWorkspace {}
}
// Right side
RowLayout {
spacing: 0
Layout.alignment: Qt.AlignRight
Blocks.SystemTray {}
Blocks.Test {}
Blocks.Notifications {}
Blocks.Memory {}
Blocks.Sound {}
Blocks.Battery {}
Blocks.Date {}
Blocks.Time {}
}
}
}
}
}

View file

@ -0,0 +1,89 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
Rectangle {
id: root
Layout.preferredWidth: wsText.implicitWidth + 10
Layout.preferredHeight: 27
property string text
property bool dim: false
property bool underline
property var onClicked: function() {}
property int leftPadding
property int rightPadding
property string fgColor: "white"
property string dimFgColor: "#999999"
property string hoveredBgColor: "#444444"
// Background color
color: {
if (mouseArea.containsMouse)
return hoveredBgColor;
return "transparent";
}
states: [
State {
when: mouseArea.containsMouse
PropertyChanges {
target: root
}
}
]
Behavior on color {
ColorAnimation {
duration: 200
}
}
BarText {
id: wsText
text: root.text
anchors {
left: parent.left
right: parent.right
leftMargin: root.leftPadding
rightMargin: root.rightPadding
verticalCenter: parent.verticalCenter
}
color: {
if (mouseArea.containsMouse || !root.dim)
return fgColor
return dimFgColor
}
Behavior on color {
ColorAnimation {
duration: 100
}
}
}
MouseArea {
id: mouseArea
anchors.fill: root
hoverEnabled: true
acceptedButtons: Qt.LeftButton
onClicked: root.onClicked()
}
// While line underneath workspace
Rectangle {
id: wsLine
width: parent.width
height: 3
color: {
if (parent.underline)
return fgColor;
return "transparent";
}
anchors.bottom: parent.bottom
}
}

View file

@ -0,0 +1,39 @@
import Quickshell
import Quickshell.Io
import QtQuick
Item {
property string text
property string color: "white"
property string mainFont: "FiraCode"
property string symbolFont: "Symbols Nerd Font Mono"
property int pointSize: 11
implicitWidth: thetext.implicitWidth
implicitHeight: thetext.implicitHeight
function wrapSymbols(text) {
const isSymbol = (codePoint) =>
(codePoint >= 0xE000 && codePoint <= 0xF8FF) // Private Use Area
|| (codePoint >= 0xF0000 && codePoint <= 0xFFFFF) // Supplementary Private Use Area-A
|| (codePoint >= 0x100000 && codePoint <= 0x10FFFF); // Supplementary Private Use Area-B
return text.replace(/./gu, (c) => isSymbol(c.codePointAt(0))
? `<span style='font-family: ${symbolFont}; letter-spacing: -5px; font-size: ${pointSize + 4}px'>${c}</span>`
: c);
}
Text {
id: thetext
text: wrapSymbols(parent.text)
color: parent.color
anchors.centerIn: parent
font {
family: parent.mainFont
pointSize: parent.pointSize
}
textFormat: Text.RichText
}
}

View file

@ -0,0 +1,11 @@
import QtQuick
Text {
required property int id
required property string body
required property string summary
property int margin
text: `- ${summary}: ${body}`
}

View file

@ -0,0 +1,101 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Services.Notifications
PanelWindow {
// required property font custom_font
required property color text_color
property list<QtObject> notification_objects
width: 500
height: 600
color: "#171a18"
WlrLayershell.layer: WlrLayer.Overlay
Rectangle {
border.width: 5
border.color: "#8ec07c"
anchors.fill: parent
color: "transparent"
ColumnLayout {
id: content
anchors {
left: parent.left
leftMargin: 10
right: parent.right
rightMargin: 10
top: parent.top
topMargin: 10
}
RowLayout {
Layout.fillWidth: true
Text {
Layout.fillWidth: true
text: "Notifications:"
// font: custom_font
color: text_color
}
Text {
text: "clear"
// font: custom_font
color: text_color
TapHandler {
id: tapHandler
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: {
server.trackedNotifications.values.forEach((notification) => {
notification.tracked = false
})
notification_objects.forEach((object) => {
object.destroy();
})
notification_objects = [];
}
}
HoverHandler {
id: mouse
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
cursorShape: Qt.PointingHandCursor
}
}
}
}
}
NotificationServer {
id: server
onNotification: (notification) => {
notification.tracked = true
console.log(JSON.stringify(notification));
var notification_component = Qt.createComponent("Notification.qml");
var notification_object = notification_component
.createObject(content,
{
id: notification.id,
body: notification.body,
summary: notification.summary,
// font: custom_font,
color: text_color,
margin: 10
}
)
if (notification_object == null) {
console.log("Error creating notification")
} else {
notification_objects.push(notification_object);
}
}
}
}

View file

@ -0,0 +1,89 @@
import QtQuick
import Quickshell
import "root:/" // for Globals
LazyLoader {
id: root
// The item to display the tooltip at. If set to null the tooltip will be hidden.
property Item relativeItem: null
// Tracks the item after relativeItem is unset.
property Item displayItem: null
property PopupContext popupContext: Globals.popupContext
property bool hoverable: false;
readonly property bool hovered: item?.hovered ?? false
// The content to show in the tooltip.
required default property Component contentDelegate
active: displayItem != null && popupContext.popup == this
onRelativeItemChanged: {
if (relativeItem == null) {
if (item != null) item.hideTimer.start();
} else {
if (item != null) item.hideTimer.stop();
displayItem = relativeItem;
popupContext.popup = this;
}
}
PopupWindow {
anchor {
window: root.displayItem.QsWindow.window
rect.y: anchor.window.height + 3
rect.x: anchor.window.contentItem.mapFromItem(root.displayItem, root.displayItem.width / 2, 0).x
edges: Edges.Top
gravity: Edges.Bottom
}
visible: true
property alias hovered: body.containsMouse;
property Timer hideTimer: Timer {
interval: 250
// unloads the popup by causing active to become false
onTriggered: root.popupContext.popup = null;
}
color: "transparent"
// don't accept mouse input if !hoverable
Region { id: emptyRegion }
mask: root.hoverable ? null : emptyRegion
width: body.implicitWidth
height: body.implicitHeight
MouseArea {
id: body
anchors.fill: parent
implicitWidth: content.implicitWidth + 10
implicitHeight: content.implicitHeight + 10
hoverEnabled: root.hoverable
Rectangle {
anchors.fill: parent
radius: 5
border.width: 1
color: palette.active.toolTipBase
border.color: palette.active.light
Loader {
id: content
anchors.centerIn: parent
sourceComponent: contentDelegate
active: true
}
}
}
}
}

View file

@ -0,0 +1,33 @@
import QtQuick
import Quickshell.Io
import Quickshell.Hyprland
import "../"
BarText {
text: {
var str = activeWindowTitle
return str.length > chopLength ? str.slice(0, chopLength) + '...' : str;
}
property int chopLength: 70
property string activeWindowTitle
Process {
id: titleProc
command: ["sh", "-c", "hyprctl activewindow | grep title: | sed 's/^[^:]*: //'"]
running: true
stdout: SplitParser {
onRead: data => activeWindowTitle = data
}
}
Component.onCompleted: {
Hyprland.rawEvent.connect(hyprEvent)
}
function hyprEvent(e) {
titleProc.running = true
}
}

View file

@ -0,0 +1,26 @@
import QtQuick
import Quickshell.Io
import "../"
BarBlock {
property string battery
text: battery
Process {
id: batteryProc
command: ["block_battery"]
running: true
stdout: SplitParser {
onRead: data => battery = data
}
}
Timer {
interval: 1000
running: true
repeat: true
onTriggered: batteryProc.running = true
}
}

View file

@ -0,0 +1,37 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import "../"
Item {
implicitHeight: text.implicitHeight
implicitWidth: text.implicitWidth
property string percentUsed
Process {
id: cpuProc
command: ["sh", "-c", "top -bn 1 | grep \"%Cpu(s)\" | awk '{usage=100-$8; printf \"%02d%%\\n\", usage}'"]
running: true
stdout: SplitParser {
onRead: data => percentUsed = data
}
}
Timer {
interval: 2000
running: true
repeat: true
onTriggered: cpuProc.running = true
}
BarText {
id: text
text: "<div style = 'font-family: Symbols Nerd Font Mono'>%1</div>%2"
.arg(" ") // The rest of the string
.arg(percentUsed) // Symbol needs its own font
}
}

View file

@ -0,0 +1,8 @@
import QtQuick
import "../"
BarBlock {
id: text
text: ` ${Datetime.date}`
}

View file

@ -0,0 +1,31 @@
pragma Singleton
import Quickshell
import Quickshell.Io
import QtQuick
Singleton {
property string time;
property string date;
Process {
id: dateProc
command: ["date", "+%a %e %b|%R"]
running: true
stdout: SplitParser {
onRead: data => {
date = data.split("|")[0]
time = data.split("|")[1]
}
}
}
Timer {
interval: 1000
running: true
repeat: true
onTriggered: dateProc.running = true
}
}

View file

@ -0,0 +1,11 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import "../"
BarBlock {
Layout.preferredWidth: 30
rightPadding: 5
text: ""
}

View file

@ -0,0 +1,29 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Io
import "../"
BarBlock {
id: text
text: ` ${Math.floor(percentFree)}%`
property real percentFree
Process {
id: memProc
command: ["sh", "-c", "free | grep Mem | awk '{print $3/$2 * 100.0}'"]
running: true
stdout: SplitParser {
onRead: data => percentFree = data
}
}
Timer {
interval: 2000
running: true
repeat: true
onTriggered: memProc.running = true
}
}

View file

@ -0,0 +1,34 @@
import QtQuick
import Quickshell.Services.Notifications
import "../"
BarBlock {
id: root
property bool showNotification: false
text: " " + notifServer.trackedNotifications.values.length
onClicked: function() {
showNotification = !showNotification
}
NotificationServer {
id: notifServer
onNotification: (notification) => {
notification.tracked = true
}
}
NotificationPanel {
text_color: root.color
visible: showNotification
anchors {
top: parent.top
}
margins {
top: 10
}
}
}

View file

@ -0,0 +1,15 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.Pipewire
import "../"
BarBlock {
id: text
text: ` ${Math.floor(sink?.audio.volume * 100)}%`
property PwNode sink: Pipewire.defaultAudioSink
PwObjectTracker { objects: [ sink ] }
}

View file

@ -0,0 +1,74 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.SystemTray
import "../" as Bar
RowLayout {
spacing: 5
Repeater {
model: SystemTray.items
MouseArea {
id: delegate
required property SystemTrayItem modelData
property alias item: delegate.modelData
Layout.fillHeight: true
implicitWidth: icon.implicitWidth + 5
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
hoverEnabled: true
onClicked: event => {
if (event.button == Qt.LeftButton) {
item.activate();
} else if (event.button == Qt.MiddleButton) {
item.secondaryActivate();
} else if (event.button == Qt.RightButton) {
menuAnchor.open();
}
}
onWheel: event => {
event.accepted = true;
const points = event.angleDelta.y / 120
item.scroll(points, false);
}
IconImage {
id: icon
anchors.centerIn: parent
source: item.icon
implicitSize: 16
}
QsMenuAnchor {
id: menuAnchor
menu: item.menu
anchor.window: delegate.QsWindow.window
anchor.adjustment: PopupAdjustment.Flip
anchor.onAnchoring: {
const window = delegate.QsWindow.window;
const widgetRect = window.contentItem.mapFromItem(delegate, 0, delegate.height, delegate.width, delegate.height);
menuAnchor.anchor.rect = widgetRect;
}
}
Bar.Tooltip {
relativeItem: delegate.containsMouse ? delegate : null
Label {
text: delegate.item.tooltipTitle || delegate.item.id
}
}
}
}
}

View file

@ -0,0 +1,77 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.SystemTray
import "../"
Repeater {
// model: SystemTray.items
model: ScriptModel {
values: SystemTray.items.values
.filter((item) => item.id == "nm-tray")
}
BarBlock {
id: block
Layout.preferredWidth: 30
leftPadding: 4
text: " "
required property SystemTrayItem modelData
property alias item: block.modelData
MouseArea {
id: delegate
anchors.fill: block
property alias item: block.item
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
hoverEnabled: true
onClicked: event => {
if (event.button == Qt.LeftButton) {
item.activate();
} else if (event.button == Qt.MiddleButton) {
item.secondaryActivate();
} else if (event.button == Qt.RightButton) {
menuAnchor.open();
}
}
onWheel: event => {
event.accepted = true;
const points = event.angleDelta.y / 120
item.scroll(points, false);
}
QsMenuAnchor {
id: menuAnchor
menu: item.menu
anchor.window: delegate.QsWindow.window
anchor.adjustment: PopupAdjustment.Flip
anchor.onAnchoring: {
console.log("here2")
const window = delegate.QsWindow.window;
const widgetRect = window.contentItem.mapFromItem(delegate, 0, delegate.height, delegate.width, delegate.height);
menuAnchor.anchor.rect = widgetRect;
}
}
Tooltip {
relativeItem: delegate.containsMouse ? delegate : null
Label {
text: delegate.item.tooltipTitle || delegate.item.id
}
}
}
}
}

View file

@ -0,0 +1,8 @@
import QtQuick
import "../"
BarBlock {
id: text
text: ` ${Datetime.time}`
}

View file

@ -0,0 +1,63 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
import "root:/"
import "../"
RowLayout {
spacing: 0
property HyprlandMonitor monitor: Hyprland.monitorFor(screen)
Repeater {
model: ScriptModel {
values: {
var seenEmpty = false
return [...Hyprland.workspaces.values]
.filter((ws) => {
if (ws.monitor !== monitor || ws.name.includes("special"))
return false
// There is a flickering that can happen when switching from one
// empty workspace to another where both empty workspaces are shown
// on the bar at the same time. This ensures that only the first
// empty workspace is shown.
const isNumeric = /^\d+$/.test(ws.name);
if (!isNumeric)
return true;
if (!seenEmpty) {
seenEmpty = true
return true
}
return false;
})
// Sort workspaces by id
.sort((a, b) => a.id - b.id)
}
}
BarBlock {
property HyprlandWorkspace ws: modelData
property bool isActive: Hyprland.focusedMonitor?.activeWorkspace?.id === ws.id
property bool isOpen: monitor.activeWorkspace?.id === ws.id
property bool hasClients: ws.name.length > 2
dim: true
underline: isActive || isOpen
onClicked: function() {
Hyprland.dispatch(`workspace ${ws.id}`);
}
leftPadding: hasClients ? 2 : 0
text: {
if (isActive) {
if (!hasClients)
return `<span style='color:${fgColor};'>${ws.name}</span>`
var split_i = ws.id > 9 ? 3 : 2
return `<span style='color:${fgColor};'>${ws.name.slice(0, split_i)}</span>${ws.name.slice(split_i)}`
}
return ws.name
}
}
}
}

View file

@ -0,0 +1,8 @@
//@ pragma UseQApplication
import Quickshell
import "bar" as Bar
ShellRoot {
Bar.Bar {}
}