Compare commits

..
Author SHA1 Message Date
1c3bb35bde
Set default volume and brightness at login
Add three `systemd` user units that reset
volume, screen brightness, and keyboard backlight,
so that every session starts from a known state.

Values come from ~/.config/environment.d/50-defaults.conf,
and can be overridden per machine via an untracked 90-local.conf
2026-10-07 13:01:51 +02:00
f305c573c7
Set up xcape ...
... to enable us to use Caps Lock as another Excape key
2026-10-07 13:01:51 +02:00
417ed15f47
Adjust locale settings for local usage 2026-10-07 13:01:51 +02:00
734e5e4c73
Add xdg-terminals.list 2026-10-06 13:36:45 +02:00
e18754a3ee
Add mimeapps.list 2026-10-06 13:36:45 +02:00
Alexander
4229888d43
Add gdm-settings-sync utility ...
... that syncs `dconf` settings of the local user
to `gdm3`, the main login window after boot
2026-10-06 13:36:45 +02:00
244af260a4
Add our colors to fastfetch 2026-10-06 13:36:44 +02:00
ac6bda082e
Add aliases for easier xcliping 2026-10-06 13:36:44 +02:00
4a951e0438
Add aliases for ageing 2026-10-06 13:36:44 +02:00
b85c3e8f9a
Add configuration for rofi 2026-10-06 13:36:43 +02:00
1bf78f47cd
Add configuration for alacritty 2026-10-06 13:36:43 +02:00
86cce2d9cf
Remove the forge "unfocused-border" patch
The patch rewrote forge's window.js with `sed`/`awk` anchored on
exact upstream lines, making it the most fragile piece of the
repository, for a purely cosmetic hairline on unfocused windows.

This also simplifies a future migration away from forge.
2026-10-06 13:36:43 +02:00
ff5713a91a
Remove archived GNOME extension configs 2026-10-06 13:36:43 +02:00
0f94baacaf
Add (un-)mount ~/Vault toggle 2026-10-06 13:36:42 +02:00
7804080953
Add configuration for GNOME 2026-10-06 13:36:42 +02:00
46b9bacd18
Add desktop branch ...
... that assumes a running GNOME on X11
2026-10-06 13:36:42 +02:00
74 changed files with 7795 additions and 80 deletions

View file

@ -11,6 +11,40 @@ complete -W '--force' dotfiles-install dotfiles-update
complete -W '--quieter' generate-shell-completions
_color_palette() {
local cur="$2" prev="$3"
local flags='--scheme --show --write'
# Values for `--scheme`, in both the "--scheme value"
# and the "--scheme=value" form
case "$prev" in
--scheme)
mapfile -t COMPREPLY < <(compgen -W 'dark light' -- "$cur")
return
;;
=)
if [ "${COMP_WORDS[COMP_CWORD - 2]}" = "--scheme" ]; then
mapfile -t COMPREPLY < <(compgen -W 'dark light' -- "$cur")
return
fi
;;
esac
# Offer only flags not already on the line
local flag remaining=''
for flag in $flags; do
case " ${COMP_WORDS[*]} " in
*" $flag "*) ;;
*) remaining="$remaining $flag" ;;
esac
done
mapfile -t COMPREPLY < <(compgen -W "$remaining" -- "$cur")
}
complete -F _color_palette color-palette
# Fuzzy completion with the `**` trigger
# (e.g., `vi **<Tab>`, `ssh **<Tab>`)
#

View file

@ -0,0 +1,8 @@
# Nextcloud-related Configurations
This folder contains
the [sync exclude list](./sync-exclude.lst)
for the [Nextcloud](https://nextcloud.com/) client.
The client's other files here (e.g., `nextcloud.cfg`) are untracked
and re-created by [`nextcloud-restore`](../../.local/bin/nextcloud-restore).

View file

@ -0,0 +1,50 @@
# Global exclude patterns
*~
~$*
.~lock.*
~*.tmp
]*.~*
]Icon\r*
].DS_Store
].ds_store
*.textClipping
._*
]Thumbs.db
]photothumb.db
System Volume Information
.*.sw?
.*.*sw?
].TemporaryItems
].Trashes
].DocumentRevisions-V100
].Trash-*
.fseventd
.apdisk
.Spotlight-V100
.directory
*.part
*.filepart
*.crdownload
*.kate-swp
*.gnucash.tmp-*
.synkron.*
.sync.ffs_db
.symform
.symform-store
.fuse_hidden*
*.unison
.nfs*
# syncthing
.stfolder
.stignore
.stversions
*.sb-*

View file

@ -0,0 +1,8 @@
# `alacritty`-related Configurations
This folder contains
the [config](./alacritty.toml)
for the [`alacritty`](https://alacritty.org/) terminal.
`colors.toml` is untracked
and written by [`color-palette`](../../.local/bin/color-palette).

View file

@ -0,0 +1,97 @@
[general]
import = ["colors.toml"]
[bell]
animation = "EaseOutSine"
duration = 250
[cursor]
blink_interval = 500
blink_timeout = 0
thickness = 0.1
unfocused_hollow = true
[cursor.style]
blinking = "On"
shape = "Block"
[font]
size = 12.0
[font.bold]
family = "FiraCode Nerd Font"
style = "Bold"
[font.bold_italic]
family = "FiraCode Nerd Font"
style = "Semibold"
[font.italic]
family = "FiraCode Nerd Font"
style = "Light"
[font.normal]
family = "FiraCode Nerd Font"
style = "Regular"
[font.offset]
x = 0
y = 0
[[keyboard.bindings]]
action = "SpawnNewInstance"
key = "Return"
mods = "Control|Shift"
[scrolling]
history = 99999
multiplier = 10
[terminal.shell]
args = ["-l"]
program = "/usr/bin/zsh"
[window]
decorations = "none"
dynamic_padding = true
opacity = 0.90
[window.padding]
x = 10
y = 10

View file

@ -0,0 +1,19 @@
# Session defaults, read by `systemd --user` at login
#
# Applied by:
# - set-brightness-default.service
# - set-keyboard-brightness-default.service
# - set-volume-default.service
#
# For machine-local overrides create an untracked
# ~/.config/environment.d/90-local.conf instead
# and repeat only the keys you want to change
#
# Apply with: `systemctl --user daemon-reload`,
# then log out and back in
#
# Verify with: `systemctl --user show-environment`
DEFAULT_BRIGHTNESS=30
DEFAULT_KEYBOARD_BRIGHTNESS=50
DEFAULT_VOLUME=30

View file

@ -0,0 +1,6 @@
# Session Environment Defaults
This folder contains environment variables
read by `systemd --user` at login.
Machine-local overrides go into an untracked `90-local.conf`.

View file

@ -1,5 +1,7 @@
# `fastfetch`-related Configurations
This folder contains
the [config](./config.jsonc)
This folder contains configurations
for [`fastfetch`](https://github.com/fastfetch-cli/fastfetch).
`config.jsonc` is untracked
and written by [`color-palette`](../../.local/bin/color-palette).

View file

@ -1,47 +0,0 @@
// Config for `fastfetch`
//
// See: https://github.com/fastfetch-cli/fastfetch
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"type": "small",
"padding": {
"top": 1,
"right": 4
}
},
"display": {
"separator": " ",
"key": {
"width": 12
}
},
"modules": [
"title",
"separator",
"os",
"kernel",
"uptime",
"packages",
"shell",
"break",
"cpu",
"memory",
{
"type": "disk",
"folders": "/"
},
"localip",
"break",
"colors"
]
}

7
.config/forge/README.md Normal file
View file

