feat: initial Moongreet greeter implementation

greetd-Greeter für Wayland mit Python + GTK4 + gtk4-layer-shell.
Enthält IPC-Protokoll, User/Session-Erkennung, Power-Actions,
komplettes UI-Layout und 36 Tests (Unit + Integration).
This commit is contained in:
2026-03-26 09:47:19 +01:00
commit 87c2e7d9c8
21 changed files with 1610 additions and 0 deletions
+62
View File
@@ -0,0 +1,62 @@
# ABOUTME: Session detection — discovers available Wayland and X11 sessions.
# ABOUTME: Parses .desktop files from standard session directories.
import configparser
from dataclasses import dataclass
from pathlib import Path
DEFAULT_WAYLAND_DIRS = [Path("/usr/share/wayland-sessions")]
DEFAULT_XSESSION_DIRS = [Path("/usr/share/xsessions")]
@dataclass
class Session:
"""Represents an available login session."""
name: str
exec_cmd: str
session_type: str # "wayland" or "x11"
def _parse_desktop_file(path: Path, session_type: str) -> Session | None:
"""Parse a .desktop file and return a Session, or None if invalid."""
config = configparser.ConfigParser(interpolation=None)
config.read(path)
section = "Desktop Entry"
if not config.has_section(section):
return None
name = config.get(section, "Name", fallback=None)
exec_cmd = config.get(section, "Exec", fallback=None)
if not name or not exec_cmd:
return None
return Session(name=name, exec_cmd=exec_cmd, session_type=session_type)
def get_sessions(
wayland_dirs: list[Path] = DEFAULT_WAYLAND_DIRS,
xsession_dirs: list[Path] = DEFAULT_XSESSION_DIRS,
) -> list[Session]:
"""Discover available sessions from .desktop files."""
sessions: list[Session] = []
for directory in wayland_dirs:
if not directory.exists():
continue
for desktop_file in sorted(directory.glob("*.desktop")):
session = _parse_desktop_file(desktop_file, "wayland")
if session:
sessions.append(session)
for directory in xsession_dirs:
if not directory.exists():
continue
for desktop_file in sorted(directory.glob("*.desktop")):
session = _parse_desktop_file(desktop_file, "x11")
if session:
sessions.append(session)
return sessions