Files
Classroom_Desktop/config/plasma/lookandfeel/contents/layouts/org.kde.plasma.desktop-layout.js
T
ekklesiaandClaude Opus 5 34fd02e08f feat: give every room the broker, one scale, and its own panel back
Little Waders took the Plasma build and reported what a container
cannot. A disc player on a machine with no optical drive, a clock nobody
at the back of the room could read, a browser at half the size of the
panel around it, and Parent Call with no broker to call.

The broker is the same for every classroom, so it is a default now and
not something to fill in room by room. classroom-migrate brings an
existing room to the same place without touching its name, its username
or its password, and Parent Call distinguishes a broker it cannot reach
from one that was never set up: those send somebody to look at
completely different things.

The disc player's detection was right and ran too late — alongside the
session rather than before it, and the panel is built from the layout the
moment a session starts. It runs before the display manager now, and
again from udev when a drive is plugged in.

UI_SCALE had a ceiling of 1.5, which cannot express a 4K television; a
clock pinned at 15 points, which is the same size at every scale; and a
browser that was never told the number at all. All three are fixed and
the room doubles together at 200%.

This also brings 0.1.47's work into the repository, where it had only
ever existed in a build directory under /tmp: the hidden display dialog,
its authenticated writer, the polkit action, and the church's own
wallpaper. One piece of it is deliberately left out. The custom volume
display needed a shell package of our own, and with one selected
plasmashell builds no panel at all — measured twice, with that build's
own files, on a classroom that deletes its panel configuration at every
login by design.

The lab connected to the real church broker the moment the package
defaulted to it. Nothing was left behind, which was checked, but the
guard that should have stopped it had never worked: it used iptables,
which the lab image does not have, and probed with /dev/tcp under dash,
where that always fails. Both reported success.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-12 19:05:09 -05:00

163 lines
7.4 KiB
JavaScript