@ -0,0 +1,7 @@
# Forge-related Configurations
This folder contains settings
for the [Forge GNOME shell extension](https://extensions.gnome.org/extension/4481/forge/).
`~/.config/forge/stylesheet/forge/stylesheet.css` is untracked
and written by [`color-palette`](../../.local/bin/color-palette).

View file

@ -0,0 +1,136 @@
{
"overrides": [
{
"wmClass": "Ibus-ui-emojier",
"mode": "float"
},
{
"wmClass": "Nextcloud",
"mode": "float"
},
{
"wmClass": "org.gnome.Shell.Extensions",
"wmTitle": "Forge Settings",
"mode": "float"
},
{
"wmClass": "jetbrains-toolbox",
"mode": "float"
},
{
"wmClass": "jetbrains-goland",
"wmTitle": "splash",
"mode": "float"
},
{
"wmClass": "jetbrains-webstorm",
"wmTitle": "splash",
"mode": "float"
},
{
"wmClass": "jetbrains-phpstorm",
"wmTitle": "splash",
"mode": "float"
},
{
"wmClass": "jetbrains-datagrip",
"wmTitle": "splash",
"mode": "float"
},
{
"wmClass": "jetbrains-rubymine",
"wmTitle": "splash",
"mode": "float"
},
{
"wmClass": "jetbrains-idea",
"wmTitle": "splash",
"mode": "float"
},
{
"wmClass": "com.github.amezin.ddterm",
"mode": "float"
},
{
"wmClass": "com.github.donadigo.eddy",
"mode": "float"
},
{
"wmClass": "Conky",
"mode": "float"
},
{
"wmClass": "Gnome-initial-setup",
"mode": "float"
},
{
"wmClass": "org.gnome.Calculator",
"mode": "float"
},
{
"wmClass": "gnome-terminal-server",
"wmTitle": "Preferences – General",
"mode": "float"
},
{
"wmClass": "gnome-terminal-preferences",
"mode": "float"
},
{
"wmClass": "Guake",
"mode": "float"
},
{
"wmClass": "zoom",
"mode": "float"
},
{
"wmClass": "firefox",
"wmTitle": "About Mozilla Firefox",
"mode": "float"
},
{
"wmClass": "firefox",
"wmTitle": "!Mozilla Firefox",
"mode": "float"
},
{
"wmClass": "org.mozilla.firefox.desktop",
"wmTitle": "About Mozilla Firefox",
"mode": "float"
},
{
"wmClass": "org.mozilla.firefox.desktop",
"wmTitle": "!Mozilla Firefox",
"mode": "float"
},
{
"wmClass": "thunderbird",
"wmTitle": "About Mozilla Thunderbird",
"mode": "float"
},
{
"wmClass": "thunderbird",
"wmTitle": "!Mozilla Thunderbird",
"mode": "float"
},
{
"wmClass": "org.mozilla.Thunderbird.desktop",
"wmTitle": "About Mozilla Thunderbird",
"mode": "float"
},
{
"wmClass": "org.mozilla.Thunderbird.desktop",
"wmTitle": "!Mozilla Thunderbird",
"mode": "float"
},
{
"wmClass": "evolution-alarm-notify",
"mode": "float"
},
{
"wmClass": "variety",
"mode": "float"
}
]
}

View file

@ -350,6 +350,20 @@ ui = auto
# The named colors below follow the semantic roles defined
# in ~/.config/gnome-settings/COLORS.md:
#
# red errors, failures, deletions
# green success, additions
# yellow warnings, highlights, modifications
# blue information
# magenta special items (e.g., tags, stashes)
# cyan secondary information (e.g., remotes)
#
# The terminals have "bold is bright" turned off,
# so "bold" is only a weight and "bright<color>" is the emphasis shade
[color "branch"]
current = cyan dim bold reverse

View file

@ -0,0 +1,58 @@
# GNOME Settings
This folder contains my GNOME settings
split into several `*.ini` files by logical group.
Machine-specific overrides may live in `local/*.ini` and are loaded last.
See this [README.md](./local/README.md) for details and examples.
All paths inside the files are absolute,
anchored at the root of `dconf`.
Therefore, they must always be loaded anchored at the root as well.
The files are machine independent and use `/home/user` as a placeholder,
which must be rewritten to the real home directory before loading:
```bash
sed "s|/home/user|$HOME|g" <file> | dconf load /
```
[`gnome-restore`](../../.local/bin/gnome-restore) automates this upon every login
(via the `gnome-restore.service` systemd user unit).
Process:
1. Back up the current `dconf` state into ~/.local/state/gnome-settings-backups/
2. On a fresh session, remove the temporary background state
written by [`randomize-background`](../../.local/bin/randomize-background)
3. Reset all managed sub-trees,
so that keys removed from the `*.ini` files do not linger in the live state
4. Patch a broken backup path in the installed `forge` extension (`theme.js`)
5. Ensure the enabled GNOME extensions' schemas are imported
6. Load every `*.ini` here, then every `local/*.ini`
[`dconf-load`](../../.local/bin/dconf-load) captures step 6 as an independent utility,
or for just one file given as an argument,
which is handy while iterating on a single `*.ini`:
```bash
dconf-load key-bindings.ini
```
It neither backs up nor resets anything,
so keys removed from the `*.ini` files stay active until the next `gnome-restore`.
Its purpose is to help during development of the `*.ini` files.
[`dconf-verify`](../../.local/bin/dconf-verify) lists keys diverging
between the live state and the `*.ini` files,
and can be used to find live keys worth adopting.
## Color Palette
`COLORS.md` is an untracked, human-readable overview of the palette,
written by [`color-palette`](../../.local/bin/color-palette).

View file

@ -0,0 +1,463 @@
# Settings for various desktop apps
# Note that configurations for apps no longer in use
# or not yet installed are dragged along here on purpose
[ca/desrt/dconf-editor]
show-warning=false
bookmarks=['/org/gnome/shell/extensions/']
behaviour='safe'
refresh-settings-schema-source=true
small-bookmarks-rows=true
# Always start at dconf's root
restore-view=false
saved-pathbar-path='/'
saved-view='/'
[desktop/ibus/panel]
use-custom-font=true
custom-font='Adwaita Sans 11'
[org/gnome/baobab]
[org/gnome/baobab/ui]
active-chart='rings'
[org/gnome/calculator]
accuracy=12
angle-units='degrees'
base=10
button-mode='basic'
number-format='fixed'
# For exchange rates
refresh-interval=86400
show-thousands=true
show-zeroes=true
source-currency='EUR'
target-currency='USD'
source-units='degree'
target-units='radian'
window-maximized=false
[org/gnome/calendar]
active-view='week'
weather-settings=(true, true, '', @mv nothing)
window-maximized=false
[org/gnome/Characters]
[org/gnome/clocks]
geolocation=true
# Keep in sync with "locations" in [org/gnome/shell/world-clocks]
world-clocks=[{'location': <(uint32 2, <('Phoenix', 'KPHX', true, [(0.58353629681163499, -1.955660817467636)], [(0.58378430809834336, -1.9560609516519483)])>)>}, {'location': <(uint32 2, <('New York', 'KNYC', true, [(0.71180344078725644, -1.2909618758762367)], [(0.71059804659265924, -1.2916478949920254)])>)>}, {'location': <(uint32 2, <('UTC', 'BIRK', true, [(1.1216380205691279, -0.38222710618675809)], [(1.1195629471197465, -0.38251373858977449)])>)>}, {'location': <(uint32 2, <('London', 'EGLL', true, [(0.89845190959903677, -0.0080529408042633736)], [(0.89899290734596930, -0.0021946055346929697)])>)>}, {'location': <(uint32 2, <('Berlin', 'EDDB', true, [(0.91426163401859872, 0.23591034304566436)], [(0.91658875132345297, 0.23387411976724018)])>)>}]
[org/gnome/clocks/state/window]
maximized=false
panel-id='world'
[org/gnome/Connections]
first-run=false
[org/gnome/Contacts]
did-initial-setup=true
sort-on-surname=false
window-fullscreen=false
window-maximized=false
[org/gnome/control-center]
last-panel='system'
[org/gnome/Disks]
[org/gnome/evince]
auto-reload=true
allow-links-change-zoom=false
# Default search path when opening a document
document-directory=@ms nothing
# Last location to save extracted images to
pictures-directory=@ms nothing
# Ignore a PDF's own copy/print prohibitions
override-restrictions=true
# We know what F7 does
show-caret-navigation-message=false
# Make scrolling larger PDFs smoother
page-cache-size=uint32 512
[org/gnome/evince/default]
continuous=true
dual-page=false
dual-page-odd-left=false
enable-spellchecking=true
fullscreen=false
inverted-colors=false
show-sidebar=false
sidebar-size=128
sizing-mode='automatic'
zoom=1.0
[org/gnome/evolution/mail]
use-custom-font=true
monospace-font='FiraCode Nerd Font 12'
variable-width-font='Adwaita Sans 12'
[org/gnome/gedit]
[org/gnome/gedit/plugins/filebrowser]
tree-view=true
[org/gnome/gedit/preferences/ui]
show-tabs-mode='auto'
[org/gnome/gnome-system-monitor]
cpu-smooth-graph=true
cpu-stacked-area-chart=false
disks-interval=1000
graph-update-interval=250
network-in-bits=true
maximized=false
show-all-fs=true
show-dependencies=false
show-whose-processes='user'
update-interval=1000
[org/gnome/Loupe]
# Show the image properties sidebar
show-properties=true
[org/gnome/maps]
map-type='MapsVectorSource'
last-viewed-location=[49.616891519885499, 9.1811720200844604]
zoom-level=13
show-scale=true
transportation-type='car'
[org/gnome/nautilus]
[org/gnome/nautilus/compression]
default-compression-format='zip'
[org/gnome/nautilus/icon-view]
captions=['size', 'none', 'none']
default-zoom-level='large'
[org/gnome/nautilus/list-view]
default-column-order=['name', 'size', 'type', 'owner', 'group', 'permissions', 'where', 'date_modified', 'date_modified_with_time', 'date_accessed', 'recency', 'starred', 'detailed_type']
default-visible-columns=['name', 'size', 'date_modified', 'starred']
default-zoom-level='small'
use-tree-view=true
[org/gnome/nautilus/preferences]
migrated-gtk-settings=true
always-use-location-entry=true
default-folder-viewer='list-view'
search-filter-time-type='last_modified'
show-create-link=false
show-delete-permanently=true
[org/gnome/software]
allow-updates=false
download-updates=false
download-updates-notify=false
enable-repos-dialog=true
show-only-free-apps=false
# `flatpak` authors must be verified
show-only-verified-apps=true
prompt-for-nonfree=false
show-nonfree-ui=true
installed-page-show-size=true
first-run=false
[org/gnome/terminal]
[org/gnome/terminal/legacy]
always-check-default-terminal=false
confirm-close=false
# [org/gnome/terminal/legacy/keybindings]
# See ~/.config/gnome-settings/key-bindings.ini for the key bindings
[org/gnome/terminal/legacy/profiles:]
# Dummy value
default='12345678-1234-5678-9000-123456789000'
list=['12345678-1234-5678-9000-123456789000']
[org/gnome/terminal/legacy/profiles:/:12345678-1234-5678-9000-123456789000]
visible-name='Default Profile'
use-custom-command=true
custom-command='/usr/bin/bash'
login-shell=false
audible-bell=false
use-theme-colors=false
# The 16 ANSI colors come from ~/.config/gnome-settings/COLORS.md,
# generated by ~/.local/bin/color-palette, with these semantic roles:
#
# 1. black chrome tone, "background-like", counterpart of white
# 2. red errors, failures, deletions (e.g., `diff`)
# 3. green success, executables, additions (e.g., `diff`)
# 4. yellow warnings, highlights, modifications (e.g., `diff`)
# 5. blue information, directories
# 6. magenta keywords, constants, special items
# 7. cyan strings, symlinks, secondary information
# 8. white default foreground text
#
# Each color also has a bright shade with the same role but more emphasis
#
# In light mode the bright shades are darker, not lighter,
# because they are solved for contrast against "base", not for luminance
# Fallback values for when theme coloring is turned off
background-color='rgb(252,234,227)'
foreground-color='rgb(42,11,1)'
# Keep in sync with the "Terminal ANSI Colors" table in ~/.config/gnome-settings/COLORS.md
#
# Order as described above, first normal version, then the bright shade of each
palette=['rgb(235,235,237)', 'rgb(177,79,35)', 'rgb(59,121,63)', 'rgb(126,107,24)', 'rgb(39,92,179)', 'rgb(143,77,138)', 'rgb(0,121,121)', 'rgb(42,11,1)', 'rgb(252,108,39)', 'rgb(174,47,0)', 'rgb(0,111,26)', 'rgb(115,92,0)', 'rgb(0,69,190)', 'rgb(138,47,133)', 'rgb(0,106,107)', 'rgb(42,11,1)']
bold-is-bright=false
use-system-font=false
font='FiraCode Nerd Font 11'
[org/gnome/TextEditor]
style-scheme='builder'
use-system-font=false
custom-font='FiraCode Nerd Font 11'
discover-settings=true
highlight-current-line=true
auto-indent=true
indent-style='space'
tab-width=4
wrap-text=false
last-save-directory='file:///home/user'
show-grid=true
show-line-numbers=true
show-map=true
show-right-margin=false
spellcheck=true
restore-session=false
[org/gnome/Totem]
subtitle-font='Adwaita Sans Bold 20'
[org/gnome/tweaks]
show-extensions-notice=false
[org/gnome/Weather]
# Keep in sync with "locations" in [org/gnome/shell/weather]
locations=[<(uint32 2, <('Berlin', 'EDDB', true, [(0.91426163401859872, 0.23591034304566436)], [(0.91658875132345297, 0.23387411976724018)])>)>, <(uint32 2, <('Heidelberg', 'EDFM', true, [(0.86345801419289459, 0.14862448983795826)], [(0.86238428763706787, 0.1517127801361921)])>)>, <(uint32 2, <('London', 'EGLL', true, [(0.89845190959903677, -0.0080529408042633736)], [(0.89899290734596930, -0.0021946055346929697)])>)>, <(uint32 2, <('New York', 'KNYC', true, [(0.71180344078725644, -1.2909618758762367)], [(0.71059804659265924, -1.2916478949920254)])>)>, <(uint32 2, <('Phoenix', 'KPHX', true, [(0.58353629681163499, -1.955660817467636)], [(0.58378430809834336, -1.9560609516519483)])>)>]
[org/gnome/GWeather4]
default-location=('Heidelberg', 'EDFM', @m(dd) nothing)
distance-unit='meters'
pressure-unit='hpa'
speed-unit='kph'
temperature-unit='celsius'
# [org/gtk/*/settings/file-chooser]
# This is the "GTK file-chooser dialog"
[org/gtk/gtk4/settings/file-chooser]
# Keep in sync with [org/gtk/settings/file-chooser]
date-format='regular'
location-mode='path-bar'
show-hidden=false
show-size-column=true
show-type-column=true
sort-column='name'
sort-directories-first=true
sort-order='ascending'
type-format='category'
[org/gtk/settings/file-chooser]
# Keep in sync with [org/gtk/gtk4/settings/file-chooser]
date-format='regular'
location-mode='path-bar'
show-hidden=false
show-size-column=true
show-type-column=true
sort-column='name'
sort-directories-first=true
sort-order='ascending'
type-format='category'
[org/gnome/portal/filechooser]
[org/gnome/portal/filechooser/com.google.Chrome]
last-folder-path='/home/user'

View file

@ -0,0 +1,827 @@
# Unify all key bindings to conveniently keep them consistent
# Target: `i3wm` defaults are the rough spec,
# but with "hjkl" for direction instead of "jkl;"
# and arrows mapped differently than "hjkl"
# => We make GNOME/forge bend to match
#
#--------------------------------------------------------------------------------------------------
# Modifier Layers
#--------------------------------------------------------------------------------------------------
#
# - Everything bound globally lives on <Super>
#
# <Super> + ... Navigate windows and workspaces,
# which includes launching the app we want to get to
#
# <Super><Shift> + ... Move windows within or to another workspace
#
# <Super><Control> + ... Swap and float windows (GNOME/forge only)
# + primary system layer, including
# media, devices, session, power, and some more
#
# <Super><Alt> + ... Grow windows
# + secondary system layer, including
# lights, brightness, and overflow from primary
#
# <Super><Alt><Shift> + ... Shrink windows
# + tertiary layer
#
# Each group may contain a few self-explanatory exceptions
#
# - These layers are never bound globally and stay free for the active app:
#
# <Control> + ...
#
# <Control><Shift> + ... Browser extension shortcuts
#
# <Control><Alt> + ...
#
# <Alt><Shift> + ... Browser extension shortcuts
#
# - F1-F12 are deliberately not bound globally, with a few exceptions,
#
# <Super>F1 to show these key bindings
#
# <Alt>F4 to close windows
#
# F11 to (un-)maximize a window
#
# <Control><Alt>F1-F12 are claimed by the X11 server for switching virtual terminals
#
# - A few exceptions to the layers above are kept on purpose,
# either because a binding is so common that people expect it,
# or because a key already says on its own what it does
#
# - Note that "compose:ralt" in ~/.config/gnome-settings/misc.ini
# turns the right <Alt> key into <Compose>
# => Every <Super><Alt> binding must be pressed with the LEFT <Alt>
#
#------------------------------------------------------------------------------------------------------------------------------------------------
# <Super> Layers
#------------------------------------------------------------------------------------------------------------------------------------------------
#
# - "hjkl" act on windows in the tree
# - arrows act on the "machine"
# - "WS" => "workspace"
# - Rows read from window navigation over launchers to system control,
# with the destructive session & power rows last
#
# | Navigation | Window Management | Primary System | Secondary System | Tertiary System
# | | | | |
# Key(s) | <Super> | <Super><Shift> | <Super><Control> | <Super><Alt> | <Super><Alt><Shift>
# ------------------+------------------------+------------------------+------------------------+------------------------+------------------------
# | Jump to window ... | Move window ... | Swap window with ... | Grow window at ... | Shrink window at ...
# k | ... up | ... up | ... window above | ... top edge | ... bottom edge
# j | ... down | ... down | ... window below | ... bottom edge | ... top edge
# h | ... left | ... left | ... window left | ... left edge | ... right edge
# l | ... right | ... right | ... window right | ... right edge | ... left edge
# | | | | |
# | | | Adjust volume ... | Adjust brightness ... |
# Up | | | ... up | ... up |
# Down | | | ... down | ... down |
# | | | | |
# | | | Play ... | Seek ... |
# Left | | | ... previous track | ... backward |
# Right | | | ... next track | ... forward |
# ------------------+------------------------+------------------------+------------------------+------------------------+------------------------
# m | Evolution | Maximize the window | Mute the volume | Mute the microphone |
# | | | | |
# f | Files (nautilus) | Toggle fullscreen | Toggle float ... | Toggle float ... | Toggle float ...
# | | | ... for the window | ... for the app | ... for entire WS
# | | | | |
# q | | Close the window | | |
# ------------------+------------------------+------------------------+------------------------+------------------------+------------------------
# b | Split beside | | Toggle bluetooth | Randomize wallpaper |
# v | Split below | | (Un-)Mount the ~/Vault | |
# e | Split toggle | | Show battery load | |
# s | Stacked layout | | | |
# w | Tabbed layout | | Toggle WiFi | Toggle airplane mode |
# ------------------+------------------------+------------------------+------------------------+------------------------+------------------------
# grave ~ ` | Toggle last two WS | | Swap last two windows | |
# | | | | |
# n | Jump to first ... | Move window to ... | | |
# | ... empty WS | ... first empty WS | | |
# | | | | |
# | Jump to WS ... | Move window to WS ... | | |
# 1 to 0 | ... No. 1 to 0 | ... No. 1 to 0 | | |
# | | | | Adjust key lights ... |
# comma < , | ... on the left | ... on the left | | ... down |
# period > . | ... on the right | ... on the right | | ... up |
# ------------------+------------------------+------------------------+------------------------+------------------------+------------------------
# slash / ? | GNOME's app drawer | GNOME's search | GNOME's message tray | Toggle key lights | Open quick settings
# | | | | |
# Tab | Show open windows | | | |
# | | | | |
# space | Open the launcher | Run a command | Toggle media playback | |
# | | | | |
# d | Open the launcher | Run a command | | Toggle dark scheme |
# | | | | |
# Return t | Alacritty (zsh) | GNOME Terminal (bash) | | |
# | | | | |
# semicolon : ; | Type an emoji | Copy an emoji | | |
# | | | | |
# i | Firefox | Chromium | Google Chrome | Toggle touchpad |
# ------------------+------------------------+------------------------+------------------------+------------------------+------------------------
# | | | | Make night light ... |
# bracketleft [ | | | | ... cooler |
# bracketright ] | | | | ... warmer |
# | | | | |
# backslash \ | | | | Force night light ... | Turn night light ...
# | | | | ... on/off | ... on/off
# ------------------+------------------------+------------------------+------------------------+------------------------+------------------------
# p | | | Open screenshot UI (1) | Capture the window (1) | Capture the screen (1)
# | | | | |
# r | | | Start screen recording | | Restart GNOME shell
# ------------------+------------------------+------------------------+------------------------+------------------------+------------------------
# Escape | | | Lock screen | Suspend with lock (2) | Hibernate with lock (2)
# | | | | |
# BackSpace Delete | | | Log out | Reboot the machine | Shutdown the machine
# | | | | |
# Home | | | Reboot the machine | |
# | | | | |
# End | | | Shutdown the machine | |
#
# (1) If a machine has a Print key,
# pressing Print (UI), <Alt>Print (Window), and <Shift>Print (Screen)
# also works
# (2) Bound in local/*.ini only, on machines that support it
#
#--------------------------------------------------------------------------------------------------
# Browser extension shortcuts
#--------------------------------------------------------------------------------------------------
#
# - Two in-app layers are used because no single layer is conflict-free:
# + <Control><Shift> dodges Firefox's <Alt> menu accelerators
# and Vimium, which treats <Alt><Shift>letter as the plain shifted letter
# + <Alt><Shift> keeps the c/d mnemonics for Dark Reader
#
# - Set manually, NOT managed by `dconf`:
# + Chrome => chrome://extensions/shortcuts (use scope: "In Chrome")
# + Firefox => about:addons -> gear icon -> "Manage Extension Shortcuts"
#
# - Notes:
# + "compose:ralt" applies here too => Must press with the left <Alt>
# + <Control><Shift>b toggles the bookmarks toolbar in Firefox
# + <Control><Shift>v shadows the browsers' "paste without formatting"
#
# Key | Extension | Action
# ------------------------+----------------+-----------------------------------------------------------------------
# <Control><Shift>l | Bitwarden | Open Bitwarden popup
# <Control><Shift>comma | Bitwarden | Generate & copy password
# <Control><Shift>period | Bitwarden | Autofill last login (i.e., "password")
# | |
# <Alt><Shift>d | Dark Reader | Toggle extension for all sites
# <Alt><Shift>c | Dark Reader | Toggle extension for current site only
#
[org/gnome/desktop/wm/keybindings]
activate-window-menu=@as []
always-on-top=@as []
# <Alt>F4 is an exception to the F-key rule,
# because everyone expects it
close=['<Super><Shift>q', '<Alt>F4']
# F11 is an exception to the F-key rule,
# because everyone expects it
toggle-fullscreen=['<Super><Shift>f', 'F11']
toggle-maximized=['<Super><Shift>m']
maximize=@as []
unmaximize=@as []
minimize=@as []
switch-applications=@as []
switch-applications-backward=@as []
switch-input-source=@as []
switch-input-source-backward=@as []
switch-group=@as []
switch-group-backward=@as []
switch-panels=@as []
switch-panels-backward=@as []
switch-windows=@as []
switch-windows-backward=@as []
cycle-group=@as []
cycle-group-backward=@as []
cycle-panels=@as []
cycle-panels-backward=@as []
# Kept mainly because other people may expect this;
# otherwise, redundant because of <Super>Tab
cycle-windows=['<Alt>Tab']
cycle-windows-backward=['<Alt><Shift>Tab']
begin-move=@as []
begin-resize=@as []
# Deprecated and ignored, listed only for completeness
panel-main-menu=@as []
# GNOME's own run prompt on <Alt>F2,
# replaced by `rofi` on <Super><Shift>space
panel-run-dialog=@as []
toggle-above=@as []
toggle-on-all-workspaces=@as []
show-desktop=@as []
# The following could also be populated automatically
# in [org/gnome/shell/extensions/space-bar/shortcuts]
# but we use the more deterministic configuration here
switch-to-workspace-1=[ '<Super>1']
switch-to-workspace-2=[ '<Super>2']
switch-to-workspace-3=[ '<Super>3']
switch-to-workspace-4=[ '<Super>4']
switch-to-workspace-5=[ '<Super>5']
switch-to-workspace-6=[ '<Super>6']
switch-to-workspace-7=[ '<Super>7']
switch-to-workspace-8=[ '<Super>8']
switch-to-workspace-9=[ '<Super>9']
switch-to-workspace-10=['<Super>0']
switch-to-workspace-11=@as []
switch-to-workspace-12=@as []
switch-to-workspace-last=@as []
switch-to-workspace-up=@as []
switch-to-workspace-down=@as []
switch-to-workspace-left=[ '<Super>comma']
switch-to-workspace-right=['<Super>period']
# "hotkey" in [desktop/ibus/panel/emoji]
# must remove <Super>period from its (default) binding;
# otherwise it contradicts "switch-to-workspace-right"
# The following could also be populated automatically
# in [org/gnome/shell/extensions/space-bar/shortcuts]
# but we use the more deterministic configuration here
move-to-workspace-1=[ '<Super><Shift>1']
move-to-workspace-2=[ '<Super><Shift>2']
move-to-workspace-3=[ '<Super><Shift>3']
move-to-workspace-4=[ '<Super><Shift>4']
move-to-workspace-5=[ '<Super><Shift>5']
move-to-workspace-6=[ '<Super><Shift>6']
move-to-workspace-7=[ '<Super><Shift>7']
move-to-workspace-8=[ '<Super><Shift>8']
move-to-workspace-9=[ '<Super><Shift>9']
move-to-workspace-10=['<Super><Shift>0']
move-to-workspace-11=@as []
move-to-workspace-12=@as []
move-to-workspace-last=@as []
move-to-workspace-up=@as []
move-to-workspace-down=@as []
move-to-workspace-left=[ '<Super><Shift>comma']
move-to-workspace-right=['<Super><Shift>period']
move-to-monitor-up=@as []
move-to-monitor-down=@as []
move-to-monitor-left=@as []
move-to-monitor-right=@as []
[org/gnome/shell/extensions/forge/keybindings]
# The latest `forge` on https://extensions.gnome.org/extension/4481/forge/
# may break "window-toggle-float", and is currently not maintained
# => Build from source with `gnome-shell-extension-forge-install`
window-toggle-float=['<Super><Control>f']
window-toggle-always-float=['<Super><Alt>f']
window-focus-up=[ '<Super>k']
window-focus-down=[ '<Super>j']
window-focus-left=[ '<Super>h']
window-focus-right=['<Super>l']
window-move-up=[ '<Super><Shift>k']
window-move-down=[ '<Super><Shift>j']
window-move-left=[ '<Super><Shift>h']
window-move-right=['<Super><Shift>l']
window-swap-up=[ '<Super><Control>k']
window-swap-down=[ '<Super><Control>j']
window-swap-left=[ '<Super><Control>h']
window-swap-right=['<Super><Control>l']
window-swap-last-active=['<Super><Control>grave']
# <Super><Alt> + hjkl pushes an edge outward (i.e., "grow")
# while <Super><Alt><Shift> + hjkl pulls the opposite edge inward (i.e., "shrink")
window-resize-top-increase=[ '<Super><Alt>k']
window-resize-top-decrease=[ '<Super><Alt><Shift>j']
window-resize-bottom-increase=['<Super><Alt>j']
window-resize-bottom-decrease=['<Super><Alt><Shift>k']
window-resize-left-increase=[ '<Super><Alt>h']
window-resize-left-decrease=[ '<Super><Alt><Shift>l']
window-resize-right-increase=[ '<Super><Alt>l']
window-resize-right-decrease=[ '<Super><Alt><Shift>h']
window-snap-center=@as []
window-snap-one-third-left=@as []
window-snap-one-third-right=@as []
window-snap-two-third-left=@as []
window-snap-two-third-right=@as []
window-gap-size-decrease=@as []
window-gap-size-increase=@as []
# Split direction is the container's axis, not the divider drawn
# - b => "beside"/"horizontal" => new window opens "beside", to the right
# - v => "vertical" => new window opens below
con-split-horizontal=['<Super>b']
con-split-vertical=[ '<Super>v']
con-split-layout-toggle=['<Super>e']
con-stacked-layout-toggle=['<Super>s']
con-tabbed-layout-toggle=['<Super>w']
con-tabbed-showtab-decoration-toggle=@as []
workspace-active-tile-toggle=['<Super><Alt><Shift>f']
prefs-open=@as []
# Allow tiling via drag-and-drop with the mouse
mod-mask-mouse-tile='None'
focus-border-toggle=@as []
prefs-tiling-toggle=@as []
[org/gnome/mutter/keybindings]
cancel-input-capture=@as []
# We must set the XF86 key here explicitly
# because by default <Super>p is also bound with it
# and we want to disable this
switch-monitor=['XF86Display']
toggle-tiled-left=@as []
toggle-tiled-right=@as []
[org/gnome/settings-daemon/plugins/media-keys]
search=['<Super><Shift>slash']
calculator=@as []
control-center=@as []
email=@as []
help=@as []
home=@as []
media=@as []
www=@as []
# Session & Power related
# "Escape" means "step away" while the session survives,
# and "the deeper the layer, the deeper the sleep"
#
# `suspend` and `hibernate` are bound per machine in local/*.ini
# because not every machine supports them:
# - `mem` and `disk` must appear in /sys/power/state
# - `hibernate` additionally needs more swap than RAM,
# with swap inside the LUKS container
#
screensaver=['<Super><Control>Escape']
#
# Reserved: <Super><Alt>Escape
suspend=@as []
#
# Reserved: <Super><Alt><Shift>Escape
hibernate=@as []
# "BackSpace" means "end the session",
# and "the deeper the layer, the further the machine goes"
#
# "Delete" mirrors it because on many keyboards it sits in the top right corner
# while "BackSpace" is the one key guaranteed to exist
#
# "Home" and "End" say what they do on their own
# (i.e., "back to the start" and "the end");
# so, they need no layer to express severity
# and serve as intuitive shortcuts
logout=[ '<Super><Control>BackSpace', '<Super><Control>Delete']
reboot=[ '<Super><Alt>BackSpace', '<Super><Alt>Delete', '<Super><Control>Home']
shutdown=['<Super><Alt><Shift>BackSpace', '<Super><Alt><Shift>Delete', '<Super><Control>End']
# The physical power button
# is disarmed by "power-button-action" in ~/.config/gnome-settings/misc.ini
# => A binding here would do "nothing" anyways
power=@as []
# Devices
# Shows an OSD message only if a machine has a battery
battery-status=['<Super><Control>e']
touchpad-toggle=['<Super><Alt>i']
touchpad-on=@as []
touchpad-off=@as []
# "Airplane mode", i.e., all radios at once
# (for WiFi only see <Super><Control>w below)
rfkill=['<Super><Alt>w']
rfkill-bluetooth=['<Super><Control>b']
# Audio related
# `play` toggles, so `pause` and `stop` are not needed
play=['<Super><Control>space']
pause=@as []
stop=@as []
eject=@as []
next=[ '<Super><Control>Right']
previous=['<Super><Control>Left']
playback-forward=['<Super><Alt>Right']
playback-rewind=[ '<Super><Alt>Left']
playback-random=@as []
playback-repeat=@as []
volume-up=['<Super><Control>Up']
volume-up-precise=@as []
volume-up-quiet=@as []
volume-down=['<Super><Control>Down']
volume-down-precise=@as []
volume-down-quiet=@as []
volume-mute=['<Super><Control>m']
volume-mute-quiet=@as []
mic-mute=['<Super><Alt>m']
# Screen and light related
# "Auto rotate"
rotate-video-lock=@as []
toggle-contrast=@as []
screen-brightness-up=[ '<Super><Alt>Up']
screen-brightness-down=['<Super><Alt>Down']
screen-brightness-cycle=@as []
magnifier=@as []
magnifier-zoom-in=@as []
magnifier-zoom-out=@as []
decrease-text-size=@as []
increase-text-size=@as []
screenreader=@as []
on-screen-keyboard=@as []
keyboard-brightness-up=[ '<Super><Alt>period']
keyboard-brightness-down=[ '<Super><Alt>comma']
keyboard-brightness-toggle=['<Super><Alt>slash']
# Non-default or "custom" GNOME bindings
# Due to the structure of the below groups,
# we must duplicate some of them to allow multiple bindings
custom-keybindings=['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_key_bindings/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/move_window_to_empty_workspace/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/list_windows/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_launcher_1/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_launcher_2/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_run_1/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_run_2/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_primary_terminal_1/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_primary_terminal_2/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_secondary_terminal_1/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_secondary_terminal_2/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_file_manager/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_firefox/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_chromium/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_google_chrome/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_evolution/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/dark_scheme_toggle/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/night_light_force/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/night_light_toggle/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/night_light_make_cooler/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/night_light_make_warmer/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/randomize_background/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/wifi_toggle/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/restart_gnome_shell/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/emoji_picker_type/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/emoji_picker_copy/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/vault_toggle/']
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_key_bindings]
binding='<Super>F1'
command='/home/user/.local/bin/key-bindings'
name='Show the key bindings'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/move_window_to_empty_workspace]
binding='<Super><Shift>n'
command='/home/user/.local/bin/move-window-to-empty-workspace'
name='Move window to first empty workspace'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/list_windows]
binding='<Super>Tab'
command='rofi -show window'
name='Show open windows'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_launcher_1]
binding='<Super>space'
command='rofi -show drun'
name='Open the launcher [1/2]'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_launcher_2]
# i3wm's default
binding='<Super>d'
command='rofi -show drun'
name='Open the launcher [2/2]'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_run_1]
binding='<Super><Shift>space'
command='rofi -show run'
name='Run a command [1/2]'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/show_run_2]
binding='<Super><Shift>d'
command='rofi -show run'
name='Run a command [2/2]'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_primary_terminal_1]
# i3wm's default, used for our primary terminal with `zsh`
binding='<Super>Return'
command='alacritty'
name='Alacritty (zsh) [1/2]'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_primary_terminal_2]
binding='<Super>t'
command='alacritty'
name='Alacritty (zsh) [2/2]'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_secondary_terminal_1]
# Our secondary terminal with `bash`
binding='<Super><Shift>Return'
command='gnome-terminal'
name='GNOME Terminal (bash) [1/2]'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_secondary_terminal_2]
binding='<Super><Shift>t'
command='gnome-terminal'
name='GNOME Terminal (bash) [2/2]'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_file_manager]
binding='<Super>f'
command='nautilus'
name='Files'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_firefox]
binding='<Super>i'
command='firefox-esr'
name='Firefox'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_chromium]
binding='<Super><Shift>i'
command='chromium'
name='Chromium'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_google_chrome]
binding='<Super><Control>i'
command='google-chrome'
name='Google Chrome'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch_evolution]
binding='<Super>m'
command='/home/user/.local/bin/evolution-on-workspace-0'
name='Evolution'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/dark_scheme_toggle]
binding='<Super><Alt>d'
command='/home/user/.local/bin/dark-scheme-toggle'
name='Toggle dark scheme'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/night_light_force]
binding='<Super><Alt>backslash'
command='/home/user/.local/bin/night-light-toggle-schedule'
name='Force night light on/off (i.e., override the automatic schedule)'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/night_light_toggle]
binding='<Super><Alt><Shift>backslash'
command='/home/user/.local/bin/night-light-toggle-enabled'
name='Turn night light on/off (i.e., the feature as a whole)'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/night_light_make_cooler]
binding='<Super><Alt>bracketleft'
command='/home/user/.local/bin/night-light-make-cooler'
name='Make night light cooler'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/night_light_make_warmer]
binding='<Super><Alt>bracketright'
command='/home/user/.local/bin/night-light-make-warmer'
name='Make night light warmer'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/randomize_background]
binding='<Super><Alt>b'
command='/home/user/.local/bin/randomize-background'
name='Randomize wallpaper'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/wifi_toggle]
binding='<Super><Control>w'
command='/home/user/.local/bin/wifi-toggle'
name='Toggle WiFi'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/restart_gnome_shell]
binding='<Super><Alt><Shift>r'
command='/home/user/.local/bin/gnome-shell-restart'
name='Restart GNOME shell (X11 only)'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/emoji_picker_type]
binding='<Super>semicolon'
command='/home/user/.local/bin/rofimoji --action type'
name='Type an emoji'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/emoji_picker_copy]
binding='<Super><Shift>semicolon'
command='/home/user/.local/bin/rofimoji --action copy'
name='Copy an emoji'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/vault_toggle]
binding='<Super><Control>v'
command='/home/user/.local/bin/vault-toggle'
name='(Un-)Mount the vault'
[org/gnome/shell/keybindings]
# Overview is still reachable indirectly but turned off on purpose
toggle-application-view=[ '<Super>slash']
toggle-message-tray=[ '<Super><Control>slash']
toggle-overview=@as []
toggle-quick-settings=['<Super><Alt><Shift>slash']
# Take fast screenshots without manual selection first,
# as opposed to the interactive UI below
screenshot=[ '<Shift>Print', '<Super><Alt><Shift>p']
screenshot-window=['<Alt>Print', '<Super><Alt>p']
# Manually select what to screenshot ...
show-screenshot-ui=['Print', '<Super><Control>p']
# ... or what to record
show-screen-recording-ui=['<Super><Control>r']
focus-active-notification=@as []
# The defaults would collide with "screen-brightness-up/down" on <Super><Alt> + Up/Down
shift-overview-up=@as []
shift-overview-down=@as []
# Disable GNOME's default behavior of opening "favorite" apps
# with <Super>1-10 and instead switch workspaces
switch-to-application-1=@as []
switch-to-application-2=@as []
switch-to-application-3=@as []
switch-to-application-4=@as []
switch-to-application-5=@as []
switch-to-application-6=@as []
switch-to-application-7=@as []
switch-to-application-8=@as []
switch-to-application-9=@as []
# `switch-to-application-10=@as []` does not exist by default
open-new-window-application-1=@as []
open-new-window-application-2=@as []
open-new-window-application-3=@as []
open-new-window-application-4=@as []
open-new-window-application-5=@as []
open-new-window-application-6=@as []
open-new-window-application-7=@as []
open-new-window-application-8=@as []
open-new-window-application-9=@as []
[org/gnome/shell/extensions/space-bar/shortcuts]
# We use the `switch-to-workspace-N`s in [org/gnome/desktop/wm/keybindings]
enable-activate-workspace-shortcuts=false
# We use the `move-to-workspace-N`s in [org/gnome/desktop/wm/keybindings]
enable-move-to-workspace-shortcuts=false
# Jump back to the previous workspace,
# also allowing toggling between two workspaces
# (Note that "grave" is the formal word for "backtick")
activate-previous-key=['<Super>grave']
# Jump to the first empty workspace
activate-empty-key=['<Super>n']
# Use the mouse to move to the previous workspace
# by clicking on the current one (again)
back-and-forth=false
move-workspace-left=@as []
move-workspace-right=@as []
# Preferences window
open-menu=@as []
[org/gnome/terminal/legacy/keybindings]
copy='<Control><Shift>c'
paste='<Control><Shift>v'
# Search in GNOME's terminal:
# - terminal feature that belongs on the in-app <Control><Shift> layer
# - the bare <Control> layer must stay free for the programs running inside,
# for example, <Control>f forwards pages in `vi`, `less`, and others,
# and <Control>g aborts or shows file info
# - these bindings are also the default
find='<Control><Shift>f'
find-clear='<Control><Shift>j'
find-next='<Control><Shift>g'
find-previous='<Control><Shift>h'
fullscreen='F11'
# "equal" because it is below "plus" on a US keyboard
zoom-in='<Control>equal'
zoom-out='<Control>minus'
zoom-normal='<Control>0'
# Unset on purpose because with a tiling window manager
# we don't want to have to manage tabs inside a window
close-tab='disabled'
close-window='disabled'
new-tab='disabled'
new-window='disabled'
detach-tab='disabled'
next-tab='disabled'
prev-tab='disabled'
move-tab-left='disabled'
move-tab-right='disabled'
switch-to-tab-1='disabled'
switch-to-tab-2='disabled'
switch-to-tab-3='disabled'
switch-to-tab-4='disabled'
switch-to-tab-5='disabled'
switch-to-tab-6='disabled'
switch-to-tab-7='disabled'
switch-to-tab-8='disabled'
switch-to-tab-9='disabled'
switch-to-tab-10='disabled'
switch-to-tab-11='disabled'
switch-to-tab-12='disabled'
switch-to-tab-13='disabled'
switch-to-tab-14='disabled'
switch-to-tab-15='disabled'
switch-to-tab-16='disabled'
switch-to-tab-17='disabled'
switch-to-tab-18='disabled'
switch-to-tab-19='disabled'
switch-to-tab-20='disabled'
switch-to-tab-21='disabled'
switch-to-tab-22='disabled'
switch-to-tab-23='disabled'
switch-to-tab-24='disabled'
switch-to-tab-25='disabled'
switch-to-tab-26='disabled'
switch-to-tab-27='disabled'
switch-to-tab-28='disabled'
switch-to-tab-29='disabled'
switch-to-tab-30='disabled'
switch-to-tab-31='disabled'
switch-to-tab-32='disabled'
switch-to-tab-33='disabled'
switch-to-tab-34='disabled'
switch-to-tab-35='disabled'
switch-to-tab-last='disabled'
[desktop/ibus/panel/emoji]
# <Super>period is the default "hotkey", but it conflicts with
# "switch-to-workspace-right" in [org/gnome/desktop/wm/keybindings]
#
# Instead of GNOME's `ibus emoji` we use `rofimoji`
# in [org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/emoji_picker_*]
#
hotkey=@as []

