nix: tucked away home configurations

This commit is contained in:
Primrose 2024-07-12 23:26:05 +02:00
parent 6d1844ebf0
commit 5b7839dde9
Signed by: primrose
GPG key ID: 4E887A4CA9714ADA
17 changed files with 3 additions and 3 deletions

View file

@ -0,0 +1,86 @@
{ pkgs, ... }:
let
inherit (pkgs) myPkgs wired;
in
{
home.pointerCursor = {
x11.enable = true;
gtk.enable = true;
name = "Adwaita";
package = pkgs.gnome.adwaita-icon-theme;
size = 32;
};
home.packages = [
# fonts
(pkgs.nerdfonts.override {
fonts = [
"CascadiaCode"
"JetBrainsMono"
"Meslo"
];
})
pkgs.lmodern
pkgs.noto-fonts
pkgs.noto-fonts-lgc-plus
pkgs.noto-fonts-cjk-sans
pkgs.noto-fonts-cjk-serif
pkgs.noto-fonts-color-emoji
pkgs.noto-fonts-emoji-blob-bin
pkgs.hanazono
pkgs.cascadia-code
myPkgs.hiosevka-nerd-font-mono
myPkgs.hiosevka
# Window Manager related
pkgs.dmenu
pkgs.xmobar
pkgs.scrot
pkgs.xclip
pkgs.feh
pkgs.xscreensaver # TODO: why the service option won't work ?
wired
pkgs.playerctl
# GUI apps
# social
pkgs.discord
pkgs.element-desktop
pkgs.mattermost-desktop
# productivity
pkgs.bitwarden
pkgs.sioyek
pkgs.evince
pkgs.gnome.eog
pkgs.gnome.nautilus
pkgs.gnome.sushi
pkgs.evolution
pkgs.gnome.gnome-calendar
pkgs.p7zip
];
programs.kitty.enable = true;
home.file = {
xmonad = {
recursive = true;
source = ./xmonad;
target = ".config/xmonad";
};
xmobar = {
recursive = true;
source = ./xmobar;
target = ".config/xmobar";
};
wired = {
recursive = true;
source = ./wired;
target = ".config/wired";
};
xscreensaver = {
source = ./xscreensaver/.xscreensaver;
target = ".xscreensaver";
};
};
}

View file

