ref(nix): reworked flake entry point

This commit is contained in:
Léana 江 2024-02-26 17:03:14 +01:00 committed by Léana 江
parent a5c009f77c
commit 377150ddd2
19 changed files with 46 additions and 29 deletions

View file

@ -0,0 +1,115 @@
{
pkgs,
wired,
...
}: {
home.pointerCursor = {
x11.enable = true;
gtk.enable = true;
name = "Adwaita";
package = pkgs.gnome.adwaita-icon-theme;
size = 32;
};
home.packages = with pkgs; [
# fonts
(nerdfonts.override {fonts = ["CascadiaCode" "JetBrainsMono" "Meslo"];})
lmodern
noto-fonts
noto-fonts-lgc-plus
noto-fonts-cjk-sans
noto-fonts-cjk-serif
noto-fonts-color-emoji
noto-fonts-emoji-blob-bin
hanazono
cascadia-code
# Window Manager related
dmenu
xmobar
scrot
xclip
feh
xscreensaver # TODO: why the service option won't work ?
wired.default
playerctl
# GUI apps
# social
discord
element-desktop
mattermost-desktop
# productivity
bitwarden
sioyek
evince
gnome.eog
gnome.nautilus
gnome.sushi
evolution
gnome.gnome-calendar
p7zip
];
programs.kitty = {
enable = true;
font = {
name = "CaskaydiaCove Nerd Font Mono";
size = 18;
};
settings = {
foreground = "#000000";
background = "#ffffff";
confirm_os_window_close = 0;
text_composition_strategy = "1.55 0";
shell = "${pkgs.fish}/bin/fish -c tmux_home";
};
extraConfig = ''
background #f8f8f8
foreground #2a2b33
cursor #bbbbbb
selection_background #ececec
color0 #000000
color8 #000000
color1 #ca1243
color9 #ca1243
color2 #50a14f
color10 #50a14f
color3 #e5bf6d
color11 #e5bf6d
color4 #4078f2
color12 #4078f2
color5 #950095
color13 #a00095
color6 #0184bc
color14 #0184bc
color7 #bbbbbb
color15 #ffffff
selection_foreground #f8f8f8
'';
shellIntegration.enableFishIntegration = 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

61
nix/home/carbon/gui/xmonad/flake.lock generated Normal file
View file

@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1704295289,
"narHash": "sha256-9WZDRfpMqCYL6g/HNWVvXF0hxdaAgwgIGeLYiOhmes8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b0b2c5445c64191fd8d0b31f2b1a34e45a64547d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -0,0 +1,33 @@
{
description = ''
Bring XMonad library to $PATH for the language server to work
'';
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
};
outputs = {
self,
nixpkgs,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShell = pkgs.mkShell {
packages = [
(pkgs.haskell.packages.ghc947.ghcWithPackages (hpkgs:
with hpkgs; [
haskell-language-server
stylish-haskell
xmonad
xmonad-contrib
neat-interpolation
]))
];
};
});
}

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