View file

@ -0,0 +1,62 @@
# Machine-Specific Overrides
`*.ini` files here are loaded *after* the shared files one level up
and may override any of their keys.
Use them for anything tied to one machine's hardware or capabilities,
for example, suspend/hibernate bindings, HiDPI scaling, or night light warmth.
Same rules as for the shared files:
paths are anchored at the root of `dconf`,
and `/home/user` is rewritten before loading.
Two files are *generated* and must not be edited by hand:
- `palette.ini` is written by [`color-palette`](../../../.local/bin/color-palette)
- `temporary_background.ini` is written by
[`randomize-background`](../../../.local/bin/randomize-background)
and removed again by
[`gnome-restore`](../../../.local/bin/gnome-restore)
on the next login
## Examples
Suspend and hibernate bindings are reserved
in [`key-bindings.ini`](../key-bindings.ini)
but only bound here
on machines that support them:
```ini
# local/power.ini
[org/gnome/settings-daemon/plugins/media-keys]
suspend=['<Super><Alt>Escape']
hibernate=['<Super><Alt><Shift>Escape']
```
A HiDPI panel:
```ini
# local/display.ini
[org/gnome/desktop/interface]
text-scaling-factor=1.25
```
A machine in a dim room that should run warmer by default:
```ini
# local/night-light.ini
[org/gnome/settings-daemon/plugins/color]
night-light-temperature=uint32 1800
```

View file