@ -0,0 +1,175 @@
(
// Maximum number of notifications to show at any one time.
// A value of 0 means that there is no limit.
max_notifications: 0,
// The default timeout, in miliseconds, for notifications that don't have an initial timeout set.
// 1000ms = 1s.
timeout: 10000,
// `poll_interval` decides decides how often (in milliseconds) Wired checks events,
// draws notifications (if necessary) -- the update loop while any notification is present.
// Note that when no notifications are present, Wired polls at `idle_poll_interval` instead.
// 16ms ~= 60hz / 7ms ~= 144hz.
poll_interval: 16,
// The interval at which wired updates when no notifications/windows are present.
//idle_poll_interval: 500,
// Wired will pause notifications if you are idle (no mouse or keyboard input) for longer than
// `idle_threshold` seconds.
// Note that notifications will not be automatically unpaused on wake, and will need to be manually
// cleared, unless `unpause_on_input` is set to true.
// Also note that no distinction is made between manually paused and idle paused notifications.
// If `idle_threshold` is not specified, the behavior will be disabled entirely.
//idle_threshold: 3600,
// Notifications will spawn paused, and have to be manually unpaused or cleared by the user,
// unless `unpause_on_input` is also set.
//notifications_spawn_paused: false,
// Unpause notifications when we receive any input after being idle for longer than 1 second.
// Note that no distinction is made between manually paused notifications and idle paused/spawned notifications.
//unpause_on_input: false,
// Enable/disable replacement functionality.
// If this is disabled, replacement requests will just send a new notification.
// E.g., with replacing_enabled: true, Pidgin will only show the latest message from each contact,
// instead of sending a new one for each message.
// Default: true
//replacing_enabled: true,
// Whether a notification should reset its timeout when it is replaced.
// No effect if replacing_enabled is set to false.
// Default: false
//replacing_resets_timeout: false,
// Some apps/programs close notifications on their own by sending a request to dbus.
// Sometimes this is not desired.
// Default: true
//closing_enabled: true,
// How many notifications are kept in history.
// Each notification is roughly 256 bytes (excluding buffers!), so there's some math to do here.
// Default: 10
//history_length: 10,
// When a `NotificationBlock` has monitorr: -1 (i.e. should follow active monitor), then what input
// should we use to determine the active monitor?
// Options: Mouse, Window
// Default: Mouse
//focus_follows: Mouse,
// Enable printing notification data to a file.
// Useful for scripting purposes.
// The data is written as JSON.
// Default: None
//print_to_file: "/tmp/wired.log",
// Minimum window width and height. This is used to create the base rect that the notification
// grows within.
// The notification window will never be smaller than this.
// A value of 1 means that the window will generally always resize with notification, unless
// you have a 1x1 pixel notification...
// Generally, you shouldn't need to set this.
//min_window_width: 1,
//min_window_height: 1,
// Enable/disable debug rendering.
debug: false,
debug_color: Color(r: 0.0, g: 1.0, b: 0.0, a: 1.0), // Primary color for debug rectangles.
debug_color_alt: Color(r: 1.0, g: 0.0, b: 0.0, a: 1.0), // Secondary color for debug rectangles.
layout_blocks: [
// Layout 1, when an image is present.
(
name: "root",
parent: "",
hook: Hook(parent_anchor: TL, self_anchor: TL),
offset: Vec2(x: 7.0, y: 7.0),
//render_criteria: [HintImage],
// https://github.com/Toqozz/wired-notify/wiki/NotificationBlock
params: NotificationBlock((
monitor: 0,
border_width: 3.0,
border_rounding: 3.0,
//background_color: Color(r: 0.15686, g: 0.15686, b: 0.15686, a: 1.0),
background_color: Color(hex: "#282828"),
border_color: Color(hex: "#ebdbb2"),
border_color_low: Color(hex: "#282828"),
border_color_critical: Color(hex: "#fb4934"),
border_color_paused: Color(hex: "#fabd2f"),
gap: Vec2(x: 0.0, y: 8.0),
notification_hook: Hook(parent_anchor: BL, self_anchor: TL),
)),
),
(
name: "image",
parent: "root",
hook: Hook(parent_anchor: TL, self_anchor: TL),
offset: Vec2(x: 0.0, y: 0.0),
// https://github.com/Toqozz/wired-notify/wiki/ImageBlock
params: ImageBlock((
image_type: Hint,
// We actually want 4px padding, but the border is 3px.
padding: Padding(left: 7.0, right: 0.0, top: 7.0, bottom: 7.0),
rounding: 3.0,
scale_width: 48,
scale_height: 48,
filter_mode: Lanczos3,
)),
),
(
name: "summary",
parent: "image",
hook: Hook(parent_anchor: MR, self_anchor: BL),
offset: Vec2(x: 0.0, y: 0.0),
// https://github.com/Toqozz/wired-notify/wiki/TextBlock
params: TextBlock((
text: "%s",
font: "Arial Bold 11",
ellipsize: Middle,
color: Color(hex: "#ebdbb2"),
color_hovered: Color(hex: "#fbf1c7"),
padding: Padding(left: 7.0, right: 7.0, top: 7.0, bottom: 0.0),
dimensions: (width: (min: 50, max: 150), height: (min: 0, max: 0)),
)),
),
(
name: "body",
parent: "summary",
hook: Hook(parent_anchor: BL, self_anchor: TL),
offset: Vec2(x: 0.0, y: -3.0),
// https://github.com/Toqozz/wired-notify/wiki/ScrollingTextBlock
params: ScrollingTextBlock((
text: "%b",
font: "Arial 11",
color: Color(hex: "#ebdbb2"),
color_hovered: Color(hex: "#fbf1c7"),
padding: Padding(left: 7.0, right: 7.0, top: 3.0, bottom: 7.0),
width: (min: 150, max: 250),
scroll_speed: 0.1,
lhs_dist: 35.0,
rhs_dist: 35.0,
scroll_t: 1.0,
)),
),
],
// https://github.com/Toqozz/wired-notify/wiki/Shortcuts
shortcuts: ShortcutsConfig (
notification_interact: 1,
notification_close: 2,
// notification_closeall: 99,
// notification_pause: 99,
notification_action1: 3,
// notification_action2: 99,
// notification_action3: 99,
// notification_action4: 99,
),
)

