Tiny Pebbles came through the 0.2.2 upgrade on Plasma's own purple wallpaper: its desktop was containment 10, made after the layout had run (most likely the television arriving after a night-time reboot), with no wallpaper configured. The look and feel's fallback could not catch it, because it named a file and Plasma only accepts a wallpaper package there. The fallback is now the EkklesiaClassroom package, whose one image links to the classroom's picture. classroom-desktop-wallpaper, run before every plasmashell start, writes the picture into every desktop containment the file already has: found by plugin, never by number; panels and everything else byte for byte; a file that is already right not written at all. Co-Authored-By: Claude Opus 5.5 <[email protected]>
254 lines
11 KiB
JavaScript
254 lines
11 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.
|
|
|
|
// WHICH APPLICATIONS THIS DEVICE OFFERS.
|
|
//
|
|
// classroom-desktop-layout rewrites the lines between the markers to
|
|
// match device.conf and this machine's hardware, and nothing else in
|
|
// this file. Each application is its own line because each is its own
|
|
// setting: a laptop taking children's church needs Wonder Ink and a tower
|
|
// used for Bible study does not, so the shape of the machine is never
|
|
// allowed to decide what it is for.
|
|
//
|
|
// The first three are true here, which is what an existing classroom must
|
|
// come up as. PRESENTATIONS is false, which is what an existing classroom
|
|
// must come up as too: no room has ever had it, and an upgrade may not
|
|
// put a button on a bar nobody asked for.
|
|
/* CLASSROOM-FEATURES-BEGIN */
|
|
var WONDERINK = true;
|
|
var DVD = true;
|
|
var PARENT_CALL = true;
|
|
var PRESENTATIONS = false;
|
|
/* CLASSROOM-FEATURES-END */
|
|
|
|
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.
|
|
//
|
|
// Only the desktops that exist right now. A screen that appears later —
|
|
// the television switched on after a reboot at three in the morning, which
|
|
// is what Tiny Pebbles had — gets a desktop Plasma makes without this
|
|
// file. That one takes the look and feel's default wallpaper, which is the
|
|
// classroom's package, and classroom-desktop-wallpaper writes it in by
|
|
// name before the shell next starts.
|
|
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.
|
|
if (PARENT_CALL) {
|
|
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);
|
|
}
|
|
|
|
// Help is intentionally absent from this release's teacher-facing panel.
|
|
// Its launcher, source pages and build pipeline remain installed for the
|
|
// documentation correction pass; only the unfinished entry point is hidden.
|
|
|
|
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 LAUNCHERS, IN ONE FIXED ORDER.
|
|
//
|
|
// The order is written here and nowhere else, so the same set of enabled
|
|
// applications produces the same bar on every machine in the church.
|
|
// Anything switched off is left out of the list rather than blanked, so
|
|
// the remaining launchers close up and there is never a gap where a
|
|
// disabled application used to be.
|
|
//
|
|
// The browser is always present. Wonder Ink and the disc player are
|
|
// answered above.
|
|
var launchers = [];
|
|
|
|
if (WONDERINK) {
|
|
launchers.push("applications:ekklesia-wonderink.desktop");
|
|
}
|
|
|
|
launchers.push("applications:google-chrome.desktop");
|
|
|
|
if (DVD) {
|
|
launchers.push("applications:ekklesia-dvd.desktop");
|
|
}
|
|
|
|
// LAST, AND THAT IS THE WHOLE REASON IT IS HERE.
|
|
//
|
|
// Every existing room has Wonder Ink, the browser and the disc player in
|
|
// that order, and teachers have been pressing them in that order for
|
|
// months. Appending keeps all three exactly where they are on every
|
|
// machine that upgrades; putting Presentations anywhere else in the row
|
|
// would move a button somebody reaches for without looking.
|
|
if (PRESENTATIONS) {
|
|
launchers.push("applications:ekklesia-presentations.desktop");
|
|
}
|
|
|
|
tasks.writeConfig("launchers", launchers.join(","));
|
|
|
|
// THE ORDER STAYS PUT WHEN AN APPLICATION OPENS.
|
|
//
|
|
// 1 is "manually", and it has to be 1. This is not a preference; it is
|
|
// the only value at which the Icons-Only Task Manager keeps a running
|
|
// application in its pinned position.
|
|
//
|
|
// 0.2.4 set this to 0 to stop teachers dragging the launchers about, and
|
|
// that worked — and broke the order instead, which is the bug this
|
|
// replaces. Two lines of the stock applet explain the whole thing:
|
|
//
|
|
// main.qml:153 hideActivatedLaunchers: tasks.iconsOnly || ...
|
|
// main.qml:155 launchInPlace: tasks.iconsOnly && sortingStrategy === 1
|
|
//
|
|
// For an icons-only bar the first is ALWAYS true: the moment an
|
|
// application starts, its launcher is hidden. The second is what puts the
|
|
// running window back in the launcher's place — and only at 1. At 0 the
|
|
// launcher vanished and the window was appended after the others, so
|
|
// opening the browser moved it behind the disc player. Reproduced in the
|
|
// lab with a real Chrome window, and fixed by this line; both measured.
|
|
//
|
|
// The cost is that manual sorting is also the only mode in which
|
|
// MouseHandler.qml accepts a reordering drop, so a teacher can drag the
|
|
// launchers again within a session. There is no value that gives both,
|
|
// and no Kiosk key that separates them. classroom-desktop-reset rebuilds
|
|
// this bar from the package at every login, so a drag never outlives the
|
|
// session, and docs/testing.md records the trade rather than hiding it.
|
|
tasks.writeConfig("sortingStrategy", 1);
|
|
// Launchers stay together at the start of the row and running windows
|
|
// appear after them, so opening or closing an application cannot move a
|
|
// pinned icon. This is Plasma's default; it is written down because the
|
|
// classroom depends on it.
|
|
tasks.writeConfig("separateLaunchers", true);
|
|
// 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);
|