@ -0,0 +1,530 @@
# Various other settings
[org/freedesktop/tracker/miner/files]
# This is the `localsearch` indexing service
index-recursive-directories=['/home/user/Cloud']
index-single-directories=['&DOWNLOAD']
[org/gnome/desktop/a11y]
# Caret browsing for read-only text and GTK3 only
always-show-text-caret=false
# Show the "Universal Access" icon even when no feature is active
always-show-universal-access-status=false
[org/gnome/desktop/a11y/applications]
# Touchscreen keyboard
screen-keyboard-enabled=false
# Master switch for [org/gnome/desktop/a11y/magnifier] below
screen-magnifier-enabled=false
# Disable `orca`
screen-reader-enabled=false
[org/gnome/desktop/a11y/interface]
# Replace the GTK theme,
# overriding our "color-scheme" in [org/gnome/desktop/interface]
high-contrast=false
# Adds a glyph inside toggle switches, for color blindness
show-status-shapes=false
[org/gnome/desktop/a11y/keyboard]
enable=false
# Latch modifiers instead of holding them
stickykeys-enable=false
# Only accept keys held for "slowkeys-delay" ms
slowkeys-enable=false
# Ignore a repeat of the same key within bouncekeys-delay ms
bouncekeys-enable=false
# Move the pointer with the numeric keypad
# (Collides with "numlock-state" in [org/gnome/desktop/peripherals/keyboard])
mousekeys-enable=false
# Beep when Caps/Num/Scroll Lock are toggled
togglekeys-enable=false
# [org/gnome/desktop/a11y/magnifier]
# Inert because "screen-magnifier-enabled" above is false
[org/gnome/desktop/a11y/mouse]
# Click by resting the pointer for "dwell-time" seconds
dwell-click-enabled=false
# Hold the left button for "secondary-click-time" seconds to right-click
secondary-click-enabled=false
[org/gnome/desktop/app-folders]
# If this is non-empty, `gnome-shell` does not recreate the default folders
folder-children=['Unused']
[org/gnome/desktop/background]
color-shading-type='solid'
# Keep "picture-uri"s in sync with [org/gnome/desktop/screensaver] below
picture-options='zoom'
picture-uri-dark='file:///home/user/.local/share/backgrounds/dark.jpg'
picture-uri='file:///home/user/.local/share/backgrounds/light.jpg'
primary-color='#fceae3'
secondary-color='#fceae3'
[org/gnome/desktop/break-reminders]
# We keep the settings below as defaults
# for when we re-enable the feature again
selected-breaks=@as []
[org/gnome/desktop/break-reminders/eyesight]
# The 20-20-20 rule: every 20 minutes, look away for 20 seconds
countdown=false
delay-seconds=uint32 180
duration-seconds=uint32 20
interval-seconds=uint32 1200
fade-screen=true
lock-screen=false
notify=true
notify-overdue=true
notify-upcoming=false
play-sound=true
[org/gnome/desktop/break-reminders/movement]
# Get up and move for 5 minutes every 30 minutes
countdown=false
delay-seconds=uint32 180
duration-seconds=uint32 300
interval-seconds=uint32 1800
fade-screen=true
lock-screen=false
notify=true
notify-overdue=true
notify-upcoming=true
play-sound=true
[org/gnome/desktop/calendar]
show-weekdate=true
[org/gnome/desktop/datetime]
automatic-timezone=true
[org/gnome/desktop/file-sharing]
require-password='always'
[org/gnome/desktop/input-sources]
per-window=false
sources=[('xkb', 'us')]
# `xkb-options` are purely additive and there is no "off" token;
# so, whatever is listed below is enabled, and everything else is disabled
#
# Enabled:
#
# - "caps:ctrl_modifier"
# => Caps Lock becomes an additional Control for quicker access when typing
# - "compose:ralt"
# => Right Alt can be used to Compose, e.g., Compose a " gives ä
# - "lv3:menu_switch"
# => Menu becomes "AltGr", which unlocks the third level of the layout,
# and which is different from the normal <Alt> modifier
#
# Alternative:
#
# - "caps:ctrl_super"
# => Caps Lock becomes an additional <Super> for quicker window navigation
#
# Deliberately NOT enabled:
#
# - "grp:alt_shift_toggle"
# => Makes a bare tap of Alt+Shift cycle the active keyboard layouts
# - "terminate:ctrl_alt_bksp"
# => Maps <Control><Alt>BackSpace to the X keysym "Terminate_Server",
# which Kills the X server instantly with no prompt and no session save
#
xkb-options=['caps:ctrl_modifier', 'compose:ralt', 'lv3:menu_switch']
[org/gnome/desktop/interface]
accent-color='orange'
clock-format='24h'
clock-show-date=true
clock-show-seconds=true
clock-show-weekday=true
# Options are:
# - "default"
# + Basically a light theme
# + Some of the shell chrome remains dark (e.g., the top bar)
# + Selectable in the `gnome-control-center`
# - "prefer-dark"
# + Official dark theme
# + Selectable in the `gnome-control-center`
# - "prefer-light"
# + Unofficial light theme
# + Not selectable in the `gnome-control-center`
# + Usable via the "Dark Style" toggle in the quick settings menu
# only with the "Light Style" extension
color-scheme='prefer-light'
font-name='Adwaita Sans 11'
document-font-name='Adwaita Sans 11'
monospace-font-name='FiraCode Nerd Font 11'
font-antialiasing='grayscale'
font-hinting='slight'
enable-animations=true
enable-hot-corners=false
# `ibus` is needed for Unicode/emoji input (e.g., Ctrl+Shift+u), but
# we leave it to auto-detection in case the system does not support it
# gtk-im-module='ibus'
gtk-theme='Adwaita'
icon-theme='Adwaita'
show-battery-percentage=true
toolkit-accessibility=false
[org/gnome/desktop/lockdown]
# Keep in sync with "user-switch-enabled" in [org/gnome/desktop/screensaver]
disable-user-switching=true
[org/gnome/desktop/media-handling]
automount=true
automount-open=false
autorun-never=true
autorun-x-content-ignore=@as []
autorun-x-content-open-folder=@as []
autorun-x-content-start-app=@as []
[org/gnome/desktop/peripherals/keyboard]
numlock-state=true
remember-numlock-state=true
[org/gnome/desktop/peripherals/mouse]
natural-scroll=false
[org/gnome/desktop/peripherals/touchpad]
send-events='enabled'
edge-scrolling-enabled=false
natural-scroll=true
two-finger-scrolling-enabled=true
tap-to-click=true
[org/gnome/desktop/privacy]
disable-camera=false
disable-microphone=false
disable-sound-output=false
hide-identity=true
old-files-age=uint32 7
recent-files-max-age=7
remember-app-usage=true
remember-recent-files=true
remove-old-temp-files=true
remove-old-trash-files=true
report-technical-problems=false
send-software-usage-stats=false
show-full-name-in-top-bar=false
usb-protection=true
# TODO: Uncomment only together with a populated /etc/usbguard/rules.conf,
# or every new device is blocked
# usb-protection-level='always'
[org/gnome/desktop/remote-desktop]
[org/gnome/desktop/remote-desktop/rdp]
enable=false
view-only=true
[org/gnome/desktop/remote-desktop/vnc]
enable=false
view-only=true
[org/gnome/desktop/screen-time-limits]
daily-limit-enabled=false
daily-limit-seconds=uint32 28800
grayscale=false
history-enabled=false
[org/gnome/desktop/screensaver]
color-shading-type='solid'
# Make the machine locked after suspend
lock-enabled=true
# Only applies to the idle path, and
# "Suspend" locks immediately, regardless of this delay
# => Together with the "idle-*" settings we follow a
# "Blank first, lock much later" strategy
lock-delay=uint32 7200
logout-enabled=true
# Keep "picture-uri" in sync with [org/gnome/desktop/background] above
picture-options='zoom'
picture-uri='file:///home/user/.local/share/backgrounds/dark.jpg'
primary-color='#000000'
secondary-color='#000000'
show-full-name-in-top-bar=false
status-message-enabled=false
# Keep in sync with "disable-user-switching" in [org/gnome/desktop/lockdown]
user-switch-enabled=false
[org/gnome/desktop/search-providers]
disable-external=false
# The disabled entries should also be the end of the sort-order
disabled=['org.gnome.Characters.desktop', 'org.gnome.clocks.desktop', 'org.gnome.seahorse.Application.desktop', 'org.gnome.Terminal.desktop']
sort-order=['org.gnome.Nautilus.desktop', 'org.gnome.Settings.desktop', 'org.gnome.Software.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Contacts.desktop', 'org.gnome.Characters.desktop', 'org.gnome.clocks.desktop', 'org.gnome.seahorse.Application.desktop', 'org.gnome.Terminal.desktop']
[org/gnome/desktop/session]
# Blank the screen after 10 minutes of idle time
# => Together with the other "idle-*" and the "lock-delay" settings
# we follow a "Blank first, lock much later" strategy
idle-delay=uint32 600
[org/gnome/desktop/sound]
allow-volume-above-100-percent=true
event-sounds=true
input-feedback-sounds=true
# [org/gnome/desktop/wm/keybindings]
# See ~/.config/gnome-settings/key-bindings.ini for the key bindings
[org/gnome/desktop/wm/preferences]
audible-bell=false
visual-bell=false
action-double-click-titlebar='toggle-maximize'
action-middle-click-titlebar='none'
action-right-click-titlebar='none'
mouse-button-modifier=''
# Right-drag resizes when true, and middle-drag when false
# (May only be enabled if "mouse-button-modifier" is set above)
resize-with-right-button=false
# Just show an "X" to close a window in the GUI
button-layout='close:'
focus-mode='click'
raise-on-click=true
# 'strict' would withhold focus from windows launched from a terminal
focus-new-windows='smart'
titlebar-uses-system-font=false
titlebar-font='Adwaita Sans Bold 11'
num-workspaces=10
workspace-names=['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
[org/gnome/mutter]
dynamic-workspaces=false
# We use `forge` for tiling
edge-tiling=false
# Keep in sync with "overlay-key" under [org/gnome/shell/extensions/just-perfection]
overlay-key=''
workspaces-only-on-primary=true
# [org/gnome/mutter/keybindings]
# See ~/.config/gnome-settings/key-bindings.ini for the key bindings
[org/gnome/settings-daemon/plugins/color]
# We add some custom logic in ~/.local/bin/night-light-* scripts
# for more convenient management of the tool via keyboard bindings
night-light-enabled=true
# We use the live location to determine the schedule by default,
# and use ~/.local/bin/night-light-toggle-schedule to force "Night Light" on
night-light-schedule-automatic=true
# If automatic does not work, we fall back to something reasonable
night-light-schedule-from=18.0
night-light-schedule-to=6.0
# The `$_DEFAULT_TEMPERATURE` used in the ~/.local/bin/night-light-* scripts
night-light-temperature=uint32 2200
[org/gnome/settings-daemon/plugins/media-keys]
# See ~/.config/gnome-settings/key-bindings.ini for the key bindings
volume-step=10
[org/gnome/settings-daemon/plugins/power]
# Together with the "idle-delay" and "lock-delay" settings
# we follow a "Blank first, lock much later" strategy
idle-dim=true
idle-brightness=10
power-button-action='nothing'
power-saver-profile-on-low-battery=true
# 0 => "never"
sleep-inactive-ac-timeout=0
sleep-inactive-ac-type='nothing'
# 0 => "never"
sleep-inactive-battery-timeout=0
sleep-inactive-battery-type='nothing'
[org/gnome/system/location]
enabled=true
[system/locale]
region='en_DK.UTF-8'
[system/proxy]
mode='none'

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,56 @@
# Basic GNOME Shell configuration
[org/gnome/shell]
# Always reset the command history
command-history=@as []
development-tools=false
# Empty because we disable the "dash" in [org/gnome/shell/extensions/just-perfection]
favorite-apps=@as []
last-selected-power-profile='balanced'
# For mounting encrypted or remote filesystems
remember-mount-password=true
# Never show GNOME's welcome dialog again
welcome-dialog-last-shown-version='999.999'
[org/gnome/shell/app-switcher]
current-workspace-only=true
# [org/gnome/shell/keybindings]
# See ~/.config/gnome-settings/key-bindings.ini for the key bindings
[org/gnome/shell/weather]
automatic-location=true
# Keep in sync with "locations" in [org/gnome/Weather]
locations=[<(uint32 2, <('Berlin', 'EDDB', true, [(0.91426163401859872, 0.23591034304566436)], [(0.91658875132345297, 0.23387411976724018)])>)>, <(uint32 2, <('Heidelberg', 'EDFM', true, [(0.86345801419289459, 0.14862448983795826)], [(0.86238428763706787, 0.1517127801361921)])>)>, <(uint32 2, <('London', 'EGLL', true, [(0.89845190959903677, -0.0080529408042633736)], [(0.89899290734596930, -0.0021946055346929697)])>)>, <(uint32 2, <('New York', 'KNYC', true, [(0.71180344078725644, -1.2909618758762367)], [(0.71059804659265924, -1.2916478949920254)])>)>, <(uint32 2, <('Phoenix', 'KPHX', true, [(0.58353629681163499, -1.955660817467636)], [(0.58378430809834336, -1.9560609516519483)])>)>]
[org/gnome/shell/window-switcher]
app-icon-mode='app-icon-only'
current-workspace-only=true
[org/gnome/shell/world-clocks]
# Keep in sync with "world-clocks" in [org/gnome/clocks]
locations=[<(uint32 2, <('Phoenix', 'KPHX', true, [(0.58353629681163499, -1.955660817467636)], [(0.58378430809834336, -1.9560609516519483)])>)>, <(uint32 2, <('New York', 'KNYC', true, [(0.71180344078725644, -1.2909618758762367)], [(0.71059804659265924, -1.2916478949920254)])>)>, <(uint32 2, <('UTC', 'BIRK', true, [(1.1216380205691279, -0.38222710618675809)], [(1.1195629471197465, -0.38251373858977449)])>)>, <(uint32 2, <('London', 'EGLL', true, [(0.89845190959903677, -0.0080529408042633736)], [(0.89899290734596930, -0.0021946055346929697)])>)>, <(uint32 2, <('Berlin', 'EDDB', true, [(0.91426163401859872, 0.23591034304566436)], [(0.91658875132345297, 0.23387411976724018)])>)>]

View file

@ -0,0 +1,360 @@
# Configure all the GNOME Shell extensions
# - "alphabetical-app-grid" and "app-hider" create a simple and flat app drawer
# - "forge" takes the major role for the desktop layout
[org/gnome/shell]
enabled-extensions=['AlphabeticalAppGrid@stuarthayhurst', 'app-hider@lynith.dev', 'appindicator-hider@theophilediot.github.io', 'appindicatorsupport@rgcjonas.gmail.com', 'drive-menu@gnome-shell-extensions.gcampax.github.com', 'forge@jmmaranan.com', 'just-perfection-desktop@just-perfection', 'launch-new-instance@gnome-shell-extensions.gcampax.github.com', 'light-style@gnome-shell-extensions.gcampax.github.com', 'no-screenshot-box@screenshot', 'panel-date-format@keiii.github.com', 'rounded-window-corners@fxgn', 'space-bar@luchrioh']
disabled-extensions=@as []
disable-user-extensions=false
[org/gnome/shell/extensions/alphabetical-app-grid]
folder-order-position='alphabetical'
sort-folder-contents=true
logging-enabled=false
[org/gnome/shell/extensions/app-hider]
# We hide CLI utilities and rarely needed apps from the app drawer
hidden-apps=['com.nextcloud.desktopclient.nextcloud.desktop', 'display-im7.q16.desktop', 'gvim.desktop', 'htop.desktop', 'idle-python3.13.desktop', 'idle.desktop', 'im-config.desktop', 'jupyter-notebook.desktop', 'jupyterlab.desktop', 'libreoffice-startcenter.desktop', 'lynis.desktop', 'nvidia-settings.desktop', 'org.bpython-interpreter.bpython.desktop', 'org.freedesktop.MalcontentControl.desktop', 'org.gnome.Extensions.desktop', 'org.gnome.Settings.desktop', 'org.gnome.Software.desktop', 'org.gnome.Totem.desktop', 'org.gnome.Tour.desktop', 'org.gnome.tweaks.desktop', 'ranger.desktop', 'rofi-theme-selector.desktop', 'rofi.desktop', 'screenshot-screen.desktop', 'screenshot-ui.desktop', 'screenshot-window.desktop', 'system-config-printer.desktop', 'texdoctk.desktop', 'yelp.desktop']
[org/gnome/shell/extensions/appindicator]
tray-pos='right'
tray-order=999
compact-mode-enabled=true
# E.g., needed for `nextcloud`
legacy-tray-enabled=true
icon-opacity=240
# 0 => Use the icon's native size
icon-size=0
# 0.0 => No adjustment
icon-saturation=0.0
icon-brightness=0.0
icon-contrast=0.0
# Per-indicator icon overrides (indicator-id, icon-name, attention-icon-name)
custom-icons=@a(sss) []
[org/gnome/shell/extensions/appindicator-hider]
# Hide RustDesk's tray icon
hidden-indicators=['id:tray-icon']
# [org/gnome/shell/extensions/drive-menu]
# This extension does not have any settings
[org/gnome/shell/extensions/forge]
# "Magic number" such that forge's stylesheet at
# ~/.config/forge/stylesheet/forge/stylesheet.css
# is not rewritten with default values
css-last-update=uint32 37
logging-enabled=false
primary-layout-mode='tiling'
workspace-skip-tile=''
tiling-mode-enabled=true
stacked-tiling-mode-enabled=true
tabbed-tiling-mode-enabled=true
auto-exit-tabbed=true
showtab-decoration-enabled=true
auto-split-enabled=false
split-border-toggle=false
dnd-center-layout='tabbed'
float-always-on-top-enabled=true
focus-border-toggle=true
focus-on-hover-enabled=false
move-pointer-focus-enabled=false
preview-hint-enabled=true
quick-settings-enabled=false
resize-amount=uint32 32
window-gap-hidden-on-single=false
window-gap-size=uint32 3
window-gap-size-increment=uint32 2
[org/gnome/shell/extensions/just-perfection]
support-notifier-type=0
# Keep in sync with "overlay-key" in [org/gnome/mutter]
overlay-key=false
# Does not work with "overlay-key" turned off
double-super-to-appgrid=false
background-menu=false
# On-screen display for volume, brightness, ...
osd=true
# Show OSD notifications in the center of the screen
osd-position=8
# When switching between workspaces
workspace-popup=false
# Windows related stuff
window-demands-attention-focus=true
window-maximized-on-create=false
# Right-click in the title bar
window-menu=false
window-menu-take-screenshot-button=true
# Panel related stuff
panel=true
panel-in-overview=true
panel-notification-icon=true
# Panel should be at the top
top-panel-position=0
activities-button=false
clock-menu=true
clock-menu-position=0
clock-menu-position-offset=0
calendar=true
events-button=true
invert-calendar-column-items=false
weather=true
world-clock=true
keyboard-layout=false
accessibility-menu=false
power-icon=true
quick-settings=true
quick-settings-airplane-mode=true
quick-settings-backlight=true
quick-settings-dark-mode=true
quick-settings-night-light=true
screen-recording-indicator=true
screen-sharing-indicator=true
# "Hot Corner" animation
ripple-box=false
# In app drawer and overview menu
# Do not start in overview menu after login
startup-status=0
search=true
type-to-search=true
dash=false
dash-app-running=false
dash-separator=false
show-apps-button=false
# Reduce the noise in the overview menu
window-picker-icon=false
window-preview-caption=false
window-preview-close-button=false
workspace=false
workspaces-in-app-grid=false
workspace-peek=false
workspace-wrap-around=true
workspace-background-corner-size=0
workspace-switcher-should-show=false
workspace-thumbnail-to-main-view=false
# Look & Feel
accent-color-icon=false
animation=1
theme=false
# [org/gnome/shell/extensions/launch-new-instance]
# This extension does not have any settings
# [org/gnome/shell/extensions/light-style]
# This extension does not have any settings
[org/gnome/shell/extensions/no-screenshot-box]
mute-screenshot-sound=true
remove-preselected-box=true
# On a laptop with a touchpad "true" would be too tedious
screenshot-on-release=false
[org/gnome/shell/extensions/panel-date-format]
format='%A %B %-d, %Y %H:%M:%S %Z%z'
[org/gnome/shell/extensions/rounded-window-corners-reborn]
# Rounds all window corners uniformly (e.g., needed for `alacritty`)
#
# The rings drawn by forge sit outside the window frame
# and use a "border-radius" of 13px in
# ~/.config/forge/stylesheet/forge/stylesheet.css so their curves
# stay roughly concentric with the 12px window corners
#
# "padding" stays 0 because forge draws its focus rings outside
# the window frame and they never cover the contents
#
custom-rounded-corner-settings=@a{sv} {}
global-rounded-corner-settings={'padding': <{'left': uint32 0, 'right': 0, 'top': 0, 'bottom': 0}>, 'keepRoundedCorners': <{'maximized': true, 'fullscreen': true}>, 'borderRadius': <uint32 12>, 'smoothing': <0.0>, 'borderColor': <(0.6, 0.149, 0.0, 1.0)>, 'enabled': <true>}
focused-shadow={'horizontalOffset': 0, 'verticalOffset': 4, 'blurOffset': 28, 'spreadRadius': 3, 'opacity': 60}
unfocused-shadow={'horizontalOffset': 0, 'verticalOffset': 2, 'blurOffset': 12, 'spreadRadius': -1, 'opacity': 65}
# `forge` draws the borders
# => This extension must not
border-width=0
# Round GTK3/legacy apps,
# but not libadwaita's ones that are already rounded
skip-libadwaita-app=true
skip-libhandy-app=false
blacklist=@as []
enable-preferences-entry=false
tweak-kitty-terminal=false
debug-mode=false
[org/gnome/shell/extensions/space-bar]
[org/gnome/shell/extensions/space-bar/appearance]
# The colors below are the "orange"/light defaults from
# ~/.config/gnome-settings/COLORS.md and are overridden at load time
# by local/palette.ini, written by ~/.local/bin/color-palette
custom-styles-enabled=false
workspace-margin=2
workspaces-bar-padding=0
active-workspace-font-size=10
active-workspace-font-weight='700'
active-workspace-text-color='rgb(42,11,1)'
active-workspace-background-color='rgb(237,91,0)'
active-workspace-border-color='rgb(153,38,0)'
active-workspace-border-radius=8
active-workspace-border-width=0
active-workspace-padding-h=8
active-workspace-padding-v=2
inactive-workspace-font-size=10
inactive-workspace-font-weight='600'
inactive-workspace-text-color='rgb(99,18,0)'
inactive-workspace-background-color='rgb(235,235,237)'
inactive-workspace-border-color='rgb(235,235,237)'
inactive-workspace-border-radius=8
inactive-workspace-border-width=0
inactive-workspace-padding-h=8
inactive-workspace-padding-v=2
empty-workspace-font-size=10
empty-workspace-font-weight='600'
empty-workspace-text-color='rgb(252,108,39)'
empty-workspace-background-color='rgb(235,235,237)'
empty-workspace-border-color='rgb(235,235,237)'
empty-workspace-border-radius=8
empty-workspace-border-width=0
empty-workspace-padding-h=8
empty-workspace-padding-v=2
[org/gnome/shell/extensions/space-bar/behavior]
system-workspace-indicator=false
position='left'
position-index=0
indicator-style='workspaces-bar'
always-show-numbers=false
show-empty-workspaces=false
smart-workspace-names=false
enable-custom-label=true
enable-custom-label-in-menu=true
custom-label-named='{{name}}'
custom-label-unnamed='{{number}}'
scroll-wheel='disabled'
toggle-overview=false
# [org/gnome/shell/extensions/space-bar/shortcuts]
# See ~/.config/gnome-settings/key-bindings.ini for the key bindings

308
.config/mimeapps.list Normal file
View file

@ -0,0 +1,308 @@
[Default Applications]
application/pdf=org.gnome.Evince.desktop
application/x-shellscript=org.gnome.TextEditor.desktop
application/xhtml+xml=firefox.desktop;firefox-esr.desktop;google-chrome.desktop;chromium.desktop
audio/3gpp2=vlc.desktop
audio/3gpp=vlc.desktop
audio/AMR-WB=vlc.desktop
audio/AMR=vlc.desktop
audio/aac=vlc.desktop
audio/ac3=vlc.desktop
audio/basic=vlc.desktop
audio/dv=vlc.desktop
audio/eac3=vlc.desktop
audio/flac=vlc.desktop
audio/m4a=vlc.desktop
audio/midi=vlc.desktop
audio/mp1=vlc.desktop
audio/mp2=vlc.desktop
audio/mp3=vlc.desktop
audio/mp4=vlc.desktop
audio/mpeg=vlc.desktop
audio/mpegurl=vlc.desktop
audio/mpg=vlc.desktop
audio/ogg=vlc.desktop
audio/opus=vlc.desktop
audio/scpls=vlc.desktop
audio/vnd.dolby.heaac.1=vlc.desktop
audio/vnd.dolby.heaac.2=vlc.desktop
audio/vnd.dolby.mlp=vlc.desktop
audio/vnd.dts.hd=vlc.desktop
audio/vnd.dts=vlc.desktop
audio/vnd.rn-realaudio=vlc.desktop
audio/vorbis=vlc.desktop
audio/wav=vlc.desktop
audio/webm=vlc.desktop
audio/x-aac=vlc.desktop
audio/x-adpcm=vlc.desktop
audio/x-aiff=vlc.desktop
audio/x-ape=vlc.desktop
audio/x-flac=vlc.desktop
audio/x-gsm=vlc.desktop
audio/x-it=vlc.desktop
audio/x-m4a=vlc.desktop
audio/x-matroska=vlc.desktop
audio/x-mod=vlc.desktop
audio/x-mp1=vlc.desktop
audio/x-mp2=vlc.desktop
audio/x-mp3=vlc.desktop
audio/x-mpeg=vlc.desktop
audio/x-mpegurl=vlc.desktop
audio/x-mpg=vlc.desktop
audio/x-ms-asf=vlc.desktop
audio/x-ms-asx=vlc.desktop
audio/x-ms-wax=vlc.desktop
audio/x-ms-wma=vlc.desktop
audio/x-musepack=vlc.desktop
audio/x-pn-aiff=vlc.desktop
audio/x-pn-au=vlc.desktop
audio/x-pn-realaudio-plugin=vlc.desktop
audio/x-pn-realaudio=vlc.desktop
audio/x-pn-wav=vlc.desktop
audio/x-pn-windows-acm=vlc.desktop
audio/x-real-audio=vlc.desktop
audio/x-realaudio=vlc.desktop
audio/x-s3m=vlc.desktop
audio/x-scpls=vlc.desktop
audio/x-shorten=vlc.desktop
audio/x-speex=vlc.desktop
audio/x-tta=vlc.desktop
audio/x-vorbis+ogg=vlc.desktop
audio/x-vorbis=vlc.desktop
audio/x-wav=vlc.desktop
audio/x-wavpack=vlc.desktop
audio/x-xm=vlc.desktop
image/avif=org.gnome.Loupe.desktop
image/bmp=org.gnome.Loupe.desktop
image/gif=org.gnome.Loupe.desktop
image/heic=org.gnome.Loupe.desktop
image/jpeg=org.gnome.Loupe.desktop
image/jxl=org.gnome.Loupe.desktop
image/png=org.gnome.Loupe.desktop
image/qoi=org.gnome.Loupe.desktop
image/svg+xml-compressed=org.gnome.Loupe.desktop
image/svg+xml=org.gnome.Loupe.desktop
image/tiff=org.gnome.Loupe.desktop
image/vnd-ms.dds=org.gnome.Loupe.desktop
image/vnd.microsoft.icon=org.gnome.Loupe.desktop
image/vnd.radiance=org.gnome.Loupe.desktop
image/webp=org.gnome.Loupe.desktop
image/x-dds=org.gnome.Loupe.desktop
image/x-exr=org.gnome.Loupe.desktop
image/x-portable-anymap=org.gnome.Loupe.desktop
image/x-portable-bitmap=org.gnome.Loupe.desktop
image/x-portable-graymap=org.gnome.Loupe.desktop
image/x-portable-pixmap=org.gnome.Loupe.desktop
image/x-qoi=org.gnome.Loupe.desktop
image/x-tga=org.gnome.Loupe.desktop
text/calendar=org.gnome.Evolution.desktop
text/html=firefox.desktop;firefox-esr.desktop;google-chrome.desktop;chromium.desktop
text/markdown=org.gnome.TextEditor.desktop
text/plain=org.gnome.TextEditor.desktop
text/x-python=org.gnome.TextEditor.desktop
video/3gp=vlc.desktop
video/3gpp2=vlc.desktop
video/3gpp=vlc.desktop
video/avi=vlc.desktop
video/divx=vlc.desktop
video/dv=vlc.desktop
video/fli=vlc.desktop
video/flv=vlc.desktop
video/mp2t=vlc.desktop
video/mp4=vlc.desktop
video/mp4v-es=vlc.desktop
video/mpeg-system=vlc.desktop
video/mpeg=vlc.desktop
video/msvideo=vlc.desktop
video/ogg=vlc.desktop
video/quicktime=vlc.desktop
video/vivo=vlc.desktop
video/vnd.avi=vlc.desktop
video/vnd.divx=vlc.desktop
video/vnd.mpegurl=vlc.desktop
video/vnd.rn-realvideo=vlc.desktop
video/vnd.vivo=vlc.desktop
video/webm=vlc.desktop
video/x-anim=vlc.desktop
video/x-avi=vlc.desktop
video/x-flc=vlc.desktop
video/x-fli=vlc.desktop
video/x-flic=vlc.desktop
video/x-flv=vlc.desktop
video/x-m4v=vlc.desktop
video/x-matroska=vlc.desktop
video/x-mjpeg=vlc.desktop
video/x-mpeg-system=vlc.desktop
video/x-mpeg2=vlc.desktop
video/x-mpeg=vlc.desktop
video/x-ms-asf-plugin=vlc.desktop
video/x-ms-asf=vlc.desktop
video/x-ms-asx=vlc.desktop
video/x-ms-wm=vlc.desktop
video/x-ms-wmv=vlc.desktop
video/x-ms-wmx=vlc.desktop
video/x-ms-wvx=vlc.desktop
video/x-msvideo=vlc.desktop
video/x-nsv=vlc.desktop
video/x-ogm+ogg=vlc.desktop
video/x-ogm=vlc.desktop
video/x-theora+ogg=vlc.desktop
video/x-theora=vlc.desktop
x-scheme-handler/claude-cli=claude-code-url-handler.desktop
x-scheme-handler/http=firefox.desktop;firefox-esr.desktop;google-chrome.desktop;chromium.desktop
x-scheme-handler/https=firefox.desktop;firefox-esr.desktop;google-chrome.desktop;chromium.desktop
[Added Associations]
application/pdf=org.gnome.Evince.desktop;
application/x-shellscript=org.gnome.TextEditor.desktop;
application/xhtml+xml=firefox.desktop;firefox-esr.desktop;google-chrome.desktop;chromium.desktop;
audio/3gpp2=vlc.desktop;org.gnome.Totem.desktop;
audio/3gpp=vlc.desktop;org.gnome.Totem.desktop;
audio/AMR-WB=vlc.desktop;org.gnome.Totem.desktop;
audio/AMR=vlc.desktop;org.gnome.Totem.desktop;
audio/aac=vlc.desktop;org.gnome.Totem.desktop;
audio/ac3=vlc.desktop;org.gnome.Totem.desktop;
audio/basic=vlc.desktop;org.gnome.Totem.desktop;
audio/dv=vlc.desktop;org.gnome.Totem.desktop;
audio/eac3=vlc.desktop;org.gnome.Totem.desktop;
audio/flac=vlc.desktop;org.gnome.Totem.desktop;
audio/m4a=vlc.desktop;org.gnome.Totem.desktop;
audio/midi=vlc.desktop;org.gnome.Totem.desktop;
audio/mp1=vlc.desktop;org.gnome.Totem.desktop;
audio/mp2=vlc.desktop;org.gnome.Totem.desktop;
audio/mp3=vlc.desktop;org.gnome.Totem.desktop;
audio/mp4=vlc.desktop;org.gnome.Totem.desktop;
audio/mpeg=vlc.desktop;org.gnome.Totem.desktop;
audio/mpegurl=vlc.desktop;org.gnome.Totem.desktop;
audio/mpg=vlc.desktop;org.gnome.Totem.desktop;
audio/ogg=vlc.desktop;org.gnome.Totem.desktop;
audio/opus=vlc.desktop;org.gnome.Totem.desktop;
audio/scpls=vlc.desktop;org.gnome.Totem.desktop;
audio/vnd.dolby.heaac.1=vlc.desktop;
audio/vnd.dolby.heaac.2=vlc.desktop;
audio/vnd.dolby.mlp=vlc.desktop;
audio/vnd.dts.hd=vlc.desktop;
audio/vnd.dts=vlc.desktop;
audio/vnd.rn-realaudio=vlc.desktop;org.gnome.Totem.desktop;
audio/vorbis=vlc.desktop;
audio/wav=vlc.desktop;org.gnome.Totem.desktop;
audio/webm=vlc.desktop;org.gnome.Totem.desktop;
audio/x-aac=vlc.desktop;org.gnome.Totem.desktop;
audio/x-adpcm=vlc.desktop;
audio/x-aiff=vlc.desktop;org.gnome.Totem.desktop;
audio/x-ape=vlc.desktop;org.gnome.Totem.desktop;
audio/x-flac=vlc.desktop;org.gnome.Totem.desktop;
audio/x-gsm=vlc.desktop;org.gnome.Totem.desktop;
audio/x-it=vlc.desktop;org.gnome.Totem.desktop;
audio/x-m4a=vlc.desktop;org.gnome.Totem.desktop;
audio/x-matroska=vlc.desktop;org.gnome.Totem.desktop;
audio/x-mod=vlc.desktop;org.gnome.Totem.desktop;
audio/x-mp1=vlc.desktop;org.gnome.Totem.desktop;
audio/x-mp2=vlc.desktop;org.gnome.Totem.desktop;
audio/x-mp3=vlc.desktop;org.gnome.Totem.desktop;
audio/x-mpeg=vlc.desktop;org.gnome.Totem.desktop;
audio/x-mpegurl=vlc.desktop;org.gnome.Totem.desktop;
audio/x-mpg=vlc.desktop;org.gnome.Totem.desktop;
audio/x-ms-asf=vlc.desktop;org.gnome.Totem.desktop;
audio/x-ms-asx=vlc.desktop;org.gnome.Totem.desktop;
audio/x-ms-wax=vlc.desktop;org.gnome.Totem.desktop;
audio/x-ms-wma=vlc.desktop;org.gnome.Totem.desktop;
audio/x-musepack=vlc.desktop;org.gnome.Totem.desktop;
audio/x-pn-aiff=vlc.desktop;org.gnome.Totem.desktop;
audio/x-pn-au=vlc.desktop;org.gnome.Totem.desktop;
audio/x-pn-realaudio-plugin=vlc.desktop;org.gnome.Totem.desktop;
audio/x-pn-realaudio=vlc.desktop;org.gnome.Totem.desktop;
audio/x-pn-wav=vlc.desktop;org.gnome.Totem.desktop;
audio/x-pn-windows-acm=vlc.desktop;org.gnome.Totem.desktop;
audio/x-real-audio=vlc.desktop;org.gnome.Totem.desktop;
audio/x-realaudio=vlc.desktop;org.gnome.Totem.desktop;
audio/x-s3m=vlc.desktop;org.gnome.Totem.desktop;
audio/x-scpls=vlc.desktop;org.gnome.Totem.desktop;
audio/x-shorten=vlc.desktop;org.gnome.Totem.desktop;
audio/x-speex=vlc.desktop;org.gnome.Totem.desktop;
audio/x-tta=vlc.desktop;org.gnome.Totem.desktop;
audio/x-vorbis+ogg=vlc.desktop;org.gnome.Totem.desktop;
audio/x-vorbis=vlc.desktop;org.gnome.Totem.desktop;
audio/x-wav=vlc.desktop;org.gnome.Totem.desktop;
audio/x-wavpack=vlc.desktop;org.gnome.Totem.desktop;
audio/x-xm=vlc.desktop;org.gnome.Totem.desktop;
image/avif=org.gnome.Loupe.desktop;
image/bmp=org.gnome.Loupe.desktop;
image/gif=org.gnome.Loupe.desktop;
image/heic=org.gnome.Loupe.desktop;
image/jpeg=org.gnome.Loupe.desktop;
image/jxl=org.gnome.Loupe.desktop;
image/png=org.gnome.Loupe.desktop;
image/qoi=org.gnome.Loupe.desktop;
image/svg+xml-compressed=org.gnome.Loupe.desktop;
image/svg+xml=org.gnome.Loupe.desktop;
image/tiff=org.gnome.Loupe.desktop;
image/vnd-ms.dds=org.gnome.Loupe.desktop;
image/vnd.microsoft.icon=org.gnome.Loupe.desktop;
image/vnd.radiance=org.gnome.Loupe.desktop;
image/webp=org.gnome.Loupe.desktop;
image/x-dds=org.gnome.Loupe.desktop;
image/x-exr=org.gnome.Loupe.desktop;
image/x-portable-anymap=org.gnome.Loupe.desktop;
image/x-portable-bitmap=org.gnome.Loupe.desktop;
image/x-portable-graymap=org.gnome.Loupe.desktop;
image/x-portable-pixmap=org.gnome.Loupe.desktop;
image/x-qoi=org.gnome.Loupe.desktop;
image/x-tga=org.gnome.Loupe.desktop;
text/calendar=org.gnome.Evolution.desktop;org.gnome.Calendar.desktop;
text/html=firefox.desktop;firefox-esr.desktop;google-chrome.desktop;chromium.desktop;
text/markdown=org.gnome.TextEditor.desktop;
text/plain=org.gnome.TextEditor.desktop;
text/x-python=org.gnome.TextEditor.desktop;
video/3gp=vlc.desktop;org.gnome.Totem.desktop;
video/3gpp2=vlc.desktop;org.gnome.Totem.desktop;
video/3gpp=vlc.desktop;org.gnome.Totem.desktop;
video/avi=vlc.desktop;org.gnome.Totem.desktop;
video/divx=vlc.desktop;org.gnome.Totem.desktop;
video/dv=vlc.desktop;org.gnome.Totem.desktop;
video/fli=vlc.desktop;org.gnome.Totem.desktop;
video/flv=vlc.desktop;org.gnome.Totem.desktop;
video/mp2t=vlc.desktop;org.gnome.Totem.desktop;
video/mp4=vlc.desktop;org.gnome.Totem.desktop;
video/mp4v-es=vlc.desktop;org.gnome.Totem.desktop;
video/mpeg-system=vlc.desktop;org.gnome.Totem.desktop;
video/mpeg=vlc.desktop;org.gnome.Totem.desktop;
video/msvideo=vlc.desktop;org.gnome.Totem.desktop;
video/ogg=vlc.desktop;org.gnome.Totem.desktop;
video/quicktime=vlc.desktop;org.gnome.Totem.desktop;
video/vivo=vlc.desktop;org.gnome.Totem.desktop;
video/vnd.avi=vlc.desktop;org.gnome.Totem.desktop;
video/vnd.divx=vlc.desktop;org.gnome.Totem.desktop;
video/vnd.mpegurl=vlc.desktop;org.gnome.Totem.desktop;
video/vnd.rn-realvideo=vlc.desktop;org.gnome.Totem.desktop;
video/vnd.vivo=vlc.desktop;org.gnome.Totem.desktop;
video/webm=vlc.desktop;org.gnome.Totem.desktop;
video/x-anim=vlc.desktop;org.gnome.Totem.desktop;
video/x-avi=vlc.desktop;org.gnome.Totem.desktop;
video/x-flc=vlc.desktop;org.gnome.Totem.desktop;
video/x-fli=vlc.desktop;org.gnome.Totem.desktop;
video/x-flic=vlc.desktop;org.gnome.Totem.desktop;
video/x-flv=vlc.desktop;org.gnome.Totem.desktop;
video/x-m4v=vlc.desktop;org.gnome.Totem.desktop;
video/x-matroska=vlc.desktop;org.gnome.Totem.desktop;
video/x-mjpeg=vlc.desktop;org.gnome.Totem.desktop;
video/x-mpeg-system=vlc.desktop;org.gnome.Totem.desktop;
video/x-mpeg2=vlc.desktop;org.gnome.Totem.desktop;
video/x-mpeg=vlc.desktop;org.gnome.Totem.desktop;
video/x-ms-asf-plugin=vlc.desktop;org.gnome.Totem.desktop;
video/x-ms-asf=vlc.desktop;org.gnome.Totem.desktop;
video/x-ms-asx=vlc.desktop;org.gnome.Totem.desktop;
video/x-ms-wm=vlc.desktop;org.gnome.Totem.desktop;
video/x-ms-wmv=vlc.desktop;org.gnome.Totem.desktop;
video/x-ms-wmx=vlc.desktop;org.gnome.Totem.desktop;
video/x-ms-wvx=vlc.desktop;org.gnome.Totem.desktop;
video/x-msvideo=vlc.desktop;org.gnome.Totem.desktop;
video/x-nsv=vlc.desktop;org.gnome.Totem.desktop;
video/x-ogm+ogg=vlc.desktop;org.gnome.Totem.desktop;
video/x-ogm=vlc.desktop;org.gnome.Totem.desktop;
video/x-theora+ogg=vlc.desktop;org.gnome.Totem.desktop;
video/x-theora=vlc.desktop;org.gnome.Totem.desktop;
video/x-totem-stream=org.gnome.Totem.desktop;
x-scheme-handler/claude-cli=claude-code-url-handler.desktop;
x-scheme-handler/http=firefox.desktop;firefox-esr.desktop;google-chrome.desktop;chromium.desktop;
x-scheme-handler/https=firefox.desktop;firefox-esr.desktop;google-chrome.desktop;chromium.desktop;

9
.config/rofi/README.md Normal file
View file

@ -0,0 +1,9 @@
# `rofi`-related Configurations
This folder contains
the [config](./config.rasi)
and [theme](./theme.rasi)
for the [`rofi`](https://github.com/davatorium/rofi) launcher.
`colors.rasi` is untracked
and written by [`color-palette`](../../.local/bin/color-palette).

48
.config/rofi/config.rasi Normal file
View file

@ -0,0 +1,48 @@
configuration {
/* Bound in ~/.config/gnome-settings/key-bindings.ini:
- <Super>space => drun
+ <Super>d
- <Super><Shift>space => run
+ <Super><Shift>d
- <Super>Tab => window
*/
modes: "combi,drun,window,run";
combi-modes: [ window, drun ];
combi-hide-mode-prefix: true;
font: "Adwaita Sans 12";
show-icons: true;
icon-theme: "Adwaita";
drun-display-format: "{name}";
window-format: "{w} {c} {t}";
matching: "fuzzy";
sort: true;
terminal: "/usr/bin/alacritty";
/* `vi`-style list navigation */
kb-row-down: "Down,Control+j";
kb-row-up: "Up,Control+k";
kb-mode-next: "Shift+Right,Control+l";
kb-mode-previous: "Shift+Left,Control+h";
kb-accept-entry: "Return,KP_Enter";
kb-cancel: "Escape,Control+bracketleft";
kb-remove-char-back: "BackSpace,Shift+BackSpace";
/* Defaults stripped of the keys taken over above */
kb-clear-line: "";
kb-mode-complete: "";
kb-remove-to-eol: "";
kb-row-select: "Tab"; /* Tab completes the selection into the input */
kb-element-next: ""; /* must be freed first - it owns Tab by default */
}
@theme "theme"

80
.config/rofi/theme.rasi Normal file
View file

@ -0,0 +1,80 @@
/* The colors are from the palette in ~/.config/gnome-settings/COLORS.md */
/* => The values below are the "orange" defaults, overridden */
/* at the bottom by the color-palette written import */
* {
accent-c: #ed5b00; /* accent: active accents */
bg-dark: #fceae3; /* base: input bar */
bg: #ebebed; /* chrome: menu surfaces */
border-c: #992600; /* active-border: border */
emphasis-c: #fc6c27; /* emphasis-dim: selected tabs */
fg: #2a0b01; /* text */
fg-a12: rgba(42, 11, 1, 0.12); /* text @ 12%: selected row */
fg-dim: #631200; /* chrome-quiet: quiet text */
background-color: transparent;
text-color: @fg;
}
window {
background-color: @bg;
border: 2px;
border-color: @border-c;
border-radius: 12px; /* == libadwaita, forge */
width: 32em;
padding: 12px;
}
mainbox {
children: [ inputbar, listview, mode-switcher ];
}
inputbar {
background-color: @bg-dark;
border-radius: 8px;
padding: 8px 12px;
children: [ prompt, entry ];
}
prompt { text-color: @fg-dim; margin: 0 8px 0 0; }
entry { placeholder: ""; }
listview {
lines: 6;
spacing: 0.2em;
fixed-height: true;
margin: 12px 0 0 0;
scrollbar: false;
}
element {
padding: 0.6em 0.8em;
border-radius: 8px;
spacing: 0.8em; /* gap between icon and text */
text-color: @fg-dim;
}
element active { text-color: @accent-c; }
element urgent { text-color: @border-c; background-color: @bg-dark; }
element selected {
background-color: @fg-a12;
text-color: @fg;
}
element selected.active { background-color: @emphasis-c; text-color: @fg; }
element-text, element-icon {
background-color: transparent;
text-color: inherit;
}
element-icon { size: 1.8em; }
mode-switcher { margin: 12px 0 0 0; spacing: 8px; }
button {
padding: 4px 10px;
border-radius: 8px;
background-color: @bg-dark;
text-color: @fg-dim;
}
button selected {
background-color: @emphasis-c; /* active tab, like forge */
text-color: @fg;
}
@import "colors"

View file

@ -78,6 +78,21 @@ alias lla='lal'
if _command_exists age; then
alias aged='age -d -i ~/.config/age/identity.txt'
alias agee='age -r age1gzy6tj8y93ljuelcedrkcsv3p6gygk7ng3386u32av9a4ujh737qef8crp'
fi
if _command_exists xclip; then
alias clip='xclip -selection clipboard'
alias clip-out='xclip -selection clipboard -o'
alias c='clip'
fi
if _command_exists git; then
# Manage the bare `git` repository in ~/ holding the dotfiles

View file

@ -1,24 +1,42 @@
#!/bin/sh
# Locale settings for headless machines
# Locale settings for desktop machines
# as run by the author of this `dotfiles` repository
# Requires the en_US.UTF-8, en_DK.UTF-8, en_IE.UTF-8, and de_DE.UTF-8
# locales be installed which is checked by ~/.local/bin/ensure-locales
# Other hosts (e.g., servers) usually lack some of these locales,
# and Debian's /etc/ssh/ssh_config forwards all of them via `SendEnv LANG LC_*`
# => ~/.local/bin/ssh, ~/.local/bin/scp, and ~/.local/bin/sftp
# send `LC_ALL=C.UTF-8` on top to mask them on remote hosts
# Drop what a client may forward over `ssh`,
# because `AcceptEnv LANG LC_*` may be set in /etc/ssh/sshd_config
unset \
LC_ALL \
LC_ADDRESS \
LC_COLLATE \
LC_CTYPE LC_IDENTIFICATION \
LC_MEASUREMENT \
LC_MESSAGES \
LC_MONETARY \
LC_NAME \
LC_NUMERIC \
LC_PAPER \
LC_TELEPHONE \
LC_TIME
export LANG=en_US.UTF-8 # Fallback for any (future) LC_* not set below
# Set every LC_* category implicitly with the `$LANG` fallback
export LANG=C.UTF-8
# Base: US English for language, text handling, and sorting
export LC_COLLATE=en_US.UTF-8 # Dictionary sort order => Ignore punctuation
export LC_CTYPE=en_US.UTF-8 # UTF-8 character classification
export LC_MESSAGES=en_US.UTF-8
export LC_NUMERIC=en_US.UTF-8 # 1,234.56 rather than 1.234,56
# Exceptions: European conventions with English number formatting
export LC_MEASUREMENT=en_IE.UTF-8 # Use the metric system
export LC_MONETARY=en_IE.UTF-8 # Euro with 1,234.56
export LC_PAPER=en_IE.UTF-8 # Use DIN-A4 for a page
export LC_TIME=en_DK.UTF-8 # ISO dates, 24h clock, Monday first
# (German) metadata
export LC_ADDRESS=de_DE.UTF-8 # German postal layout
export LC_IDENTIFICATION=en_US.UTF-8
export LC_NAME=en_US.UTF-8
export LC_TELEPHONE=de_DE.UTF-8 # For "+49" and "030 12345"
export TZ="Europe/Berlin"

View file

@ -7,6 +7,7 @@ if [ "$SHLVL" = 1 ]; then # ~ if on the outermost shell instance
# Clear screen and scrollback without a `terminfo` lookup
# because `clear` fails on hosts that do not know `$TERM`
# (e.g., `alacritty`)
printf '\033[H\033[2J\033[3J'
# On a real Linux `tty`, run `clear_console` for a full reset also

View file

@ -0,0 +1,4 @@
# `systemd` User Units
This folder contains user services and timers,
enabled by [`dotfiles-install`](../../../.local/bin/dotfiles-install).

View file

@ -0,0 +1,12 @@
[Unit]
Description=Restore of the GNOME settings upon login
Before=graphical-session-pre.target
ConditionPathIsDirectory=%h/.config/gnome-settings
[Service]
Environment=FRESH_SESSION=1
Type=oneshot
ExecStart=%h/.local/bin/gnome-restore
[Install]
WantedBy=graphical-session-pre.target

View file

@ -0,0 +1,6 @@
[Unit]
Description=Return "Night Light" to the automatic schedule and default warmth
[Service]
Type=oneshot
ExecStart=%h/.local/bin/night-light-reset

View file

@ -0,0 +1,6 @@
[Timer]
OnCalendar=03:00
Persistent=true
[Install]
WantedBy=timers.target

View file

@ -0,0 +1,13 @@
[Unit]
Description=Set default screen brightness
After=graphical-session.target
ConditionPathExistsGlob=/sys/class/backlight/*
PartOf=graphical-session.target
[Service]
Type=oneshot
ExecStart=%h/.local/bin/set-brightness-default
TimeoutStartSec=30
[Install]
WantedBy=graphical-session.target

View file

@ -0,0 +1,12 @@
[Unit]
Description=Set default keyboard backlight brightness
After=graphical-session.target
PartOf=graphical-session.target
[Service]
Type=oneshot
ExecStart=%h/.local/bin/set-keyboard-brightness-default
TimeoutStartSec=30
[Install]
WantedBy=graphical-session.target

View file

@ -0,0 +1,13 @@
[Unit]
Description=Set default output volume
After=wireplumber.service
PartOf=graphical-session.target
Wants=wireplumber.service
[Service]
Type=oneshot
ExecStart=%h/.local/bin/set-volume-default
TimeoutStartSec=30
[Install]
WantedBy=graphical-session.target

View file

@ -0,0 +1,12 @@
[Unit]
# Works together with "xkb-options" in ~/.config/gnome-settings/misc.ini
Description=Tap Caps Lock (acting as Control) to send Escape
ConditionEnvironment=XDG_SESSION_TYPE=x11
ConditionPathExists=/usr/bin/xcape
[Service]
Type=forking
ExecStart=/usr/bin/xcape -e 'Caps_Lock=Escape'
[Install]
WantedBy=graphical-session.target

View file

@ -0,0 +1,3 @@
Alacritty.desktop
org.gnome.Console.desktop
org.gnome.Terminal.desktop

1106
.local/bin/color-palette Executable file

File diff suppressed because it is too large Load diff

52
.local/bin/dark-scheme-toggle Executable file
View file

@ -0,0 +1,52 @@
#!/bin/sh
# Triggered by <Super><Alt>d
# as defined in [org/gnome/settings-daemon/plugins/media-keys]
# in ~/.config/gnome-settings/key-bindings.ini
set -eu
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
Forge=org.gnome.shell.extensions.forge
Interface=org.gnome.desktop.interface
if [ "$(gsettings get $Interface color-scheme)" = "'prefer-dark'" ]; then
new_theme="light"
else
new_theme="dark"
fi
# Render and apply the palette for the target scheme before flipping,
# so that the visible switch happens in one step
"$HOME/.local/bin/color-palette" --write --scheme "$new_theme"
dconf load / < "$XDG_CONFIG_HOME/gnome-settings/local/palette.ini"
# Set the "color-scheme" explicitly here to be on the safe side
# (although it is also contained in the palette.ini file)
#
# See comments for "color-scheme" under [org/gnome/desktop/interface]
# in ~/.config/gnome-settings/misc.ini
gsettings set $Interface color-scheme "prefer-$new_theme"
# `forge` only re-reads its stylesheet on a restart;
# however, it takes about one second to do so
# gnome-extensions disable forge@jmmaranan.com
# gnome-extensions enable forge@jmmaranan.com
# As a hack, we make `forge` re-read its stylesheet by poking a watched setting
if gnome-extensions list --enabled 2>/dev/null | grep -qxF "forge@jmmaranan.com"; then
_gap=$(gsettings get $Forge window-gap-size | awk '{print $2}')
gsettings set $Forge window-gap-size "uint32 $((_gap + 1))"
gsettings set $Forge window-gap-size "uint32 $_gap"
fi
echo "Switched the color theme to $new_theme"

84
.local/bin/dconf-load Executable file
View file

@ -0,0 +1,84 @@
#!/bin/sh
# Load the ~/.config/gnome-settings[/local]/*.ini files into `dconf`,
# or just the single <file> given as an argument
#
# Unlike ~/.local/bin/gnome-restore this neither backs up nor resets
# anything, so keys removed from the *.ini files stay active
# => Use this for a quick iteration on the *.ini files,
# and `gnome-restore` for a deterministic state
set -eu
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
GNOME_CFG_DIR="$XDG_CONFIG_HOME/gnome-settings"
_usage() {
echo "Usage: $(basename "$0") [<file>]" >&2
exit 1
}
_load() {
# The *.ini files are machine independent and use a placeholder /home/user
echo " $(basename "$1")"
sed "s|/home/user|$HOME|g" "$1" | dconf load /
}
if ! command -v dconf >/dev/null 2>&1; then
echo "dconf is not installed" >&2
exit 1
fi
[ "$#" -le 1 ] || _usage
# A single file, e.g., while iterating on it
if [ "$#" -eq 1 ]; then
if [ ! -f "$1" ]; then
echo "No such file: $1" >&2
exit 1
fi
echo "Loading a single GNOME settings file:"
_load "$1"
exit 0
fi
# Load all *.ini files in ~/.config/gnome-settings[/local]/
if [ ! -d "$GNOME_CFG_DIR" ]; then
echo "No such directory: $GNOME_CFG_DIR" >&2
exit 1
fi
echo "Loading GNOME settings from: $GNOME_CFG_DIR"
for file in "$GNOME_CFG_DIR"/*.ini; do
[ -e "$file" ] || continue # because the glob does not expand if empty
_load "$file"
done
for file in "$GNOME_CFG_DIR"/local/*.ini; do
[ -e "$file" ] || continue # because the glob does not expand if empty
_load "$file"
done

43
.local/bin/dconf-verify Executable file
View file

@ -0,0 +1,43 @@
#!/bin/sh
# List GNOME `dconf` keys that are live but not described by ~/.config/gnome-settings/*.ini
set -eu
# Keep in sync with the `RESET_PATHS` in ~/.local/bin/gnome-restore
# (Note: The `$FILTER` below is a bit more generic than the `RESET_PATHS`)
FILTER='^(org/gnome/|org/gtk/|desktop/ibus/|org/freedesktop/tracker/|ca/desrt/|system/)'
GNOME_CFG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/gnome-settings"
flat() {
awk '/^\[/ { s = substr($0, 2, length($0) - 2); next }
/^[A-Za-z0-9][A-Za-z0-9_-]*=/ { i = index($0, "="); print s "/" substr($0, 1, i - 1) }'
}
live=$(mktemp)
managed=$(mktemp)
trap 'rm -f "$live" "$managed"' EXIT INT TERM
dconf dump / | flat | grep -E "$FILTER" | sort -u > "$live"
find "$GNOME_CFG_DIR" -maxdepth 2 -type f -name '*.ini' -exec cat {} + \
| sed "s|/home/user|$HOME|g" \
| flat | grep -E "$FILTER" | sort -u > "$managed"
echo ""
echo "== Live keys NOT in the ~/.config/gnome-settings/*.ini files =="
comm -23 "$live" "$managed"
echo ""
echo ""
echo "== Keys in the ~/.config/gnome-settings/*.ini files but NOT live =="
comm -13 "$live" "$managed"
echo ""

View file

@ -11,15 +11,17 @@ set -eu
XDG_BIN_HOME="${XDG_BIN_HOME:-$HOME/.local/bin}"
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
# Each branch's first commit sets the default to its own name
# => Overridable via the environment (e.g., done by `dotfiles-update`)
DOTFILES_BRANCH="${DOTFILES_BRANCH:-main}"
DOTFILES_BRANCH="${DOTFILES_BRANCH:-desktop}"
DOTFILES_DIR="${DOTFILES_DIR:-$XDG_DATA_HOME/dotfiles}"
DOTFILES_HTTPS="${DOTFILES_HTTPS:-https://code.webartifex.de/alexander/dotfiles}"
DOTFILES_SSH="${DOTFILES_SSH:-git@git.webartifex.de:alexander/dotfiles.git}"
BACKUPS_DIR="$XDG_STATE_HOME/dotfiles-backups"
BACKUP_DIR="$BACKUPS_DIR/$(date +%Y%m%d-%H%M%S)"
@ -129,6 +131,22 @@ _git checkout --force "$DOTFILES_BRANCH"
_git config --local status.showUntrackedFiles no
# Prefer `ssh` for syncing, but only if this machine may have access,
# which we proxy with the presence of a default private key file
for _key in id_ed25519 id_ecdsa id_rsa; do
if [ -f "$HOME/.ssh/$_key" ]; then
_git remote set-url origin "$DOTFILES_SSH"
echo "The dotfiles now sync via: $DOTFILES_SSH"
break
fi
done
unset _key
locales_ok=1
sh "$XDG_BIN_HOME/ensure-locales" >/dev/null 2>&1 || locales_ok=0
if command -v batcat >/dev/null 2>&1 && ! command -v bat >/dev/null 2>&1; then
ln -sf "$(command -v batcat)" "$XDG_BIN_HOME/bat"
fi
@ -138,6 +156,35 @@ sh "$XDG_BIN_HOME/generate-shell-completions" --quieter \
|| echo "WARN: generating shell completions failed" >&2
if command -v python3 >/dev/null 2>&1; then
python3 -m \
pip install \
--user \
--upgrade \
--break-system-packages \
coloraide \
rofimoji \
|| echo "WARN: pip install failed" >&2
python3 "$XDG_BIN_HOME/color-palette" --write \
|| echo "WARN: color-palette failed" >&2
fi
if systemctl --user daemon-reload 2>/dev/null; then
systemctl --user enable gnome-restore.service
systemctl --user enable night-light-reset.timer
systemctl --user enable set-brightness-default.service
systemctl --user enable set-keyboard-brightness-default.service
systemctl --user enable set-volume-default.service
systemctl --user enable xcape.service
else
echo "WARN: no systemd user session, units not enabled" >&2
fi
# Keep only the most recent backups
_keep=10
if [ -d "$BACKUPS_DIR" ]; then
@ -152,6 +199,13 @@ fi
echo ""
echo "The dotfiles were installed successfully (branch: $DOTFILES_BRANCH)"
echo ""
if [ "$locales_ok" -ne 1 ]; then
echo "WARNING: Some locales are missing, fix:"
echo " sudo $XDG_BIN_HOME/ensure-locales"
echo ""
fi
echo "Reload your shell to use them:"
echo " exec \$SHELL -l"
echo ""

112
.local/bin/ensure-locales Executable file
View file

@ -0,0 +1,112 @@
#!/bin/sh
# Ensure all locales specified in ~/.config/shell/locale are installed
set -eu
LOCALES="en_US.UTF-8 de_DE.UTF-8 en_DK.UTF-8 en_IE.UTF-8"
# Because `locale -a` prints, for example, "en_US.utf8",
# and `locale.gen` wants "en_US.UTF-8" instead
_locale_present() {
norm=$(printf '%s' "$1" | tr 'A-Z' 'a-z' | tr -d '-')
locale -a 2>/dev/null | tr 'A-Z' 'a-z' | tr -d '-' | grep -qx "$norm"
}
# In most cases there should be no missing `$LOCALES`
missing=""
for l in $LOCALES; do
_locale_present "$l" || missing="$missing $l"
done
if [ -z "$missing" ]; then
echo ""
echo "All locales present"
echo ""
exit 0
fi
# If there are missing `$LOCALES`, just notify the user
# because this script most likely was run as part of `dotfiles-install`
# and therefore without root privileges
if [ "$(id -u)" != 0 ]; then
self=$(cd "$(dirname "$0")" && pwd)/$(basename "$0")
echo "" >&2
echo "Missing locales:$missing" >&2
echo "" >&2
echo "Fix with: sudo $self" >&2
echo "" >&2
exit 1
fi
# Install the missing `$LOCALES`
if ! command -v locale-gen >/dev/null 2>&1; then
echo "" >&2
echo "locale-gen not found, generate manually:" >&2
echo "" >&2
for l in $missing; do
echo " localedef -i ${l%.*} -f UTF-8 $l" >&2
done
echo "" >&2
exit 1
fi
[ -f /etc/locale.gen ] || : > /etc/locale.gen
for l in $missing; do
# Uncomment existing line, or append if not present at all
esc=$(printf '%s' "$l" | sed 's/\./\\./g')
if grep -qE "^#? *$esc UTF-8" /etc/locale.gen; then
sed -i "s/^# *\($esc UTF-8\)/\1/" /etc/locale.gen
else
printf '%s UTF-8\n' "$l" >> /etc/locale.gen
fi
done
locale-gen
# verify all missing `$LOCALES` were installed
rc=0
for l in $missing; do
_locale_present "$l" || {
echo "Failed to generate: $l" >&2;
rc=1;
}
done
exit $rc

View file

@ -0,0 +1,30 @@
#!/bin/sh
# Raise Evolution and switch to its workspace,
# or switch to the target workspace first and launch it there
#
# Switching before the launch avoids the flicker that
# `auto-move-windows` causes by relocating an already mapped window
#
# Note that `auto-move-windows` must not also manage Evolution,
# or both mechanisms fight over the placement
set -eu
_CLASS=evolution
_COMMAND=/usr/bin/evolution
# This is the last of the 10 named but 0-based workspaces
# in "num-workspaces" under [org/gnome/desktop/wm/preferences]
_WORKSPACE=9
# "wmctrl -x -a" already switches to the window's workspace
wmctrl -x -a "$_CLASS" && exit 0
wmctrl -s "$_WORKSPACE"
exec "$_COMMAND"

189
.local/bin/gdm-settings-sync Executable file
View file

@ -0,0 +1,189 @@
#!/bin/sh
# Install the GDM greeter's `dconf` settings into /etc/dconf/db/gdm.d/
#
# The keys listed in `$MIRROR_PATHS` below are read from
# the live user session and written as one keyfile
#
# The greeter runs as the `Debian-gdm` user and never sees
# the user-level settings in ~/.config/gnome-settings/*.ini
#
# The keyfile is written, not symlinked,
# so that the greeter does not depend on ~/ being readable
#
# Without root privileges, this script only checks and reports
# => Run with `sudo` to install
set -eu
SELF_DIR=$(cd "$(dirname "$0")" && pwd)
TARGET_DIR=/etc/dconf/db/gdm.d
COMPILED_DB=/etc/dconf/db/gdm
# Only files with this prefix are managed (and pruned) here
PREFIX=90-dotfiles-
MIRRORED=mirrored
# Keys mirrored from the live user session into the GDM greeter
#
# One absolute `dconf` path per line
# => Unset keys are skipped, so the greeter keeps its defaults
MIRROR_PATHS='
# Idle and power
#
# Only the AC keys => On battery, the greeter keeps suspending
/org/gnome/desktop/session/idle-delay
/org/gnome/settings-daemon/plugins/power/idle-brightness
/org/gnome/settings-daemon/plugins/power/idle-dim
/org/gnome/settings-daemon/plugins/power/power-saver-profile-on-low-battery
/org/gnome/settings-daemon/plugins/power/sleep-inactive-ac-timeout
/org/gnome/settings-daemon/plugins/power/sleep-inactive-ac-type
# Would disarm the physical power button at the greeter as well
# /org/gnome/settings-daemon/plugins/power/power-button-action
# Keyboard (e.g., Caps Lock as Control while typing the password)
/org/gnome/desktop/input-sources/sources
/org/gnome/desktop/input-sources/xkb-options
/org/gnome/desktop/peripherals/keyboard/numlock-state
# Touchpad and mouse
/org/gnome/desktop/peripherals/mouse/natural-scroll
/org/gnome/desktop/peripherals/touchpad/natural-scroll
/org/gnome/desktop/peripherals/touchpad/tap-to-click
# Top bar
/org/gnome/desktop/interface/accent-color
/org/gnome/desktop/interface/clock-format
/org/gnome/desktop/interface/clock-show-date
/org/gnome/desktop/interface/clock-show-seconds
/org/gnome/desktop/interface/clock-show-weekday
/org/gnome/desktop/interface/show-battery-percentage
'
if ! command -v gdm3 >/dev/null 2>&1 && [ ! -d /etc/gdm3 ]; then
echo "GDM is not installed => Nothing to do"
exit 0
fi
if ! command -v dconf >/dev/null 2>&1; then
echo "dconf is not installed" >&2
exit 1
fi
# As root, the live settings must come from the invoking user
if [ "$(id -u)" = 0 ] && [ "${SUDO_USER:-root}" = "root" ]; then
echo "Run via sudo from the user whose settings to mirror" >&2
exit 1
fi
# The mirrored paths, without comments and blank lines
_mirror_paths() {
printf '%s\n' "$MIRROR_PATHS" | grep -Ev '^[[:space:]]*(#|$)' | sort -u
}
# `dconf read` as the session user, also when run via `sudo`
# (reads need no D-Bus, only the user's database file)
_dconf_read() {
if [ "$(id -u)" = 0 ]; then
_home=$(getent passwd "$SUDO_USER" | cut -d: -f6)
runuser -u "$SUDO_USER" -- env \
HOME="$_home" \
XDG_CONFIG_HOME="$_home/.config" \
XDG_RUNTIME_DIR="/run/user/$(id -u "$SUDO_USER")" \
dconf read "$1"
else
dconf read "$1"
fi
}
_render_mirrored() {
echo "# Written by gdm-settings-install from the live user session - do not edit"
_mirror_paths | while IFS= read -r path; do
_value=$(_dconf_read "$path")
[ -n "$_value" ] || continue # Unset => Keep the greeter's default
_dir=${path%/*}
_dir=${_dir#/}
if [ "$_dir" != "${_last:-}" ]; then
printf '\n[%s]\n' "$_dir"
_last=$_dir
fi
printf '%s=%s\n' "${path##*/}" "$_value"
done
}
_in_sync() {
[ -f "$COMPILED_DB" ] || return 1
_render_mirrored | cmp -s - "$TARGET_DIR/$PREFIX$MIRRORED" || return 1
# No other managed file may be left over (e.g., from older versions)
for dst in "$TARGET_DIR/$PREFIX"*; do
[ -e "$dst" ] || continue
[ "${dst##*/$PREFIX}" = "$MIRRORED" ] || return 1
done
# The compiled database must be newer than the keyfiles
[ -z "$(find "$TARGET_DIR" -newer "$COMPILED_DB" 2>/dev/null)" ]
}
if _in_sync; then
echo "GDM settings are up to date"
exit 0
fi
if [ "$(id -u)" != 0 ]; then
echo "" >&2
echo "GDM settings are not installed or outdated" >&2
echo "" >&2
echo "Fix with: sudo $SELF_DIR/$(basename "$0")" >&2
echo "" >&2
exit 1
fi
mkdir -p "$TARGET_DIR"
for dst in "$TARGET_DIR/$PREFIX"*; do
[ -e "$dst" ] || continue
[ "${dst##*/$PREFIX}" = "$MIRRORED" ] || rm -v -- "$dst"
done
_rendered=$(mktemp)
trap 'rm -f "$_rendered"' EXIT
_render_mirrored > "$_rendered"
install -v -m 644 -- "$_rendered" "$TARGET_DIR/$PREFIX$MIRRORED"
dconf update
# Debian's `gdm` profile must read the "gdm" system database
if ! grep -qs '^system-db:gdm$' /etc/dconf/profile/gdm /usr/share/dconf/profile/gdm; then
echo "WARN: no dconf profile for gdm reads system-db:gdm" >&2
fi
echo "Installed the GDM settings into: $TARGET_DIR"
echo "They take effect at the next start of the greeter (e.g., reboot)"