View file

@ -0,0 +1,37 @@
-- vim:et:sw=2:ts=2:ft=haskell
Config { overrideRedirect = False
, font = "xft:JetBrainsMono NF"
, bgColor = "#000000"
, fgColor = "#FFFFFF"
, position = TopW L 100
, commands = [ Run Kbd
[ ("myDvorakFrench", "🇫🇷")
, ("myDvorak", "🇺🇸")
, ("us", "🇹🇼")
]
, Run ThermalZone 0 ["-t", "󰔏 <temp>°C"] 30
, Run Alsa "default" "Master"
[ "-t", "<status> <volume>%"
, "--"
, "-O", "󰕾"
, "-o", "󰖁"
]
, Run Memory [ "-t", "󰍛 <usedratio>%" ] 30
, Run Date "%a %d %H:%M:%S" "date" 10
, Run Battery
[ "-t", "<acstatus>:<left>%"
, "--"
, "-O", "󰂄"
, "-i", "󱟦"
, "-o", "󰁾"
, "-h", "green"
, "-m", "yell"
, "-l", "red"
] 10
, Run XMonadLog
]
, sepChar = "%"
, alignSep = "}{"
, template = "%XMonadLog% }{ %kbd% | %alsa:default:Master% | %thermal0% | %memory% | %battery% | %date% "
}

View file

@ -0,0 +1 @@
use flake

View file