// The Ekklesia Classroom desktop.
//
// Plasma runs this once, when a session has no panel yet, and again on
// demand — `plasma-apply-lookandfeel -a org.ekklesia.classroom.desktop
// --resetLayout` rebuilds the whole desktop from this file. That is the
// classroom's recovery path for a damaged shell, and it is Plasma's own
// mechanism rather than something written here.
//
// One full-width bar along the bottom. Left is auxiliary, the middle is
// applications, the right is the small amount of status a teacher needs.
// Nothing else is on the screen.
var WALLPAPER = "/usr/share/backgrounds/ekklesia/classroom-calm.png";
// Matches the 76px strip the classroom has always used, so muscle memory
// and the room's viewing distance both carry over.
var PANEL_HEIGHT = 76;
// The idle desktop: the wallpaper, and nothing on it.
var screens = desktops();
for (var i = 0; i < screens.length; i++) {
var desktop = screens[i];
desktop.wallpaperPlugin = "org.kde.image";
desktop.currentConfigGroup = ["Wallpaper", "org.kde.image", "General"];
desktop.writeConfig("Image", "file://" + WALLPAPER);
desktop.writeConfig("SlidePaths", "");
// 2 is "scaled and cropped": the landscape fills the display at any
// aspect ratio without being stretched out of shape.
desktop.writeConfig("FillMode", 2);
desktop.reloadConfig();
}
var panel = new Panel();
panel.location = "bottom";
panel.height = PANEL_HEIGHT;
panel.hiding = "none";
panel.floating = false;
panel.lengthMode = "fill";
panel.alignment = "center";
panel.opacity = "adaptive";
// LEFT — auxiliary. Parent Call is not one of the room's applications and
// is deliberately not in the row with them.
// Quick Launch: a launcher, and only a launcher.
//
// Two other widgets were tried on a real panel. The Icon widget copies
// the desktop entry into the user's home and uses the copy, so an update
// could never change the icon or the command — it kept showing a bell out
// of a package that no longer contained one. A task manager reads
// /usr/share/applications live, which fixes that, but a task manager also
// shows every running window, so the auxiliary corner filled up with the
// lesson's tasks.
//
// Quick Launch reads the entry live and shows nothing but the button.
var parentCall = panel.addWidget("org.kde.plasma.quicklaunch");
parentCall.currentConfigGroup = ["General"];
// A file URL, not applications:. Quick Launch resolves the entry itself
// and does not copy it, so the path is a live reference to what the
// package installs.
parentCall.writeConfig(
"launcherUrls",
"file:///usr/share/applications/ekklesia-parent-call.desktop"
);
parentCall.writeConfig("showLauncherNames", false);
parentCall.writeConfig("enablePopup", false);
parentCall.writeConfig("maxSectionCount", 1);
var leftGap = panel.addWidget("org.kde.plasma.panelspacer");
leftGap.currentConfigGroup = ["General"];
leftGap.writeConfig("expanding", true);
// CENTRE — the applications, and the whole of the running/minimised/active
// story. This applet is the reason the classroom stops writing a dock.
var tasks = panel.addWidget("org.kde.plasma.icontasks");
tasks.currentConfigGroup = ["General"];
// The DVD line is rewritten by classroom-provision to match the machine:
// a room with no optical drive has it removed, so no teacher is offered a
// disc player that cannot exist. Between the marker comments, and nowhere
// else, so the edit is a line replacement and not a parse.
tasks.writeConfig("launchers", [
"applications:ekklesia-wonderink.desktop",
"applications:google-chrome.desktop",
/* CLASSROOM-DVD-LAUNCHER */ "applications:ekklesia-dvd.desktop"
].join(","));
// Every window gets its own button. Teachers should never have to open a
// group to find out that a second window exists.
tasks.writeConfig("groupingStrategy", 0);
tasks.writeConfig("showOnlyCurrentDesktop", false);
tasks.writeConfig("showOnlyCurrentActivity", false);
tasks.writeConfig("showOnlyCurrentScreen", false);
// Clicking a button always means "show me this", and never "hide it".
//
// This was measured before it was decided. Plasma 6.3 draws a minimised
// task and a task that is merely behind another window identically: no
// indicator for closed, a grey indicator for running, a teal one for
// active — three marks for four states. Rather than write a task manager
// that draws a fourth, the classroom removes the state. There is nothing
// on the idle desktop for a teacher to want to see, so minimising an
// application in this room has no purpose and only ever loses it.
//
// A window minimised some other way is still shown as running and comes
// back with one click, so it can never be lost even then.
tasks.writeConfig("minimizeActiveTaskOnClick", false);
tasks.writeConfig("fill", false);
tasks.writeConfig("maxStripes", 1);
tasks.writeConfig("indicateAudioStreams", false);
tasks.writeConfig("wheelEnabled", false);
tasks.writeConfig("middleClickAction", "NewInstance");
tasks.writeConfig("showToolTips", true);
tasks.writeConfig("iconSpacing", 2);
var rightGap = panel.addWidget("org.kde.plasma.panelspacer");
rightGap.currentConfigGroup = ["General"];
rightGap.writeConfig("expanding", true);
// RIGHT — status.
//
// Three ordinary applets straight on the bar, and no system tray around
// them. A tray is a container that discovers whatever is installed and
// then hides most of it behind an arrow; measured in the lab it collected
// battery, brightness, clipboard, keyboard layout, camera, vaults and
// screen management on a machine that has none of those to say anything
// about. Naming the four the classroom actually uses is both smaller and
// deterministic, and it leaves nothing for a teacher to expand.
panel.addWidget("org.kde.plasma.networkmanagement");
var volume = panel.addWidget("org.kde.plasma.volume");
volume.currentConfigGroup = ["General"];
// No chime when the volume changes. A classroom is often listening to
// something when somebody adjusts it, and a beep over a lesson is worse
// than no feedback at all — the on-screen display is the feedback, and it
// is in the look and feel package where a television can read it.
//
// Plasma 6 moved this setting out of the applet and into a global one,
// and the applet migrates a false written here into it on first run. So
// this is both the setting and the instruction to carry it across.
volume.writeConfig("volumeFeedback", false);
volume.writeConfig("volumeOsd", true);
volume.writeConfig("muteOsd", true);
volume.writeConfig("outputChangeOsd", true);
// A teacher pressing the volume key expects a step they can hear.
volume.writeConfig("volumeStep", 5);
panel.addWidget("org.kde.plasma.notifications");
var clock = panel.addWidget("org.kde.plasma.digitalclock");
clock.currentConfigGroup = ["Appearance"];
clock.writeConfig("showDate", true);
clock.writeConfig("dateFormat", "custom");
clock.writeConfig("customDateFormat", "ddd d MMM");
clock.writeConfig("showSeconds", 0);
clock.writeConfig("dateDisplayFormat", "BelowTime");
// Sized by the bar, not by a number written here.
//
// It used to be pinned at 15 points to stop it becoming the largest text
// in the room. On a 4K television that was a clock a teacher could not
// read from the back of the room, and it was the one thing in the
// classroom that did not follow UI_SCALE, because a point size written
// into a layout is the same point size at every scale. Plasma's own
// sizing follows the bar, and the bar follows the scale.
clock.writeConfig("autoFontAndSize", true);
clock.writeConfig("fontWeight", 500);