141
.local/bin/gnome-restore Executable file
View file

@ -0,0 +1,141 @@
#!/bin/sh
# Restore the GNOME settings from ~/.config/gnome-settings/*.ini
#
# `dconf load` merges into the existing state, implying
# that keys removed from the *.ini files would still be active
# => Reset the subtrees we fully manage first,
# which makes the resulting state deterministic
set -eu
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
BACKUP_DIR="$XDG_STATE_HOME/gnome-settings-backups"
GNOME_CFG_DIR="$XDG_CONFIG_HOME/gnome-settings"
# Subtrees either
# - fully described by the *.ini files
# - or reset to their defaults
#
# Notes:
# - Keep in sync with the `grep`s in ~/.local/bin/dconf-verify
# - "/org/freedesktop/tracker/" is exempted as we think resetting it
# makes `localsearch3` re-index everything from scratch
RESET_PATHS="
/ca/desrt/dconf-editor/
/desktop/ibus/
/org/gnome/baobab/
/org/gnome/calculator/
/org/gnome/calendar/
/org/gnome/Characters/
/org/gnome/clocks/
/org/gnome/Connections/
/org/gnome/Contacts/
/org/gnome/control-center/
/org/gnome/desktop/
/org/gnome/Disks/
/org/gnome/evince/
/org/gnome/Extensions/
/org/gnome/file-roller/
/org/gnome/gedit/
/org/gnome/gnome-system-monitor/
/org/gnome/Loupe/
/org/gnome/maps/
/org/gnome/mutter/
/org/gnome/nautilus/
/org/gnome/nm-applet/
/org/gnome/portal/
/org/gnome/settings-daemon/
/org/gnome/shell/
/org/gnome/simple-scan/
/org/gnome/software/
/org/gnome/system/location/
/org/gnome/terminal/
/org/gnome/TextEditor/
/org/gnome/Totem/
/org/gnome/tweaks/
/org/gnome/Weather/
/org/gnome/GWeather4/
/org/gtk/
/system/
"
if ! command -v dconf >/dev/null 2>&1; then
echo "dconf is not installed => Nothing to do" >&2
exit 0
fi
if [ ! -d "$GNOME_CFG_DIR" ]; then
echo "No settings found at: $GNOME_CFG_DIR" >&2
exit 1
fi
echo "Backing up current GNOME settings to: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
dconf dump / > "$BACKUP_DIR/$(date +%Y%m%d-%H%M%S).ini"
# Keep the ten most recent backups
# shellcheck disable=SC2012 # File names are timestamps => `ls` is safe
ls -1t "$BACKUP_DIR"/*.ini | tail -n +11 | xargs -r rm --
# Remove temporary background image files
# created by ~/.local/bin/randomize-background
if [ "${FRESH_SESSION:-}" = "1" ]; then
echo "Removing session-scoped background image files"
rm -f "$XDG_CONFIG_HOME/gnome-settings/local/temporary_background.ini"
find "$XDG_DATA_HOME/backgrounds" -name '*-tmp-*.jpg' -delete 2>/dev/null || true
fi
echo "Resetting managed subtrees in dconf"
for path in $RESET_PATHS; do
echo " $path"
dconf reset -f "$path"
done
# forge's `patchCss()` writes its stylesheet backup to a path built from a
# property that no longer exists, yielding "~/undefined.bak"
# => Patch the path in the installed extension
THEME_JS="$XDG_DATA_HOME/gnome-shell/extensions/forge@jmmaranan.com/lib/shared/theme.js"
if [ -w "$THEME_JS" ]; then
sed -i 's|this\.configMgr\.stylesheetFileName + "\.bak"|configCss.get_path() + ".bak"|' "$THEME_JS"
fi
echo "Import GNOME extensions' schemas"
SCHEMAS="$HOME/.local/bin/gnome-shell-extensions-schemas-import"
if [ -x "$SCHEMAS" ]; then
"$SCHEMAS" || echo "WARN: importing GNOME extension schemas failed" >&2
fi
LOAD="$HOME/.local/bin/dconf-load"
if [ -x "$LOAD" ]; then
"$LOAD"
else
echo "ERROR: $LOAD is missing" >&2
exit 1
fi
echo "Restored GNOME to the defaults defined in ~/.config/gnome-settings"

View file

@ -0,0 +1,49 @@
#!/bin/sh
# Install `forge` from source into the same place that
# https://extensions.gnome.org/extension/4481/forge/ would use
#
# The released version may break "window-toggle-float"
# (see https://github.com/forge-ext/forge/issues/492)
# and is not maintained at the moment
#
# A re-login is required afterwards,
# because `gnome-shell` only scans the extensions directory on startup
set -eu
_UUID=forge@jmmaranan.com
_REPO=https://github.com/forge-ext/forge.git
_TARGET="${XDG_DATA_HOME:-$HOME/.local/share}/gnome-shell/extensions/$_UUID"
for _tool in git make glib-compile-schemas msgfmt xgettext; do
command -v "$_tool" >/dev/null || {
echo "ERROR: $_tool is missing (try: apt install git make libglib2.0-bin gettext)" >&2
exit 1
}
done
_workdir=$(mktemp -d)
trap 'rm -rf "$_workdir"' EXIT
git clone --depth 1 "$_REPO" "$_workdir"
_commit=$(git -C "$_workdir" rev-parse --short HEAD)
make -C "$_workdir" build
rm -rf "$_TARGET"
make -C "$_workdir" install
echo "Installed $_UUID from $_commit into $_TARGET"
echo "Log out and back in, then: gnome-extensions enable $_UUID"

View file

@ -0,0 +1,34 @@
#!/bin/sh
# Make the `GSettings` schemas of all user-installed GNOME Shell extensions
# visible to a plain `gsettings`, by symlinking the *.gschema.xml files
# into the user schema directory and compiling them
#
# Idempotent: Re-running refreshes the links, prunes dangling ones
# (e.g., from removed extensions), and recompiles
set -eu
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
EXTENSIONS_DIR="$XDG_DATA_HOME/gnome-shell/extensions"
SCHEMAS_DIR="$XDG_DATA_HOME/glib-2.0/schemas"
mkdir -p "$SCHEMAS_DIR"
# Prune symlinks whose target no longer exists
find "$SCHEMAS_DIR" -maxdepth 1 -type l ! -exec test -e {} \; -exec rm -v -- {} \;
# Link every schema shipped by an extension
for xml in "$EXTENSIONS_DIR"/*/schemas/*.gschema.xml; do
[ -e "$xml" ] || continue # because the glob does not expand if empty
echo " $(basename "$xml")"
ln -sf -- "$xml" "$SCHEMAS_DIR/"
done
glib-compile-schemas "$SCHEMAS_DIR"

75
.local/bin/gnome-shell-restart Executable file
View file

@ -0,0 +1,75 @@
#!/bin/sh
# Restart `gnome-shell` in place,
# preserving the session and all windows
#
# Usually survives, but treat it like a logout:
# save your work first, because a crash on the way down can end the session
#
# Debian normally forbids starting/stopping this unit by hand;
# we allow it via a user-level drop-in (installed on first run)
set -eu
if [ "${XDG_SESSION_TYPE:-}" != "x11" ]; then
echo "gnome-shell-restart: only works on X11, not on ${XDG_SESSION_TYPE:-unknown}" >&2
exit 1
fi
_UNIT="org.gnome.Shell@x11.service"
_DROPIN_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/$_UNIT.d"
_DROPIN_FILE="$_DROPIN_DIR/allow-restart.conf"
if [ ! -f "$_DROPIN_FILE" ] || ! grep -q "SuccessExitStatus" "$_DROPIN_FILE"; then
mkdir -p "$_DROPIN_DIR"
cat > "$_DROPIN_FILE" << 'EOF'
# Written by ~/.local/bin/gnome-shell-restart
# Debian forbids starting and stopping this unit by hand
# to protect Wayland sessions, where the shell cannot restart in place
# => We are on X11
[Unit]
RefuseManualStart=no
RefuseManualStop=no
# The old shell sometimes crashes while shutting down.
#
# Without this line, `systemd` treats that crash as a real failure
# and ends the whole session (i.e., logs us out)
#
# => We count a segfault as a normal exit
#
# If the shell truly keeps crashing, the start limit still ends the session
[Service]
SuccessExitStatus=1 SEGV
EOF
systemctl --user daemon-reload
fi
# The unit allows at most 3 starts per 15 seconds
# and one restart too many counts as a failure and logs us out
# => Refuse to restart again too soon after the last one
_STARTED="$(systemctl --user show -p ActiveEnterTimestamp --value "$_UNIT")"
if [ -n "$_STARTED" ]; then
_AGE=$(( $(date +%s) - $(date -d "$_STARTED" +%s) ))
if [ "$_AGE" -lt 20 ]; then
echo "gnome-shell-restart: last shell start was only ${_AGE}s ago" >&2
echo "gnome-shell-restart: refusing to trip the start limit (wait $(( 20 - _AGE ))s)" >&2
exit 1
fi
fi
# Forget any earlier failure, so it does not block this restart
systemctl --user reset-failed "$_UNIT" 2> /dev/null || true
exec systemctl --user restart "$_UNIT"

78
.local/bin/key-bindings Executable file
View file

@ -0,0 +1,78 @@
#!/bin/sh
# Show the key bindings from ~/.config/gnome-settings/key-bindings.ini,
# one binding per line, flattened from the comment tables in that file
#
# The key column comes first and the search input is prefilled with "^",
# so that a typed pattern only matches the key column
set -eu
INI="${XDG_CONFIG_HOME:-$HOME/.config}/gnome-settings/key-bindings.ini"
awk -F '|' '
/^# .*\|/ {
sub(/^# ?/, "")
for (i = 1; i <= NF; i++) gsub(/^[ \t]+|[ \t]+$/, "", $i)
key = $1
if (key == "Key(s)") { # Header of the <Super> table
mode = "layers"
for (i = 2; i <= NF; i++) mod[i] = $i
next
}
if (key == "Key") { # Header of the browser table
mode = "browser"
next
}
if (mode == "" || key ~ /^[-+]+$/) next
# Every line starts with a layer rank used by `sort` below:
# 1 <Super>, 2 <Super><Shift>, 3 <Super><Control>,
# 4 <Super><Alt>, 5 <Super><Alt><Shift>, 6 browser bindings
if (mode == "browser") {
if (key == "") next
k = split(key, parts, ">")
line[++n] = sprintf("6 %-17s %-20s %s: %s", parts[k],
substr(key, 1, length(key) - length(parts[k])), $2, $3)
next
}
if (key == "") { # Row without a key => prefix or continuation
for (i = 2; i <= NF; i++) {
cell = $i
if (cell == "") continue
if (cell ~ /^\.\.\./) { # Continues the row above
sub(/^\.\.\. */, "", cell)
sub(/ \.\.\.$/, "", line[last[i]])
line[last[i]] = line[last[i]] " " cell
} else { # Prefix for the rows below
sub(/ \.\.\.$/, "", cell)
prefix[i] = cell
}
}
next
}
for (i = 2; i <= NF; i++) {
cell = $i
if (cell == "") continue
if (cell ~ /^\.\.\./) {
sub(/^\.\.\. */, "", cell)
cell = prefix[i] " " cell
}
line[++n] = sprintf("%d %-17s %-20s %s", i - 1, key, mod[i], cell)
last[i] = n
}
}
END { for (i = 1; i <= n; i++) print line[i] }
' "$INI" \
| LC_ALL=C sort -s -f -k2,2 -k1,1n \
| cut -d ' ' -f 2- \
| rofi -dmenu -i -p keys -no-custom -matching regex -filter '^' -no-sort \
-theme-str '* { font: "FiraCode Nerd Font 10"; } window { width: 60em; } listview { lines: 20; }' \
>/dev/null