@ -0,0 +1,290 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
import XMonad hiding (tile)
import XMonad.Actions.PerWindowKeys (bindFirst)
import XMonad.Util.EZConfig (additionalKeys, removeKeys)
import XMonad.Util.NamedScratchpad (NamedScratchpad (NS),
customFloating,
namedScratchpadAction,
namedScratchpadManageHook,
scratchpadWorkspaceTag)
import XMonad.Util.Paste (sendKey)
import XMonad.Util.SpawnOnce (spawnOnce)
import XMonad.Layout.NoBorders (Ambiguity (OnlyScreenFloat),
lessBorders)
import XMonad.Layout.Reflect (reflectHoriz, reflectVert)
import XMonad.Layout.Renamed (Rename (Replace), renamed)
import XMonad.Layout.Spacing (spacingWithEdge)
import XMonad.Hooks.DynamicLog (PP (ppCurrent, ppHiddenNoWindows, ppSep),
filterOutWsPP, wrap, xmobarColor)
import XMonad.Hooks.EwmhDesktops (ewmh, ewmhFullscreen)
import XMonad.Hooks.StatusBar (defToggleStrutsKey,
statusBarProp, withEasySB)
import XMonad.Hooks.StatusBar.PP (PP (ppCurrent, ppHiddenNoWindows, ppSep),
filterOutWsPP, wrap, xmobarColor)
import Graphics.X11.ExtraTypes.XF86 (xF86XK_AudioLowerVolume,
xF86XK_AudioMute,
xF86XK_AudioNext,
xF86XK_AudioPlay,
xF86XK_AudioPrev,
xF86XK_AudioRaiseVolume,
xF86XK_Display,
xF86XK_MonBrightnessDown,
xF86XK_MonBrightnessUp)
import qualified XMonad.StackSet as W
import Control.Monad (msum)
import Data.Ratio (Ratio, (%))
import qualified Data.Text as T
import NeatInterpolation (text)
xmonadConfig = def
{ modMask = myMod
, terminal = myTerm
, focusFollowsMouse = True
, borderWidth = 5
, workspaces = myWorkspaces
, manageHook = myManageHook
, layoutHook = myLayoutHook
, startupHook = myStartupHook
, normalBorderColor = "#18005f"
, focusedBorderColor = "#875fff"
}
`removeKeys` myUnmaps
`additionalKeys` myKeymaps
myTerm = "kitty"
myMod = mod4Mask
myWorkspaces =
[ "CODE", "CHAT", "REC", "UNIV"
, "PERS", "WEB" , "YT", "ADM"
]
data TallR a = TallR { tallNMaster :: !Int -- ^ The default number of windows in the master pane (default: 1)
, tallRatioIncrement :: !Rational -- ^ Percent of screen to increment by when resizing panes (default: 3/100)
, tallRatio :: !Rational -- ^ Default proportion of screen occupied by master pane (default: 1/2)
}
deriving (Show, Read)
instance LayoutClass TallR a where
description _ = "Tall"
pureLayout (TallR nmaster _ frac) r s = zip ws rs
where ws = W.integrate s
rs = tile frac r nmaster (length ws)
pureMessage (TallR nmaster delta frac) m =
msum [fmap resize (fromMessage m)
,fmap incmastern (fromMessage m)]
where resize Shrink = TallR nmaster delta (max 0 $ frac-delta)
resize Expand = TallR nmaster delta (min 1 $ frac+delta)
incmastern (IncMasterN d) = TallR (max 0 (nmaster+d)) delta frac
-- A modified verison of the built-in `tile` function
-- that puts master on the right
tile
:: Rational -- ^ @frac@, what proportion of the screen to devote to the master area
-> Rectangle -- ^ @r@, the rectangle representing the screen
-> Int -- ^ @nmaster@, the number of windows in the master pane
-> Int -- ^ @n@, the total number of windows to tile
-> [Rectangle]
tile f r nmaster n =
if n <= nmaster || nmaster == 0
then splitVertically n r
else
let (r1, r2) = splitHorizontallyBy f r
in splitVertically nmaster r2 ++ splitVertically (n-nmaster) r1
myLayoutHook =
let tall = renamed [Replace "virt"]
. lessBorders OnlyScreenFloat
. spacingWithEdge 5
$ TallR 1 (3/100) (1/2)
full = renamed [Replace "full"]
. lessBorders OnlyScreenFloat
. spacingWithEdge 5
$ Full
in tall ||| full
centeredFloat = customFloating $ W.RationalRect (1/6) (1/6) (2/3) (2/3)
longFloat = customFloating $ W.RationalRect (2/7) 0 (3/7) 1
myManageHook =
composeAll
[ className =? ".blueman-manager-wrapped" --> centeredFloat
, className =? "Eog" --> centeredFloat
, className =? "Org.gnome.NautilusPreviewer" --> centeredFloat
, className =? "Evince" --> longFloat
, title =? "easyeffects" --> centeredFloat
, title =? "Picture-in-Picture" --> doFloat
, className =? "Element" --> doShift "CHAT"
, className =? "discord" --> doShift "CHAT"
, className =? "thunderbird" --> doShift "CHAT"
, className =? "Mattermost" --> doShift "CHAT"
]
<+> namedScratchpadManageHook myScratchpads
myScratchpads =
[ NS "cmus"
(myTerm ++ " -T 'cmus' cmus")
(title =? "cmus")
centeredFloat
, NS "btop"
(myTerm ++ " -T 'btop' btop")
(title =? "btop")
centeredFloat
, NS "bitwarden"
"bitwarden"
(className =? "Bitwarden")
(customFloating $ W.RationalRect (1/2) (1/6) (2/5) (2/3))
]
-- Only remove mappings that needs pass through.
-- If a new mapping is added, the old one is overridden
myUnmaps =
[ (myMod, xK_h)
, (myMod, xK_l)
]
++ [ (myMod , n) | n <- [xK_1 .. xK_9] ]
++ [ (myMod .|. shiftMask, n) | n <- [xK_1 .. xK_9] ]
myKeymaps =
let remapWithFallback src dst =
let fallback = [ (pure True, uncurry sendKey src) ]
in (src, bindFirst . (++fallback) $ dst)
workspaceKeys =
[ xK_h, xK_t, xK_n, xK_s
, xK_m, xK_w, xK_v, xK_z
]
in [ -- programs
((controlMask .|. myMod, xK_f), spawn "firefox")
, ((controlMask .|. myMod, xK_m), namedScratchpadAction myScratchpads "cmus")
, ((controlMask .|. myMod, xK_p), namedScratchpadAction myScratchpads "bitwarden")
, ((controlMask .|. myMod, xK_h), namedScratchpadAction myScratchpads "btop")
-- TODO: https://libreddit.earth2077.fr/r/xmonad/comments/i1s9do/keybinding_send_key_to_application/
-- screenshot
, ( (mod4Mask .|. shiftMask, xK_3)
, spawn "scrot -F - | xclip -in -selection clipboard -t image/png"
)
, ( (mod4Mask .|. shiftMask, xK_4)
, spawn "scrot -s -F - | xclip -in -selection clipboard -t image/png"
)
, ( (controlMask .|. mod4Mask .|. shiftMask, xK_4)
, spawn "scrot -s"
)
-- toggle external display
, ((0, xF86XK_Display), spawn setupMonitors)
, ((0, xF86XK_MonBrightnessDown), spawn "light -U 5")
, ((0, xF86XK_MonBrightnessUp), spawn "light -A 5")
-- volume adjustments
, ((0, xF86XK_AudioMute), spawn "amixer set Master toggle")
, ((0, xF86XK_AudioLowerVolume), spawn "amixer set Master 5%-")
, ((0, xF86XK_AudioRaiseVolume), spawn "amixer set Master 5%+")
-- playback control
, ((0, xF86XK_AudioPrev), spawn "playerctl previous")
, ((0, xF86XK_AudioPlay), spawn "playerctl play-pause")
, ((0, xF86XK_AudioNext), spawn "playerctl next")
-- Begin / End
, ((mod4Mask, xK_Left), sendKey 0 xK_Home)
, ((mod4Mask, xK_Right), sendKey 0 xK_End)
-- Delete
, ((mod4Mask, xK_BackSpace), sendKey 0 xK_Delete)
-- screensaver / suspend
, ( (controlMask .|. mod4Mask, xK_l)
, spawn "xscreensaver-command -lock"
)
, ( (controlMask .|. mod4Mask, xK_z)
, spawn "xscreensaver-command -lock ; systemctl suspend"
)
, ( (shiftMask .|. controlMask .|. mod4Mask, xK_z)
, spawn "xscreensaver-command -lock ; systemctl hibernate"
)
-- tab navigation in firefox
, remapWithFallback
(controlMask .|. shiftMask, xK_bracketright)
[ (className =? "firefox", sendKey controlMask xK_Tab) ]
, remapWithFallback
(controlMask .|. shiftMask, xK_bracketleft)
[ (className =? "firefox", sendKey (controlMask .|. shiftMask) xK_Tab) ]
-- resize windows
, ((myMod .|. shiftMask, xK_comma) , sendMessage Shrink)
, ((myMod .|. shiftMask, xK_period), sendMessage Expand)
-- Increment / decrement the number of windows in the master area
, ((myMod ,xK_comma ), sendMessage (IncMasterN (-1)))
, ((myMod ,xK_period), sendMessage (IncMasterN 1))
-- sink
, ((myMod .|. shiftMask, xK_s), withFocused $ windows . W.sink)
]
-- organic window jumping
++ [ ((myMod, n), windows $ W.greedyView space)
| (n, space) <- zip workspaceKeys myWorkspaces ]
-- organic window yeeting
++ [ ((myMod .|. mod1Mask, n), windows $ W.shift space)
| (n, space) <- zip workspaceKeys myWorkspaces ]
myPrettyPrinter =
filterOutWsPP [scratchpadWorkspaceTag]
$ def
{ ppCurrent = xmobarColor "#FFFFFF" "" . wrap "[" "]"
, ppHiddenNoWindows = xmobarColor "#9c9c9c" ""
, ppSep = " | "
}
setupMonitors = T.unpack
[text|
if xrandr --output DP-1 --left-of eDP-1 --mode 2560x1440 --rate 59.94; then
xrandr --output eDP-1 --off
else
xrandr --auto
fi
|]
setupXmobar = T.unpack
[text|
xmobar -x 0 ~/.config/xmobar/xmobarrc
xmobar -x 1 ~/.config/xmobar/xmobarrc
|]
myStartupHook = do
spawnOnce setupMonitors -- External display hack
spawnOnce "pgrep fcitx5 || fcitx5 &" -- Input method
spawnOnce "pgrep xscreensaver || xscreensaver --no-splash &" -- Screensaver
spawnOnce "pgrep playerctld || playerctld daemon" -- Player controller
spawnOnce "pgrep wired || wired &" -- Notification daemon
main = xmonad
. ewmhFullscreen . ewmh
. withEasySB
(statusBarProp setupXmobar (pure myPrettyPrinter))
defToggleStrutsKey
$ xmonadConfig
-- vim:et:sw=2:ts=2

