refactor: group stow packages into common, mac and kde

Split the packages by platform so each app stays an opt-in Stow package
under common/, mac/ or kde/. KDE gets its own Fastfetch, Helium and
Spectacle packages, and darwin-breeze becomes kde/theme. The READMEs
document stowing a whole group as well as individual packages.
This commit is contained in:
tri committed 2026-10-30 21:57:15 +07:00
1 parent 1e99a15f6c
commit 34e978e84c
74 files changed
+532 -151

No files matched your search

@@ -0,0 +1,61 @@
[Desktop Entry]
GenericName=Screenshot Capture Utility
Name=Spectacle
Comment=Take screenshots and screen recordings
Categories=Qt;KDE;Utility;
Keywords=snapshot;capture;print;screenshot;snipping;snipping tool;snip;
Exec=/usr/bin/spectacle --background --region --copy-image
Icon=spectacle
Type=Application
StartupNotify=false
Actions=FullScreenScreenShot;CurrentMonitorScreenShot;ActiveWindowScreenShot;RectangularRegionScreenShot;WindowUnderCursorScreenShot;RecordRegion;RecordScreen;RecordWindow;OpenWithoutScreenshot;
DBusActivatable=false
X-DBUS-StartupType=Unique
X-DBUS-ServiceName=org.kde.Spectacle
X-KDE-Shortcuts=Print,Meta+Shift+S
X-KDE-DBUS-Restricted-Interfaces=org.kde.KWin.ScreenShot2
X-KDE-Wayland-Interfaces=org_kde_plasma_window_management,zkde_screencast_unstable_v1
[Desktop Action FullScreenScreenShot]
Name=Capture Entire Desktop
Exec=/usr/bin/spectacle --background --copy-image -f
X-KDE-Shortcuts=Shift+Print
[Desktop Action CurrentMonitorScreenShot]
Name=Capture Current Monitor
Exec=/usr/bin/spectacle --background --copy-image -m
[Desktop Action ActiveWindowScreenShot]
Name=Capture Active Window
Exec=/usr/bin/spectacle --background --copy-image -a
X-KDE-Shortcuts=Meta+Print
[Desktop Action RectangularRegionScreenShot]
Name=Capture Rectangular Region
Exec=/usr/bin/spectacle --background --copy-image -r
X-KDE-Shortcuts=Meta+Shift+Print
[Desktop Action WindowUnderCursorScreenShot]
Name=Capture Window Under Cursor
Exec=/usr/bin/spectacle --background --copy-image -u
X-KDE-Shortcuts=Meta+Ctrl+Print
[Desktop Action RecordRegion]
Name=Start/Stop Region Recording
Exec=/usr/bin/spectacle -R region
X-KDE-Shortcuts=Meta+Shift+R,Meta+R
[Desktop Action RecordScreen]
Name=Start/Stop Screen Recording
Exec=/usr/bin/spectacle -R screen
X-KDE-Shortcuts=Meta+Alt+R
[Desktop Action RecordWindow]
Name=Start/Stop Window Recording
Exec=/usr/bin/spectacle -R window
X-KDE-Shortcuts=Meta+Ctrl+R
[Desktop Action OpenWithoutScreenshot]
Name=Launch without taking a screenshot
Exec=/usr/bin/spectacle -l
@@ -0,0 +1 @@
../applications/org.kde.spectacle.desktop
+4
View File
@@ -0,0 +1,4 @@
^/README.*
^/apply\.py
^/settings
__pycache__
+28
View File
@@ -0,0 +1,28 @@
# Spectacle
Capture screenshots in the background, copy the image to the clipboard, and
show a completion notification. Screenshots are not automatically saved.
```sh
stow -d kde -t "$HOME" spectacle
./kde/spectacle/apply.py
```
Requires Spectacle, KDE Plasma 6, GNU Stow, Python 3, `kwriteconfig6`,
`kbuildsycoca6`, `qdbus6`, and `gdbus`. Run the apply script in your KDE session.
Move any existing files reported as conflicts by Stow out of the way first.
- **Print** / **Meta+Shift+S**: select a rectangular region.
- **Shift+Print**: entire desktop.
- **Meta+Print**: active window.
- **Meta+Shift+Print**: select a rectangular region.
- **Meta+Ctrl+Print**: window under the cursor.
The desktop launcher and shortcut entry are managed by Stow. The files in
`settings/` are merged into `~/.config/spectaclerc` and `~/.config/klipperrc`
by `apply.py`, preserving unrelated preferences and window state. Klipper's
`SaveImages=true` keeps captured images available after Spectacle exits.
After editing settings or launcher commands, run `apply.py` again. It rebuilds
the cache using the KDE session's environment and reloads only Spectacle's
shortcut component, preserving custom key bindings.
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""Apply screenshot preferences and reload Spectacle's KDE shortcuts."""
import ast
import configparser
import os
from pathlib import Path
import re
import subprocess
HERE = Path(__file__).resolve().parent
COMPONENT = "org.kde.spectacle.desktop"
ACCEL = "/component/org_kde_spectacle_desktop"
def run(*args, **kwargs):
return subprocess.run(args, check=True, text=True, **kwargs)
def accel(path, method, *args):
return run(
"gdbus", "call", "--session", "--dest", "org.kde.kglobalaccel",
"--object-path", path, "--method", method, *args,
capture_output=True,
).stdout
def main():
for name in ("spectaclerc", "klipperrc"):
config = configparser.ConfigParser(interpolation=None)
config.optionxform = str
config.read(HERE / "settings" / name)
for group in config.sections():
for key, value in config[group].items():
run("kwriteconfig6", "--file", name, "--group", group,
"--key", key, value)
# T3's locale and XDG_DATA_DIRS can differ from the running KDE session.
# Build the cache KDE actually reads, rather than an app-specific cache.
session = dict(
line.split("=", 1) for line in
run("systemctl", "--user", "show-environment", capture_output=True)
.stdout.splitlines() if "=" in line
)
env = os.environ.copy()
for key in ("LANG", "LANGUAGE", "XDG_DATA_DIRS", "XDG_DATA_HOME",
"XDG_CACHE_HOME", "XDG_CONFIG_HOME"):
env.pop(key, None)
if key in session:
env[key] = session[key]
for key in set(env) | set(session):
if key.startswith("LC_"):
env.pop(key, None)
if key in session:
env[key] = session[key]
run("kbuildsycoca6", "--noincremental", env=env)
# Existing shortcut components retain their old Exec commands. Recreate
# only Spectacle's component, preserving any customized key bindings.
try:
output = accel(ACCEL, "org.kde.kglobalaccel.Component.allShortcutInfos")
except subprocess.CalledProcessError:
shortcuts = [] # Component has not been registered yet.
else:
shortcuts = ast.literal_eval(re.sub(r"@a[is] ", "", output))[0]
accel(ACCEL, "org.kde.kglobalaccel.Component.cleanUp")
action = [COMPONENT, "_reload_config", "Spectacle", "Reload configuration"]
accel("/kglobalaccel", "org.kde.KGlobalAccel.doRegister", repr(action))
accel("/kglobalaccel", "org.kde.KGlobalAccel.unregister",
COMPONENT, "_reload_config")
for name, label, component, friendly, context, _, keys, defaults in shortcuts:
if keys != defaults:
identity = component if context == "default" else f"{component}|{context}"
accel("/kglobalaccel", "org.kde.KGlobalAccel.setForeignShortcut",
repr([identity, name, friendly, label]), repr(keys))
run("qdbus6", "org.kde.klipper", "/klipper",
"org.kde.klipper.klipper.reloadConfig")
print("Applied Spectacle: copy to clipboard with a notification, no preview.")
if __name__ == "__main__":
main()
+2
View File
@@ -0,0 +1,2 @@
[General]
SaveImages=true
+3
View File
@@ -0,0 +1,3 @@
[General]
autoSaveImage=false
clipboardGroup=PostScreenshotCopyImage