dot

vizie's NixOS desktop: Hyprland, CachyOS kernel and gaming tweaks

68 lines3022 bytesexecutable
1#!/usr/bin/env bash
2# Apps opened at login. Run once per login by autostart-apps.service (see
3# modules/home/services.nix), after Waybar, so the tray exists.
4#
5# OpenDeck, WowUp to the tray
6# Faugus its window on workspace 1
7# Signal, Discord workspace 3, Signal on top and Discord below it
8#
9# Which workspace a window lands on (and Faugus' position) is decided by the
10# temporary "startup-*" window rules in startup.lua, which also closes the window
11# WowUp opens. This script starts the apps and then stacks Signal
12# above Discord. Apps that are already running are left alone, so it is safe to run
13# again by hand.
14
15SIGNAL_HEIGHT=802 # px; Discord gets the rest of the (portrait) monitor
16
17running() { pgrep -f "$1" >/dev/null 2>&1; }
18# Each app is started as its own systemd service (app-*.service), with systemd as
19# its parent rather than this script: Discord and WowUp run in a bubblewrap
20# sandbox that exits with its parent process, so they would close as soon as
21# this script finished. `systemctl --user list-units 'app-*'` shows them.
22launch() { uwsm app -t service -- "$@" >/dev/null 2>&1; }
23dispatch() { hyprctl dispatch "$1" >/dev/null 2>&1; }
24
25# Tray apps only show an icon if the tray already exists when they start.
26for _ in $(seq 40); do
27 busctl --user status org.kde.StatusNotifierWatcher >/dev/null 2>&1 && break
28 sleep 0.5
29done
30
31# OpenDeck starts hidden with its flag. WowUp has one too but shows its window
32# anyway; startup.lua closes that window (see "startup-wowup" there).
33running '(^|/)\.?opendeck(-wrapped)? ' || launch opendeck --hide
34running 'wowup-cf' || launch wowup-cf --hidden
35running 'faugus\.(launcher|tray_only)' || launch faugus-launcher
36running 'signal-desktop.*/app\.asar' || launch signal-desktop # themed, see pkgs/signal-desktop-themed
37running '/Discord( |$)' || launch discord
38
39# --- Stack Signal above Discord ------------------------------------------------
40
41# Prints "address y width height" of the first mapped, tiled window whose class is $1,
42# ignoring small ones (Discord's updater splash).
43window() {
44 hyprctl clients -j | python3 -c '
45import json, sys
46for c in json.load(sys.stdin):
47 if c["class"] == sys.argv[1] and c.get("mapped", True) and not c["floating"] and c["size"][0] > 500:
48 print(c["address"], c["at"][1], c["size"][0], c["size"][1])
49 break
50' "$1"
51}
52
53for _ in $(seq 180); do
54 read -r signal_addr signal_y signal_w signal_h <<<"$(window signal)"
55 read -r discord_addr discord_y _ _ <<<"$(window discord)"
56 [ -n "$signal_addr" ] && [ -n "$discord_addr" ] && break
57 sleep 0.5
58done
59[ -n "$signal_addr" ] && [ -n "$discord_addr" ] || exit 0
60
61if [ "$signal_y" -gt "$discord_y" ]; then
62 dispatch "hl.dsp.window.move({ direction = \"u\", window = \"address:$signal_addr\" })"
63 sleep 0.3
64 read -r signal_addr signal_y signal_w signal_h <<<"$(window signal)"
65fi
66if [ "$signal_h" != "$SIGNAL_HEIGHT" ]; then
67 dispatch "hl.dsp.window.resize({ x = $signal_w, y = $SIGNAL_HEIGHT, window = \"address:$signal_addr\" })"
68fi