View file

@ -0,0 +1,299 @@
# XScreenSaver Preferences File
# Written by xscreensaver-settings 6.08 for leana on Mon Dec 25 21:48:30 2023.
# https://www.jwz.org/xscreensaver/
timeout: 0:10:00
cycle: 0:10:00
lock: False
lockTimeout: 0:00:00
passwdTimeout: 0:00:30
visualID: default
installColormap: True
verbose: False
splash: True
splashDuration: 0:00:05
demoCommand: xscreensaver-settings
nice: 10
fade: False
unfade: False
fadeSeconds: 0:00:03
ignoreUninstalledPrograms:False
dpmsEnabled: False
dpmsQuickOff: False
dpmsStandby: 2:00:00
dpmsSuspend: 2:00:00
dpmsOff: 4:00:00
grabDesktopImages: True
grabVideoFrames: False
chooseRandomImages: False
imageDirectory:
mode: one
selected: 204
textMode: url
textLiteral: XScreenSaver
textFile:
textProgram: fortune
textURL: https://en.wikipedia.org/w/index.php?title=Special:NewPages&feed=rss
dialogTheme: default
settingsGeom: 12,30 1152,30
programs: \
maze --root \n\
GL: superquadrics --root \n\
attraction --root \n\
blitspin --root \n\
greynetic --root \n\
helix --root \n\
hopalong --root \n\
imsmap --root \n\
- noseguy --root \n\
- pyro --root \n\
qix --root \n\
- rocks --root \n\
rorschach --root \n\
decayscreen --root \n\
flame --root \n\
halo --root \n\
slidescreen --root \n\
pedal --root \n\
bouboule --root \n\
- braid --root \n\
coral --root \n\
deco --root \n\
drift --root \n\
- fadeplot --root \n\
galaxy --root \n\
goop --root \n\
grav --root \n\
ifs --root \n\
GL: jigsaw --root \n\
julia --root \n\
- kaleidescope --root \n\
GL: moebius --root \n\
moire --root \n\
GL: morph3d --root \n\
mountain --root \n\
munch --root \n\
penrose --root \n\
GL: pipes --root \n\
rdbomb --root \n\
GL: rubik --root \n\
- sierpinski --root \n\
slip --root \n\
GL: sproingies --root \n\
starfish --root \n\
strange --root \n\
swirl --root \n\
triangle --root \n\
xjack --root \n\
xlyap --root \n\
GL: atlantis --root \n\
bsod --root \n\
GL: bubble3d --root \n\
GL: cage --root \n\
- crystal --root \n\
cynosure --root \n\
discrete --root \n\
distort --root \n\
epicycle --root \n\
flow --root \n\
GL: glplanet --root \n\
interference --root \n\
kumppa --root \n\
GL: lament --root \n\
moire2 --root \n\
GL: sonar --root \n\
GL: stairs --root \n\
truchet --root \n\
- vidwhacker --root \n\
- webcollage --root \n\
blaster --root \n\
bumps --root \n\
ccurve --root \n\
compass --root \n\
deluxe --root \n\
- demon --root \n\
GL: extrusion --root \n\
- loop --root \n\
penetrate --root \n\
petri --root \n\
phosphor --root \n\
GL: pulsar --root \n\
ripples --root \n\
shadebobs --root \n\
GL: sierpinski3d --root \n\
spotlight --root \n\
squiral --root \n\
wander --root \n\
xflame --root \n\
xmatrix --root \n\
GL: gflux --root \n\
- nerverot --root \n\
xrayswarm --root \n\
xspirograph --root \n\
GL: circuit --root \n\
GL: dangerball --root \n\
- GL: dnalogo --root \n\
GL: engine --root \n\
GL: flipscreen3d --root \n\
GL: gltext --root \n\
GL: menger --root \n\
GL: molecule --root \n\
rotzoomer --root \n\
scooter --root \n\
speedmine --root \n\
GL: starwars --root \n\
GL: stonerview --root \n\
vermiculate --root \n\
whirlwindwarp --root \n\
zoom --root \n\
anemone --root \n\
apollonian --root \n\
GL: boxed --root \n\
GL: cubenetic --root \n\
GL: endgame --root \n\
euler2d --root \n\
fluidballs --root \n\
GL: flurry --root \n\
- GL: glblur --root \n\
GL: glsnake --root \n\
halftone --root \n\
GL: juggler3d --root \n\
GL: lavalite --root \n\
- polyominoes --root \n\
GL: queens --root \n\
- GL: sballs --root \n\
GL: spheremonics --root \n\
twang --root \n\
- GL: antspotlight --root \n\
apple2 --root \n\
GL: atunnel --root \n\
barcode --root \n\
GL: blinkbox --root \n\
GL: blocktube --root \n\
GL: bouncingcow --root \n\
cloudlife --root \n\
GL: cubestorm --root \n\
eruption --root \n\
GL: flipflop --root \n\
GL: flyingtoasters --root \n\
fontglide --root \n\
GL: gleidescope --root \n\
GL: glknots --root \n\
GL: glmatrix --root \n\
- GL: glslideshow --root \n\
GL: hypertorus --root \n\
- GL: jigglypuff --root \n\
metaballs --root \n\
GL: mirrorblob --root \n\
piecewise --root \n\
GL: polytopes --root \n\
pong --root \n\
popsquares --root \n\
GL: surfaces --root \n\
xanalogtv --root \n\
abstractile --root \n\
anemotaxis --root \n\
- GL: antinspect --root \n\
fireworkx --root \n\
fuzzyflakes --root \n\
interaggregate --root \n\
intermomentary --root \n\
memscroller --root \n\
GL: noof --root \n\
pacman --root \n\
GL: pinion --root \n\
GL: polyhedra --root \n\
- GL: providence --root \n\
substrate --root \n\
wormhole --root \n\
- GL: antmaze --root \n\
GL: boing --root \n\
boxfit --root \n\
GL: carousel --root \n\
celtic --root \n\
GL: crackberg --root \n\
GL: cube21 --root \n\
fiberlamp --root \n\
GL: fliptext --root \n\
GL: glhanoi --root \n\
GL: tangram --root \n\
GL: timetunnel --root \n\
GL: glschool --root \n\
GL: topblock --root \n\
GL: cubicgrid --root \n\
cwaves --root \n\
GL: gears --root \n\
GL: glcells --root \n\
GL: lockward --root \n\
m6502 --root \n\
GL: moebiusgears --root \n\
GL: voronoi --root \n\
GL: hypnowheel --root \n\
GL: klein --root \n\
- lcdscrub --root \n\
GL: photopile --root \n\
GL: skytentacles --root \n\
GL: rubikblocks --root \n\
GL: companioncube --root \n\
GL: hilbert --root \n\
GL: tronbit --root \n\
GL: geodesic --root \n\
hexadrop --root \n\
GL: kaleidocycle --root \n\
GL: quasicrystal --root \n\
GL: unknownpleasures --root \n\
binaryring --root \n\
GL: cityflow --root \n\
GL: geodesicgears --root \n\
GL: projectiveplane --root \n\
GL: romanboy --root \n\
tessellimage --root \n\
GL: winduprobot --root \n\
GL: splitflap --root \n\
GL: cubestack --root \n\
GL: cubetwist --root \n\
GL: discoball --root \n\
GL: dymaxionmap --root \n\
GL: energystream --root \n\
GL: hexstrut --root \n\
GL: hydrostat --root \n\
GL: raverhoop --root \n\
GL: splodesic --root \n\
GL: unicrud --root \n\
GL: esper --root \n\
GL: vigilance --root \n\
GL: crumbler --root \n\
filmleader --root \n\
glitchpeg --root \n\
GL: handsy --root \n\
GL: maze3d --root \n\
GL: peepers --root \n\
GL: razzledazzle --root \n\
vfeedback --root \n\
GL: deepstars --root \n\
GL: gravitywell --root \n\
GL: beats --root \n\
GL: covid19 --root \n\
GL: etruscanvenus --root \n\
GL: gibson --root \n\
GL: headroom --root \n\
GL: sphereeversion --root \n\
binaryhorizon --root \n\
marbling --root \n\
GL: chompytower --root \n\
GL: hextrail --root \n\
GL: mapscroller --root \n\
GL: nakagin --root \n\
GL: squirtorus --root \n\
GL: cubocteversion --root \n\
droste --root \n\
GL: papercube --root \n\
GL: skulloop --root \n\
pointerHysteresis: 10
authWarningSlack: 20