View file

@ -0,0 +1,49 @@
#!/bin/sh
# Move the active window to the first empty workspace and follow it
#
# Note: This assumes that only the main monitor has workspaces enabled
set -eu
active=$(xprop -root _NET_ACTIVE_WINDOW | awk '{print $NF}')
desktop=$(xprop -id "$active" _NET_WM_DESKTOP 2>/dev/null | awk '{print $NF}')
# 4294967295 (i.e., 0xFFFFFFFF) means "on all workspaces",
# which is what `mutter` reports for windows on secondary monitors
# when "workspaces-only-on-primary" is true
if [ "$desktop" = "4294967295" ] || [ -z "$desktop" ]; then
command -v notify-send >/dev/null \
&& notify-send 'Window Management' 'Active window is not on a workspace on the main screen'
exit 1
fi
occupied_workspaces=$(wmctrl -l) || exit 1 # fail safe
occupied_workspaces=$(echo "$occupied_workspaces" | awk '{print $2}' | sort -u)
total=$(wmctrl -d | wc -l)
# 0-based index for the first workspace
i=0
while [ "$i" -lt "$total" ]; do
if ! echo "$occupied_workspaces" | grep -qx "$i"; then
wmctrl -r :ACTIVE: -t "$i"
wmctrl -s "$i"
exit 0
fi
i=$((i + 1))
done
command -v notify-send >/dev/null \
&& notify-send 'Window Management' 'No empty workspace available'
exit 1

