The DVD player was the only thing still speaking a compositor the room no longer runs. It asked sway's tree whether VLC's window had really gone fullscreen, because VLC reports playing while its window is still the black startup one the loading cover exists to hide. VLC's own status was measured as a replacement and is not one: it reports fullscreen true in the same 250ms poll as playing, because the flag is the option it was started with and not a report about its window. So the cover is held for a floor and capped by the deadline that was already there, and the compositor is not asked anything. Focus-or-launch went the same way. The session already takes an exclusive lock, so a second one cannot start, and bringing an existing one to the front is the panel's job. classroom-window, classroom_sway and classroom_chrome are gone with it — the last of them was reachable from nothing at all. DVD also moves out of the status row, where it sat beside the clock as though a disc were a machine reading. It is an application: it is in the row with Wonder Ink and the browser, and classroom-provision removes it from the layout on a machine with no optical drive, which retires DVD_ENABLED. A computer that moves between rooms takes its drive with it; nobody remembers to edit a file when it does. The panel is rebuilt from the package at every login now. Plasma keeps whatever panel it first built, so an update could change the bar in the package and never change it in a room — measured, with an icon that outlived the file it came from. Editing the live panel configuration was tried instead and destroyed the panel, because the shell owns that file. Removing it before the shell starts is safe and makes the desktop stateless. Co-Authored-By: Claude Opus 5 <[email protected]>
97 lines
2.8 KiB
Python
Executable File
97 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
"""Match the classroom's panel to the machine it is on.
|
|
|
|
There is exactly one thing about the bar that depends on hardware: a room
|
|
with no optical drive should not be offered a disc player. This edits the
|
|
one marked line in the installed layout, and nothing else.
|
|
|
|
It writes the *layout*, not the running panel. Editing
|
|
plasma-org.kde.plasma.desktop-appletsrc underneath a live plasmashell was
|
|
tried and it destroyed the panel: the shell owns that file and rewrites
|
|
it, so an edit races with it. The layout is a file the package owns and
|
|
the shell only reads, and classroom-desktop-reset makes the shell read it
|
|
again at the next login.
|
|
|
|
DVD_ENABLED is gone. A drive is something the machine can be asked about,
|
|
and asking is more reliable than remembering to edit a file when a
|
|
computer moves between rooms.
|
|
"""
|
|
|
|
import glob
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
LAYOUT = (
|
|
"/usr/share/plasma/look-and-feel/org.ekklesia.classroom.desktop"
|
|
"/contents/layouts/org.kde.plasma.desktop-layout.js"
|
|
)
|
|
|
|
MARKER = "/* CLASSROOM-DVD-LAUNCHER */"
|
|
|
|
# The kernel names optical drives sr0, sr1, ... regardless of bus.
|
|
DRIVE_GLOB = "/dev/sr[0-9]*"
|
|
|
|
|
|
def has_optical_drive():
|
|
return bool(glob.glob(DRIVE_GLOB))
|
|
|
|
|
|
def rewrite(text, wanted):
|
|
"""Comment the DVD launcher in or out, idempotently."""
|
|
line = re.compile(
|
|
r"^(\s*)(//\s*)?(" + re.escape(MARKER) + r'\s*"applications:ekklesia-dvd\.desktop")',
|
|
re.M,
|
|
)
|
|
|
|
def swap(match):
|
|
indent, _, body = match.groups()
|
|
return f"{indent}{'' if wanted else '// '}{body}"
|
|
|
|
return line.sub(swap, text)
|
|
|
|
|
|
def main():
|
|
path = sys.argv[1] if len(sys.argv) > 1 else LAYOUT
|
|
|
|
try:
|
|
with open(path, "r", encoding="utf-8") as handle:
|
|
before = handle.read()
|
|
except OSError as error:
|
|
print(f"classroom-desktop-layout: {error}", file=sys.stderr)
|
|
return 0
|
|
|
|
if MARKER not in before:
|
|
print("classroom-desktop-layout: no DVD marker in the layout",
|
|
file=sys.stderr)
|
|
return 0
|
|
|
|
wanted = has_optical_drive()
|
|
after = rewrite(before, wanted)
|
|
|
|
if after == before:
|
|
print(f"classroom-desktop-layout: DVD launcher already "
|
|
f"{'present' if wanted else 'absent'}")
|
|
return 0
|
|
|
|
# Replace the file rather than edit in place, so a full disk or a
|
|
# crash leaves the old layout intact rather than half of a new one.
|
|
temporary = f"{path}.new"
|
|
|
|
try:
|
|
with open(temporary, "w", encoding="utf-8") as handle:
|
|
handle.write(after)
|
|
os.replace(temporary, path)
|
|
except OSError as error:
|
|
print(f"classroom-desktop-layout: {error}", file=sys.stderr)
|
|
return 1
|
|
|
|
print(f"classroom-desktop-layout: DVD launcher "
|
|
f"{'added' if wanted else 'removed'}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|