xdg-user-dirs im Autostart, kanshi VM-Moduswahl
This commit is contained in:
@@ -1,6 +1,12 @@
|
|||||||
# labwc-Autostart – fluffy-pancake (Noctalia-Zweig)
|
# labwc-Autostart – fluffy-pancake (Noctalia-Zweig)
|
||||||
# Tastatur/Locale stehen in ~/.config/labwc/environment.
|
# Tastatur/Locale stehen in ~/.config/labwc/environment.
|
||||||
|
|
||||||
|
# 0. XDG-Standardordner (Dokumente, Bilder, Videos, ...) anlegen bzw.
|
||||||
|
# bei Locale-Wechsel umbenennen. Laeuft unter labwc sonst nie
|
||||||
|
# (kein X-Session-Autostart); u.a. braucht Noctalias Wallpaper-Picker
|
||||||
|
# ~/Bilder. Idempotent - macht bei existierenden Ordnern nichts.
|
||||||
|
xdg-user-dirs-update >/dev/null 2>&1 || true
|
||||||
|
|
||||||
# 1. Output-Profile (gedockt/ungedockt). Schreibt die kanshi-Config nur,
|
# 1. Output-Profile (gedockt/ungedockt). Schreibt die kanshi-Config nur,
|
||||||
# wenn sie fehlt oder von kanshi-autoconfig verwaltet wird.
|
# wenn sie fehlt oder von kanshi-autoconfig verwaltet wird.
|
||||||
# Eigene Hand-Edits bleiben unangetastet.
|
# Eigene Hand-Edits bleiben unangetastet.
|
||||||
|
|||||||
+45
-12
@@ -10,10 +10,18 @@ Verhalten:
|
|||||||
--print Vorschlag auf stdout, schreibt nichts.
|
--print Vorschlag auf stdout, schreibt nichts.
|
||||||
--apply Schreibt (mit Backup *.bak), fragt nicht.
|
--apply Schreibt (mit Backup *.bak), fragt nicht.
|
||||||
--apply-if-managed Schreibt nur, wenn die Config fehlt oder den Marker
|
--apply-if-managed Schreibt nur, wenn die Config fehlt oder den Marker
|
||||||
'# kanshi-autoconfig: managed' enthaelt.
|
'# kanshi-autoconfig: managed' enthaelt. Bei
|
||||||
-> Hand-Edits bleiben unangetastet. Wird vom
|
unveraendertem Output-Set bleibt eine verwaltete Config
|
||||||
|
unangetastet (Modus-Tweaks inklusive). Wird vom
|
||||||
labwc-Autostart bei jedem Login aufgerufen.
|
labwc-Autostart bei jedem Login aufgerufen.
|
||||||
|
|
||||||
|
Moduswahl: Auf echter Hardware der EDID-preferred-Modus (meist nativ =
|
||||||
|
richtig). In VMs meldet die Firmware oft einen Kleinstmodus als preferred
|
||||||
|
(QEMU: 1280x800) - dort wird 1920x1080@60 genommen, wenn angeboten, sonst
|
||||||
|
preferred. Einmal geschrieben bleibt die Config bei gleichem Output-Set
|
||||||
|
erhalten (Modus-Tweaks inklusive); neu generiert wird nur bei geaendertem
|
||||||
|
Output-Set (Docking) oder per --apply.
|
||||||
|
|
||||||
Faellt die Erkennung fehl (kein Wayland, kein wlr-randr), wird eine
|
Faellt die Erkennung fehl (kein Wayland, kein wlr-randr), wird eine
|
||||||
reine Fallback-Config geschrieben, damit nie ein schwarzer Bildschirm
|
reine Fallback-Config geschrieben, damit nie ein schwarzer Bildschirm
|
||||||
ohne Layout dasteht.
|
ohne Layout dasteht.
|
||||||
@@ -30,8 +38,39 @@ MARKER = "# kanshi-autoconfig: managed"
|
|||||||
CONFIG_PATH = Path.home() / ".config" / "kanshi" / "config"
|
CONFIG_PATH = Path.home() / ".config" / "kanshi" / "config"
|
||||||
|
|
||||||
|
|
||||||
|
def detect_vm():
|
||||||
|
"""True, wenn wir virtualisiert laufen (QEMU/Boxes-Test)."""
|
||||||
|
try:
|
||||||
|
proc = subprocess.run(
|
||||||
|
["systemd-detect-virt", "--vm"], capture_output=True, timeout=10
|
||||||
|
)
|
||||||
|
except (FileNotFoundError, subprocess.TimeoutExpired):
|
||||||
|
return False
|
||||||
|
return proc.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
|
def norm_rate(value):
|
||||||
|
if isinstance(value, (int, float)) and value > 1000:
|
||||||
|
return value / 1000 # mHz -> Hz
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def choose_mode(modes, current, in_vm):
|
||||||
|
"""Modus waehlen: VM-Heuristik, sonst preferred, sonst current/erster."""
|
||||||
|
if in_vm:
|
||||||
|
for m in modes:
|
||||||
|
rate = norm_rate(m.get("refresh") or m.get("rate")) or 0
|
||||||
|
if m.get("width") == 1920 and m.get("height") == 1080 and round(rate) == 60:
|
||||||
|
return m
|
||||||
|
for m in modes:
|
||||||
|
if m.get("preferred"):
|
||||||
|
return m
|
||||||
|
return current or (modes[0] if modes else None)
|
||||||
|
|
||||||
|
|
||||||
def detect_outputs():
|
def detect_outputs():
|
||||||
"""Liste von Dicts: name, internal, width, height, rate, scale."""
|
"""Liste von Dicts: name, internal, width, height, rate, scale."""
|
||||||
|
in_vm = detect_vm()
|
||||||
try:
|
try:
|
||||||
proc = subprocess.run(
|
proc = subprocess.run(
|
||||||
["wlr-randr", "--json"], capture_output=True, text=True, timeout=10
|
["wlr-randr", "--json"], capture_output=True, text=True, timeout=10
|
||||||
@@ -51,23 +90,17 @@ def detect_outputs():
|
|||||||
if out.get("connected") is False:
|
if out.get("connected") is False:
|
||||||
continue
|
continue
|
||||||
modes = out.get("modes", []) or []
|
modes = out.get("modes", []) or []
|
||||||
preferred = next((m for m in modes if m.get("preferred")), None)
|
|
||||||
current = out.get("current_mode") or out.get("mode")
|
current = out.get("current_mode") or out.get("mode")
|
||||||
chosen = preferred or current or (modes[0] if modes else None)
|
chosen = choose_mode(modes, current, in_vm)
|
||||||
if not chosen:
|
if not chosen:
|
||||||
continue
|
continue
|
||||||
width = chosen.get("width")
|
|
||||||
height = chosen.get("height")
|
|
||||||
rate = chosen.get("refresh") or chosen.get("rate")
|
|
||||||
if isinstance(rate, (int, float)) and rate > 1000:
|
|
||||||
rate = rate / 1000 # mHz -> Hz
|
|
||||||
outputs.append(
|
outputs.append(
|
||||||
{
|
{
|
||||||
"name": name,
|
"name": name,
|
||||||
"internal": name.startswith(("eDP-", "LVDS-", "DSI-")),
|
"internal": name.startswith(("eDP-", "LVDS-", "DSI-")),
|
||||||
"width": width,
|
"width": chosen.get("width"),
|
||||||
"height": height,
|
"height": chosen.get("height"),
|
||||||
"rate": rate,
|
"rate": norm_rate(chosen.get("refresh") or chosen.get("rate")),
|
||||||
"scale": out.get("scale", 1) or 1,
|
"scale": out.get("scale", 1) or 1,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user