162
.local/bin/nextcloud-restore Executable file
View file

@ -0,0 +1,162 @@
#!/bin/sh
# This script ensures my `nextcloud` clients operate in a uniform way
set -eu
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
NEXTCLOUD_CFG="${XDG_CONFIG_HOME:-$HOME/.config}/Nextcloud/nextcloud.cfg"
SERVER_URL_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/Nextcloud/server.txt"
if [ -r "$SERVER_URL_FILE" ]; then
# `tr` strips spaces, tabs, and CR/LF
SERVER_URL=$(head -n 1 "$SERVER_URL_FILE" | tr -d '[:space:]')
else
SERVER_URL=""
fi
[ "${1:-}" = "--force" ] && force=1 || force=0
if [ -z "$SERVER_URL" ]; then
if [ "$force" -eq 1 ]; then
echo "" >&2
echo "WARN: No usable server URL at $SERVER_URL_FILE, leaving the server URL unmanaged" >&2
echo "" >&2
else
echo "" >&2
echo "No usable server URL found at $SERVER_URL_FILE" >&2
echo "" >&2
echo "Create it with a single line, e.g., 'https://cloud.example.com'," >&2
echo "or re-run with --force to skip the URL settings" >&2
echo "" >&2
exit 1
fi
fi
if ! command -v crudini >/dev/null 2>&1; then
echo "crudini is not installed => cannot configure nextcloud" >&2
exit 1
fi
if ! command -v nextcloud >/dev/null 2>&1; then
echo "Nextcloud is not installed" >&2
exit 1
fi
del_key() { # section key
crudini --del "$NEXTCLOUD_CFG" "$1" "$2"
}
set_key() { # section key value
crudini --set "$NEXTCLOUD_CFG" "$1" "$2" "$3"
}
# Stop `nextcloud`
nextcloud --quit 2>/dev/null || true
for _ in $(seq 30); do
pgrep -x nextcloud >/dev/null || break
sleep 0.5
done
if pgrep -x nextcloud >/dev/null; then
echo "Nextcloud did not exit; aborting" >&2
exit 1
fi
mkdir -p "$(dirname "$NEXTCLOUD_CFG")"
touch "$NEXTCLOUD_CFG"
# Configure base settings for `nextcloud`
if [ -n "$SERVER_URL" ]; then
set_key General forceOverrideServerUrl true
set_key General overrideServerUrl "$SERVER_URL"
fi
set_key General overrideLocalDir "$HOME/Cloud"
set_key General launchOnSystemStartup true
set_key General monoIcons true
set_key General crashReporter false
# Windows-only, kept for completeness
set_key General showInExplorerNavigationPane true
set_key General optionalServerNotifications false
set_key General showCallNotifications false
set_key General showChatNotifications false
set_key General isVfsEnabled false # `true` is also not good for `gocryptfs` syncs
set_key General confirmExternalStorage true
set_key General useNewBigFolderSizeLimit false
set_key General newBigFolderSizeLimit 999
set_key General notifyExistingFoldersOverLimit false
set_key General stopSyncingExistingFoldersOverLimit false
set_key General moveToTrash true
set_key General promptDeleteAllFiles true
set_key Proxy type 0
# Make `nextcloud` sync at full speed, with sane fallback limits
# Modes:
# - 0 => unlimited
# - -1 => automatic limit
# - +1 => manually set limit
# Limits:
# - values are in KBytes/s
# - we assume line speeds of 100/30 Mbit/s, to be capped at 80%
set_key BWLimit useDownloadLimit 0
# 100 Mbit/s / 8 => 12500 KBytes/s * 0.8 => 10000
set_key BWLimit downloadLimit 10000
set_key BWLimit useUploadLimit 0
# 30 Mbit/s / 8 => 3750 KBytes/s * 0.8 => 3000
set_key BWLimit uploadLimit 3000
set_key Nextcloud remotePollInterval 60000
# Because of a bug, `nextcloud` wants to create logs at a deprecated location
# => An empty file at that location makes `nextcloud` use the new location
# inside ~/.config/Nextcloud
rm -rf "$XDG_DATA_HOME/Nextcloud"
touch "$XDG_DATA_HOME/Nextcloud"
# Resume `nextcloud`
setsid nextcloud --background >/dev/null 2>&1 &

View file

@ -0,0 +1,88 @@
#!/bin/sh
# Triggered by <Super><Alt>bracketleft
# as defined in [org/gnome/settings-daemon/plugins/media-keys]
# in ~/.config/gnome-settings/key-bindings.ini
#
# This script makes the screen a bit cooler than it currently is,
# unless it is currently in a ramping phase and not fully tinted
#
# The default warmth is restored at login by ~/.local/bin/gnome-restore
set -eu
# GNOME's GUI lets one choose between 1700 and 4700 only,
# and 6500 is the point where no color correction is applied at all
# while 1000 is the absolute minimum supported by the OS
_MIN_TEMPERATURE=1200
_MAX_TEMPERATURE=4700
notify() {
ID_FILE="${XDG_RUNTIME_DIR}/night-light-notification-id"
_id=$(cat "$ID_FILE" 2>/dev/null || true)
if [ -n "$_id" ]; then
notify-send -p -t 5000 --replace-id="$_id" "Night Light" "$1" > "$ID_FILE" || rm -f "$ID_FILE"
else
notify-send -p -t 5000 "Night Light" "$1" > "$ID_FILE" || rm -f "$ID_FILE"
fi
}
Schema=org.gnome.settings-daemon.plugins.color
active=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color NightLightActive)
applied=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color Temperature \
| sed -E 's/.*uint32 ([0-9]+).*/\1/')
automatic=$(gsettings get $Schema night-light-schedule-automatic)
current=$(gsettings get $Schema night-light-temperature | awk '{print $2}')
# Cooling never turns "Night Light" on
if [ "$active" = "(<false>,)" ]; then
notify "is not tinting the screen right now (target: ${current}K)"
exit 0
fi
# While the screen is not (fully) tinted,
# stepping the target has no visible effect
# => Only show what is going on
if [ "$automatic" = "true" ] && [ $((applied - current)) -gt 300 ]; then
notify "is still following the schedule's ramp (target: ${current}K)"
exit 0
fi
# Walking past the cool end switches the feature off
if [ "$current" -ge $_MAX_TEMPERATURE ]; then
gsettings set $Schema night-light-enabled false
notify "is now off (stepped past ${_MAX_TEMPERATURE}K)"
exit 0
fi
# 500 = (4700 - 1700 + 500) / 7
# => Seven steps spanning more than the range in the GUI,
# mainly because we want to allow a bit more warmth (i.e., +500)
new=$((current + 500))
if [ "$new" -gt $_MAX_TEMPERATURE ]; then
new=$_MAX_TEMPERATURE
fi
gsettings set $Schema night-light-temperature "uint32 $new"

View file

@ -0,0 +1,102 @@
#!/bin/sh
# Triggered by <Super><Alt>bracketright
# as defined in [org/gnome/settings-daemon/plugins/media-keys]
# in ~/.config/gnome-settings/key-bindings.ini
#
# This script ensures "Night Light" is forced on
# or makes the screen a bit warmer than it currently is
#
# The default warmth is restored at login by ~/.local/bin/gnome-restore
set -eu
# GNOME's GUI lets one choose between 1700 and 4700 only,
# and 6500 is the point where no color correction is applied at all
# while 1000 is the absolute minimum supported by the OS
_MIN_TEMPERATURE=1200
_MAX_TEMPERATURE=4700
_DEFAULT_TEMPERATURE=2200
notify() {
ID_FILE="${XDG_RUNTIME_DIR}/night-light-notification-id"
_id=$(cat "$ID_FILE" 2>/dev/null || true)
if [ -n "$_id" ]; then
notify-send -p -t 5000 --replace-id="$_id" "Night Light" "$1" > "$ID_FILE" || rm -f "$ID_FILE"
else
notify-send -p -t 5000 "Night Light" "$1" > "$ID_FILE" || rm -f "$ID_FILE"
fi
}
Schema=org.gnome.settings-daemon.plugins.color
active=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color NightLightActive)
applied=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color Temperature \
| sed -E 's/.*uint32 ([0-9]+).*/\1/')
automatic=$(gsettings get $Schema night-light-schedule-automatic)
current=$(gsettings get $Schema night-light-temperature | awk '{print $2}')
if [ "$active" = "(<true>,)" ] \
&& { [ "$automatic" = "false" ] || [ $((applied - current)) -le 300 ]; }; then
at_target=true
else
at_target=false
fi
# Step only if the screen already shows the target tint
# while off or ramping in, forcing on below provides the warming already
if [ "$at_target" = "true" ]; then
# 500 = (4700 - 1700 + 500) / 7
# => Seven steps spanning more than the range in the GUI,
# mainly because we want to allow a bit more warmth (i.e., +500)
new=$((current - 500))
if [ "$new" -lt $_MIN_TEMPERATURE ]; then
new=$_MIN_TEMPERATURE
fi
gsettings set $Schema night-light-temperature "uint32 $new"
# Untinted and parked at a cool target
# => Forcing on would barely show otherwise
elif [ "$active" = "(<false>,)" ] && [ "$current" -gt $_DEFAULT_TEMPERATURE ]; then
gsettings set $Schema night-light-temperature "uint32 $_DEFAULT_TEMPERATURE"
fi
# Always force "Night Light" on, saving a <Super><Alt>backslash call,
# with the same settings as in ~/.local/bin/night-light-toggle-schedule
if [ "$active" = "(<false>,)" ] || [ "$automatic" = "true" ]; then
gsettings set $Schema night-light-enabled true
gsettings set $Schema night-light-schedule-automatic false
gsettings set $Schema night-light-schedule-from 0.0
gsettings set $Schema night-light-schedule-to 24.0
fi
# Notify only if the press produced no visible change
# (i.e., already at the minimum and not just snapped to full warmth by the force)
if [ "$at_target" = "true" ] && [ "$current" -le $_MIN_TEMPERATURE ]; then
notify "is already as warm as it gets (${_MIN_TEMPERATURE}K)"
fi

25
.local/bin/night-light-reset Executable file
View file

@ -0,0 +1,25 @@
#!/bin/sh
# Ensure "Night Light" is enabled,
# set to run according to the automatic schedule,
# and reverted to the `_DEFAULT_TEMPERATURE`
#
# Intended to be run at 03:00 by the `night-light-reset.timer` systemd
# user unit, so that a forced state does not persist
#
# See ~/.local/bin/night-light-toggle-schedule for detailed documentation
set -eu
_DEFAULT_TEMPERATURE=2200
Schema=org.gnome.settings-daemon.plugins.color
gsettings set $Schema night-light-enabled true
gsettings set $Schema night-light-schedule-automatic true
gsettings set $Schema night-light-schedule-from 18.0
gsettings set $Schema night-light-schedule-to 6.0
gsettings set $Schema night-light-temperature "uint32 $_DEFAULT_TEMPERATURE"

View file

@ -0,0 +1,75 @@
#!/bin/sh
# Triggered by <Super><Alt><Shift>backslash
# as defined in [org/gnome/settings-daemon/plugins/media-keys]
# in ~/.config/gnome-settings/key-bindings.ini
#
# See ~/.local/bin/night-light-toggle-schedule
# for the other half of the toggling logic
# and extensive documentation
set -eu
notify() {
ID_FILE="${XDG_RUNTIME_DIR}/night-light-notification-id"
_id=$(cat "$ID_FILE" 2>/dev/null || true)
if [ -n "$_id" ]; then
notify-send -p -t 5000 --replace-id="$_id" "Night Light" "$1" > "$ID_FILE" || rm -f "$ID_FILE"
else
notify-send -p -t 5000 "Night Light" "$1" > "$ID_FILE" || rm -f "$ID_FILE"
fi
}
Schema=org.gnome.settings-daemon.plugins.color
if [ "$(gsettings get $Schema night-light-enabled)" = "true" ]; then
active_before=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color NightLightActive)
gsettings set $Schema night-light-enabled false
if [ "$active_before" = "(<false>,)" ]; then
notify "is now disabled, but the screen was not tinted anyways"
fi
else
gsettings set $Schema night-light-enabled true
# We could start from our default warmth, as defined
# in [org/gnome/settings-daemon/plugins/color]
# in ~/.config/gnome-settings/misc.ini
# but choose not to do that because this is meant to be
# a plain on/off switch with no side effects
# => Snapping is left to <Super><Alt>bracketright, which is about
# warmth rather than about the feature being on or off
#
# _DEFAULT_TEMPERATURE=2200
# current=$(gsettings get $Schema night-light-temperature | awk '{print $2}')
#
# if [ "$current" -gt $_DEFAULT_TEMPERATURE ]; then
# gsettings set $Schema night-light-temperature "uint32 $_DEFAULT_TEMPERATURE"
# fi
# Give the settings daemon a moment to recompute "NightLightActive"
sleep 0.1
active_after=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color NightLightActive)
if [ "$active_after" = "(<false>,)" ]; then
notify "is now enabled, but the schedule keeps it off for now"
fi
fi

View file

@ -0,0 +1,145 @@
#!/bin/sh
# Triggered by <Super><Alt>backslash
# as defined in [org/gnome/settings-daemon/plugins/media-keys]
# in ~/.config/gnome-settings/key-bindings.ini
#
# Night Light control:
#
# - <Super><Alt>backslash => "when" toggle
# + "Force" the screen to be warm right now!
# (Turns Night Light on if it was off, and keeps it on all day)
# + "Un-force" the Night Light into the local evening schedule
# - <Super><Alt><Shift>backslash => "if" toggle
# Plain on/off switch for the Night Light feature
# - <Super><Alt>bracketleft => Make the screen cooler
# - <Super><Alt>bracketright => Make the screen warmer, and "force" warmness
#
#
# State machine:
#
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# | | "IF" toggle | "WHEN" toggle | "make COOLER" | "make WARMER" |
# | Current STATE | <Super><Alt><Shift>backslash | <Super><Alt>backslash | <Super><Alt>bracketleft | <Super><Alt>bracketright |
# | | | | | |
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# | DISABLED | ENABLE | enabled | still disabled | enabled |
# | + scheduled | + still scheduled | + FORCED on | + still scheduled | + FORCED on |
# | => no tint | => no or set tint | => set tint | => still no tint | => set tint |
# | | based on time N? | | N! | *1 |
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# | DISABLED | ENABLE | enabled | still disabled | enabled |
# | + forced on | + still forced | + still FORCED on | + still forced | + still FORCED on |
# | => no tint | => set tint | => set tint | => still no tint | => set tint |
# | | | | N! | *1 |
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# | enabled | DISABLE | still enabled | still enabled | still enabled |
# | + SCHEDULED (day) | + still scheduled | + FORCED on | + still scheduled | + FORCED on |
# | => no tint yet | => still no tint | => set tint | => still no tint | => set tint |
# | | N! | | N! | *1 |
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# | enabled | DISABLE | still enabled | still enabled | still enabled |
# | + SCHEDULED (ramping) | + still scheduled | + FORCED on | + still scheduled | + FORCED on |
# | => some tint already | => no tint | => set tint | => no change in tint | => set tint |
# | | | | N! | |
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# | enabled | DISABLE | still enabled | still enabled | still enabled |
# | + SCHEDULED (night) | + still scheduled | + FORCED on | + still scheduled | + FORCED on |
# | => set tint | => no tint | => set tint | => LESS tint | => MORE tint |
# | | | N! | *2 N? | N? |
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# | enabled | DISABLE | still enabled | still enabled | still enabled |
# | + FORCED on | + still forced on | + back to SCHEDULED | + still forced on | + still forced on |
# | => set tint | => no tint | => no or set tint | => LESS tint | => MORE tint |
# | | | based on time N? | *2 N? | N? |
# +-----------------------+------------------------------+------------------------------+------------------------------+------------------------------+
# Legend:
# - N! => A notification is shown for sure because there is no visible change on the screen
# - N? => A notification is shown if there was no visible change on the screen
# - *1 => The temperature is snapped to 2200K to ensure a visible effect
# - *2 => The tint is turned off entirely when stepping over the maximum temperature
#
# Notes:
# - The main state property or state change is shown in CAPS
# - Steps range from 1200K (warmest) to 4700K (coolest),
# which is a bit more than the 1700K to 4700K in `gnome-control-center`
# - If the range is already exhausted, so that the tint does not change, a notification is shown
# - A 03:00 timer re-enables the Night Light feature and puts it back on the automatic schedule
# with the `$_DEFAULT_TEMPERATURE` set
#
set -eu
notify() {
ID_FILE="${XDG_RUNTIME_DIR}/night-light-notification-id"
_id=$(cat "$ID_FILE" 2>/dev/null || true)
if [ -n "$_id" ]; then
notify-send -p -t 5000 --replace-id="$_id" "Night Light" "$1" > "$ID_FILE" || rm -f "$ID_FILE"
else
notify-send -p -t 5000 "Night Light" "$1" > "$ID_FILE" || rm -f "$ID_FILE"
fi
}
Schema=org.gnome.settings-daemon.plugins.color
active_before=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color NightLightActive)
applied=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color Temperature \
| sed -E 's/.*uint32 ([0-9]+).*/\1/')
automatic=$(gsettings get $Schema night-light-schedule-automatic)
enabled=$(gsettings get $Schema night-light-enabled)
target=$(gsettings get $Schema night-light-temperature | awk '{print $2}')
if [ "$automatic" = "true" ] || [ "$enabled" = "false" ]; then
# Force "Night Light" enabled, enabling it if needed
gsettings set $Schema night-light-enabled true
gsettings set $Schema night-light-schedule-automatic false
gsettings set $Schema night-light-schedule-from 0.0
gsettings set $Schema night-light-schedule-to 24.0
if [ "$active_before" = "(<true>,)" ] && [ "$automatic" = "true" ] \
&& [ $((applied - target)) -le 300 ]; then
notify "is now forced to stay on and no longer on an automatic schedule"
fi
else
# Back to the live location's schedule
gsettings set $Schema night-light-schedule-automatic true
gsettings set $Schema night-light-schedule-from 18.0
gsettings set $Schema night-light-schedule-to 6.0
if [ "$active_before" = "(<true>,)" ]; then
# Give the settings daemon a moment to recompute "NightLightActive"
sleep 0.1
active_after=$(gdbus call --session \
--dest org.gnome.SettingsDaemon.Color \
--object-path /org/gnome/SettingsDaemon/Color \
--method org.freedesktop.DBus.Properties.Get \
org.gnome.SettingsDaemon.Color NightLightActive)
if [ "$active_after" = "(<true>,)" ]; then
notify "is still on because of an automatic schedule"
fi
fi
fi

152
.local/bin/randomize-background Executable file
View file

@ -0,0 +1,152 @@
#!/bin/sh
# Determine the next wallpaper by round robin from the cloud
# and install it as the background files referenced in
# ~/.config/gnome-settings/misc.ini
#
# Candidates:
# - Pairs => Both "<name>-d.jpg" and "<name>-l.jpg" exist
# - Singles => Any other "*.jpg" not following the -d/-l scheme,
# used as dark and light at the same time
#
# The live `gsettings` URIs point at uniquely named copies
# because `gnome-shell` caches background images by file URI;
# `gnome-restore` cleans up that temporary state during the next login
set -eu
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
SOURCE_DIR="$HOME/Cloud/Null-Tech/Backgrounds"
TARGET_DIR="$XDG_DATA_HOME/backgrounds"
LOCAL_INI="$XDG_CONFIG_HOME/gnome-settings/local/temporary_background.ini"
STATE_FILE="$XDG_STATE_HOME/current-background.txt"
[ -d "$SOURCE_DIR" ] || {
echo "No such folder: $SOURCE_DIR" >&2
exit 1
}
# One candidate per line, tab-separated: <dark-file> <light-file>
candidates=$(
for jpg in "$SOURCE_DIR"/*.jpg; do
[ -e "$jpg" ] || continue # because the glob does not expand if empty
case "$jpg" in
*-d.jpg) # Complete pairs only
stem="${jpg%-d.jpg}"
[ -f "$stem-l.jpg" ] && printf '%s\t%s\n' "$jpg" "$stem-l.jpg"
;;
*-l.jpg) # Already handled via its "-d" counterpart above
;;
*) # A single file to be used for both modes
printf '%s\t%s\n' "$jpg" "$jpg"
;;
esac
done
)
if [ -z "$candidates" ]; then
echo "No usable *.jpg files in: $SOURCE_DIR" >&2
exit 1
fi
echo "Found $(printf '%s\n' "$candidates" | wc -l) candidate(s)"
# The glob expands alphabetically => "$candidates" is already sorted
# => Pick the first candidate sorting strictly after the last-used one,
# falling back to the first one if necessary
# (e.g., for start, wrap-around, or missing state file)
last_background=$(cat "$STATE_FILE" 2>/dev/null || true)
next_background=$(printf '%s\n' "$candidates" | awk -F '\t' -v last_background="$last_background" '$1 > last_background { print; exit }')
[ -n "$next_background" ] || next_background=$(printf '%s\n' "$candidates" | head -n 1)
dark_source=$(printf '%s' "$next_background" | cut -f 1)
light_source=$(printf '%s' "$next_background" | cut -f 2)
echo "Chosen background: $(basename "$dark_source")"
dark_target="$TARGET_DIR/dark.jpg"
light_target="$TARGET_DIR/light.jpg"
# Create a unique name per run
# so that the URIs below never repeat
timestamp=$(date +%s)
dark_live_target="$TARGET_DIR/dark-tmp-$timestamp.jpg"
light_live_target="$TARGET_DIR/light-tmp-$timestamp.jpg"
mkdir -p \
"$TARGET_DIR" \
"$(dirname "$LOCAL_INI")" \
"$(dirname "$STATE_FILE")"
# Fixed-name copies, referenced as login-time defaults in the *.ini files
cp -- "$dark_source" "$dark_target"
cp -- "$light_source" "$light_target"
# Uniquely named copies for the live `gsettings` URIs
# to ensure `gnome-shell` uses the correct files right away
cp -- "$dark_source" "$dark_live_target"
cp -- "$light_source" "$light_live_target"
printf '%s\n' "$dark_source" > "$STATE_FILE"
Background=org.gnome.desktop.background
Screensaver=org.gnome.desktop.screensaver
gsettings set $Background picture-uri-dark "file://$dark_live_target"
gsettings set $Background picture-uri "file://$light_live_target"
gsettings set $Screensaver picture-uri "file://$dark_live_target"
# Persist the unique URIs for `gnome-restore`,
# which loads local/*.ini after the base *.ini files
cat > "$LOCAL_INI" <<EOF
# Written by $(basename "$0") - do not edit
[org/gnome/desktop/background]
picture-uri-dark='file://$dark_live_target'
picture-uri='file://$light_live_target'
[org/gnome/desktop/screensaver]
picture-uri='file://$dark_live_target'
EOF
# Remove the uniquely named copies of previously chosen wallpapers
find "$TARGET_DIR" -name 'dark-tmp-*.jpg' ! -name "dark-tmp-$timestamp.jpg" -delete
find "$TARGET_DIR" -name 'light-tmp-*.jpg' ! -name "light-tmp-$timestamp.jpg" -delete
echo "Installed as: $TARGET_DIR/{dark,light}.jpg"

5
.local/bin/scp Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
# See ~/.local/bin/ssh
exec /usr/bin/scp -o SetEnv=LC_ALL=C.UTF-8 "$@"

36
.local/bin/screenshot-screen Executable file
View file

@ -0,0 +1,36 @@
#!/bin/sh
# Take a screenshot of the whole screen
# (i.e., what "<Shift>Print" does)
#
# The screenshot machinery lives inside `gnome-shell`
# and cannot be called directly because
# its D-Bus methods are restricted to trusted callers
#
# => We synthesize the key press instead, after a short delay
# so that a launcher's keyboard grab (e.g., `rofi`) is released
set -eu
[ "${XDG_SESSION_TYPE:-}" = "x11" ] || {
echo "X11 only (xdotool)" >&2
exit 1
}
# Optional countdown in seconds (e.g., `screenshot-screen 3`),
# defaulting to 0.2
countdown="${1:-0.2}"
case "$countdown" in
''|.|*[!0-9.]*|*.*.*)
echo "Not a number: $countdown" >&2
exit 1
;;
esac
sleep "$countdown"
xdotool key shift+Print

25
.local/bin/screenshot-ui Executable file
View file

@ -0,0 +1,25 @@
#!/bin/sh
# Open GNOME's screenshot UI
# (i.e., what a simple "Print" does)
#
# The screenshot machinery lives inside `gnome-shell`
# and cannot be called directly because
# its D-Bus methods are restricted to trusted callers
#
# => We synthesize the key press instead, after a short delay
# so that a launcher's keyboard grab (e.g., `rofi`) is released
set -eu
[ "${XDG_SESSION_TYPE:-}" = "x11" ] || {
echo "X11 only (xdotool)" >&2
exit 1
}
sleep 0.2
xdotool key Print

36
.local/bin/screenshot-window Executable file
View file

@ -0,0 +1,36 @@
#!/bin/sh
# Take a screenshot of the focused window
# (i.e., what "<Alt>Print" does)
#
# The screenshot machinery lives inside `gnome-shell`
# and cannot be called directly because
# its D-Bus methods are restricted to trusted callers
#
# => We synthesize the key press instead, after a short delay
# so that a launcher's keyboard grab (e.g., `rofi`) is released
set -eu
[ "${XDG_SESSION_TYPE:-}" = "x11" ] || {
echo "X11 only (xdotool)" >&2
exit 1
}
# Optional countdown in seconds (e.g., `screenshot-window 3`),
# defaulting to 0.2
countdown="${1:-0.2}"
case "$countdown" in
''|.|*[!0-9.]*|*.*.*)
echo "Not a number: $countdown" >&2
exit 1
;;
esac
sleep "$countdown"
xdotool key alt+Print

View file

@ -0,0 +1,20 @@
#!/bin/sh
set -eu
# Loaded from ~/.config/environment.d/50-defaults.conf or a local override
BRIGHTNESS="${DEFAULT_BRIGHTNESS:?unset, check ~/.config/environment.d/}"
gdbus wait --session --timeout 10 org.gnome.SettingsDaemon.Power
gdbus call --session \
--dest org.gnome.SettingsDaemon.Power \
--object-path /org/gnome/SettingsDaemon/Power \
--method org.freedesktop.DBus.Properties.Set \
org.gnome.SettingsDaemon.Power.Screen Brightness "<int32 $BRIGHTNESS>" \
>/dev/null
echo "Set screen brightness to $BRIGHTNESS"

View file

@ -0,0 +1,47 @@
#!/bin/sh
set -eu
# Loaded from ~/.config/environment.d/50-defaults.conf or a local override
BRIGHTNESS="${DEFAULT_KEYBOARD_BRIGHTNESS:?unset, check ~/.config/environment.d/}"
# Nothing to do on machines without a keyboard backlight
KBD_DEVICE=
for led in /sys/class/leds/*kbd_backlight*; do
[ -e "$led" ] || break
KBD_DEVICE=$led
break
done
if [ -z "$KBD_DEVICE" ]; then
echo "No keyboard backlight, skipping"
exit 0
fi
kbd_set() {
gdbus call --session \
--dest org.gnome.SettingsDaemon.Power \
--object-path /org/gnome/SettingsDaemon/Power \
--method org.freedesktop.DBus.Properties.Set \
org.gnome.SettingsDaemon.Power.Keyboard Brightness "<int32 $BRIGHTNESS>" \
>/dev/null
}
gdbus wait --session --timeout 10 org.gnome.SettingsDaemon.Power
# `gsd-power` owns its bus name before it has probed the keyboard
# backlight, so at login the first write may silently be discarded
kbd_set
if [ "$(cat "$KBD_DEVICE/brightness")" = "0" ]; then
sleep 3
kbd_set
fi
echo "Set keyboard brightness to $BRIGHTNESS"

25
.local/bin/set-volume-default Executable file
View file

@ -0,0 +1,25 @@
#!/bin/sh
set -eu
# Loaded from ~/.config/environment.d/50-defaults.conf or a local override
VOLUME="${DEFAULT_VOLUME:?unset, check ~/.config/environment.d/}"
i=0
while ! wpctl status >/dev/null 2>&1; do
i=$((i + 1))
if [ "$i" -ge 20 ]; then
echo "no PipeWire sink after 10s" >&2
exit 1
fi
sleep 0.5
done
wpctl set-volume @DEFAULT_AUDIO_SINK@ "$VOLUME%"
wpctl set-mute @DEFAULT_AUDIO_SINK@ 0
echo "Set volume to $VOLUME%"

5
.local/bin/sftp Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
# See ~/.local/bin/ssh
exec /usr/bin/sftp -o SetEnv=LC_ALL=C.UTF-8 "$@"

14
.local/bin/ssh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
# Mask the exotic `LC_*` values from ~/.config/shell/locale on remote hosts
#
# Debian's /etc/ssh/ssh_config forwards them via `SendEnv LANG LC_*`,
# which cannot be cleared from ~/.ssh/config
# => Send `LC_ALL` on top, which overrides all `LC_*` and `LANG` remotely
#
# `C.UTF-8` is built into `glibc` and thus available on every host
#
# Found via the `$PATH` by `git`, `rsync`, `sshfs`, scripts, and GUI apps;
# `scp` and `sftp` call /usr/bin/ssh directly and have their own wrappers
exec /usr/bin/ssh -o SetEnv=LC_ALL=C.UTF-8 "$@"

101
.local/bin/vault-toggle Executable file
View file

@ -0,0 +1,101 @@
#!/bin/sh
# Mount or unmount the `gocryptfs` ~/Vault synced via the ~/Cloud
#
# Triggered by <Super><Control>v
# as defined in [org/gnome/settings-daemon/plugins/media-keys]
# in ~/.config/gnome-settings/key-bindings.ini
#
# The password is taken from the secret service (e.g., GNOME Keyring)
# and, if not stored there, asked for with a GUI prompt
#
# Store the password once with:
# secret-tool store --label='gocryptfs ~/Vault' gocryptfs vault
#
# Requires:
# - gocryptfs
# - libnotify-bin
# - libsecret-tools
# - zenity
set -eu
CIPHER_DIR="$HOME/Cloud/Misc/Vault.enc"
MOUNT_POINT="$HOME/Vault"
_command_exists() {
command -v "$1" 1>/dev/null 2>&1
}
_notify() {
_command_exists notify-send || return 0
notify-send 'Vault' "$1"
}
# Print the password to stdout,
# instead of storing it in a variable
_password() {
if _command_exists secret-tool \
&& secret-tool lookup gocryptfs vault 2>/dev/null; then
return 0
fi
zenity --password --title='Unlock the Vault' 2>/dev/null
}
_unmount() {
if _command_exists fusermount3; then
fusermount3 -u "$MOUNT_POINT"
else
fusermount -u "$MOUNT_POINT"
fi
}
# Unmount if mounted
if mountpoint -q "$MOUNT_POINT"; then
if _unmount 2>/dev/null; then
_notify 'Locked'
exit 0
fi
# Most likely a shell or an app still has a file open inside
_notify 'Still in use => Close all files and shells inside first'
exit 1
fi
# Mount otherwise
if [ ! -f "$CIPHER_DIR/gocryptfs.conf" ]; then
_notify "No vault found at $CIPHER_DIR"
exit 1
fi
# Nextcloud does not sync mode bits
# => Enforce owner-only access on every client,
# which `gocryptfs` also shows as the mode of the mount point
chmod 700 "$CIPHER_DIR"
mkdir -p "$MOUNT_POINT"
# `gocryptfs` reads the password from stdin if that is not a terminal
if _password | gocryptfs -idle 1h -quiet -sharedstorage "$CIPHER_DIR" "$MOUNT_POINT"; then
_notify 'Unlocked'
else
_notify 'Not unlocked (wrong or no password?)'
exit 1
fi

27
.local/bin/wifi-toggle Executable file
View file

@ -0,0 +1,27 @@
#!/bin/sh
# Toggle the WiFi on or off
set -eu
_notify() {
command -v notify-send >/dev/null 2>&1 || return 0
notify-send 'WiFi' "$1"
}
case "$(nmcli -t radio wifi)" in
enabled)
nmcli radio wifi off
_notify 'Radio turned off'
;;
disabled)
nmcli radio wifi on
_notify 'Radio turned on'
;;
*)
_notify 'No radio available'
exit 1
;;
esac

View file

@ -0,0 +1,4 @@
# Desktop Entries
This folder contains `*.desktop` launchers
for some scripts in [`~/.local/bin`](../../bin).

View file

@ -0,0 +1,7 @@
[Desktop Entry]
Type=Application
Name=Capture the whole screen
Exec=screenshot-screen
Icon=applets-screenshooter
Terminal=false
Categories=Utility;

View file

@ -0,0 +1,7 @@
[Desktop Entry]
Type=Application
Name=Open GNOME's screenshot UI
Exec=screenshot-ui
Icon=applets-screenshooter
Terminal=false
Categories=Utility;

View file

@ -0,0 +1,7 @@
[Desktop Entry]
Type=Application
Name=Capture the focused window
Exec=screenshot-window
Icon=applets-screenshooter
Terminal=false
Categories=Utility;

9
.zshrc
View file

@ -75,6 +75,15 @@ compdef '_arguments "--force[skip safety checks / reinstall]"' dotfiles-install
# Complete the `--quieter` flag of the `generate-shell-completions` utility in ~/.local/bin
compdef '_arguments "--quieter[suppress the reload hint]"' generate-shell-completions
# Complete the flags of the `color-palette` in ~/.local/bin
# => Keep the (short) descriptions in sync
# with the `argparse` section in ~/.local/bin/color-palette
compdef '_arguments \
"--scheme[Override the live GNOME color-scheme]:scheme:(dark light)" \
"--show[Show the derived colors as swatches]" \
"--write[Write the palette into all consumer files]"' \
color-palette
# Enable match highlighting and scrolling through long lists,
# and provide a different style of menu completion
zmodload zsh/complist

View file

@ -26,7 +26,7 @@ If I told you to go here and copy/paste my public `ssh` keys
either [here](.ssh/authorized_keys_webartifex)
or [here](https://code.webartifex.de/alexander.keys).
Read [this](https://code.webartifex.de/alexander/dotfiles/src/branch/main/.ssh#how-the-keys-are-managed)
Read [this](https://code.webartifex.de/alexander/dotfiles/src/branch/desktop/.ssh#how-the-keys-are-managed)
for how the keys are managed.
@ -35,18 +35,28 @@ Read [this](https://code.webartifex.de/alexander/dotfiles/src/branch/main/.ssh#h
Simply run:
```sh
curl https://code.webartifex.de/alexander/dotfiles/raw/branch/main/.local/bin/dotfiles-install > dotfiles-install && sh ./dotfiles-install && rm ./dotfiles-install
curl https://code.webartifex.de/alexander/dotfiles/raw/branch/desktop/.local/bin/dotfiles-install > dotfiles-install && sh ./dotfiles-install && rm ./dotfiles-install
```
or
```sh
wget https://code.webartifex.de/alexander/dotfiles/raw/branch/main/.local/bin/dotfiles-install -O dotfiles-install && sh ./dotfiles-install && rm ./dotfiles-install
wget https://code.webartifex.de/alexander/dotfiles/raw/branch/desktop/.local/bin/dotfiles-install -O dotfiles-install && sh ./dotfiles-install && rm ./dotfiles-install
```
This downloads a simple [installation script](.local/bin/dotfiles-install)
and then executes it.
The script's only dependency is [`git`](https://git-scm.com/).
Besides [git](https://git-scm.com/), the script assumes
a [Debian](https://www.debian.org/) 13 desktop
with [GNOME](https://www.gnome.org/) 48+
on [X11](https://www.x.org/),
though older GNOME versions
and [Wayland](https://wayland.freedesktop.org/) should mostly work,
except for some X11-only stuff.
Further, it uses
[`python3`](https://www.python.org/) with `pip`
to generate the [color palette](.local/bin/color-palette)
and enables a few `systemd` user units.
So, it should not be too hard to get this going.
The repository is cloned as a bare repository into `~/.local/share/dotfiles`
@ -56,12 +66,12 @@ Afterwards, the files can be managed with the
[`dotfiles` alias](.config/shell/aliases),
for example, `dotfiles status` or `dotfiles pull`.
The above commands install the *main* variant.
To install the *desktop* variant,
switch to the [desktop](https://code.webartifex.de/alexander/dotfiles/src/branch/desktop) branch first.
The above commands install the *desktop* variant.
To install the *main* variant,
switch to the [main](https://code.webartifex.de/alexander/dotfiles/src/branch/main) branch first.
Normally, I advise against executing shell scripts from the internet,
but this one is short enough to be read even by beginners.
but this one is still short enough to be read in a few minutes.
So, convince yourself that it is not harmful!