feat: give the classroom a desktop instead of a shell
The whole appliance UI is now configuration for a desktop Debian already ships: a Plasma 6.3 session with a colour scheme, a look and feel package that builds the bar, window rules, and KDE's own Kiosk restrictions. Two things were measured rather than assumed, and both changed a decision. Plasma restarts a crashed panel three times a minute and then gives up, which is the failure a classroom has already had. Four lines of systemd drop-in make it unconditional; the panel then survived eight SIGKILLs a second apart, back each time in 2.4s. Plasma draws a minimised task and a background task identically, so the five states the room needs cannot all be shown. Rather than write a task manager, the classroom removes minimise: clicking a launcher always means show me this. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
bfc7caf28f
commit
87b55761c6
@@ -2,25 +2,20 @@
|
||||
"DefaultBrowserSettingEnabled": false,
|
||||
"PromotionalTabsEnabled": false,
|
||||
"MetricsReportingEnabled": false,
|
||||
|
||||
"BrowserSignin": 0,
|
||||
"SyncDisabled": true,
|
||||
"SigninInterceptionEnabled": false,
|
||||
|
||||
"BrowserAddPersonEnabled": false,
|
||||
"BrowserGuestModeEnabled": false,
|
||||
"ProfilePickerOnStartupAvailability": 1,
|
||||
|
||||
"PasswordManagerEnabled": false,
|
||||
"PasswordLeakDetectionEnabled": false,
|
||||
"BackgroundModeEnabled": false,
|
||||
"DisablePrintPreview": true,
|
||||
|
||||
"CookiesSessionOnlyForUrls": [
|
||||
"[*.]wonderink.org"
|
||||
],
|
||||
|
||||
"ShowHomeButton": true,
|
||||
"HomepageIsNewTabPage": false,
|
||||
"HomepageLocation": "https://app.wonderink.org/"
|
||||
"HomepageLocation": "https://www.youtube.com/"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"RestoreOnStartup": 4,
|
||||
"RestoreOnStartupURLs": [
|
||||
"https://app.wonderink.org/"
|
||||
"https://www.youtube.com/"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Parent Call.
|
||||
|
||||
Deliberately not a colour tile. Parent Call is not one of the room's
|
||||
applications and does not sit in the row with them, so it is drawn in
|
||||
the interface's own accent as a line mark: present, reachable, and
|
||||
visibly a different kind of thing from Wonder Ink and the browser. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<!-- Inset so the mark has the same optical size as the filled tiles
|
||||
beside it in the bar; an outline drawn to the edges reads larger. -->
|
||||
<g transform="translate(64 64) scale(0.62) translate(-64 -64)"
|
||||
fill="none" stroke="#4FB3A8" stroke-width="8"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M40 58a24 24 0 0 1 48 0c0 18 6 24 9 28H31c3-4 9-10 9-28z"/>
|
||||
<path d="M55 94a9 9 0 0 0 18 0"/>
|
||||
<path d="M64 26v-8"/>
|
||||
<path d="M100 30a30 30 0 0 1 8 20"/>
|
||||
<path d="M28 30a30 30 0 0 0-8 20"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 992 B |
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Wonder Ink.
|
||||
|
||||
A stand-in for the product's own mark, which the classroom does not
|
||||
have a licensed asset for. It is a filled colour tile rather than a
|
||||
line drawing on purpose: the room already learned, the hard way, that
|
||||
a monochrome glyph on a bar is read as a decoration and not as an
|
||||
application. Somebody asked whether the old browser glyph meant "the
|
||||
Internet". A tile with its own colour does not get that question. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<defs>
|
||||
<linearGradient id="tile" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#4FB3A8"/>
|
||||
<stop offset="0.55" stop-color="#3E93A8"/>
|
||||
<stop offset="1" stop-color="#7C6FC4"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="6" y="6" width="116" height="116" rx="28" fill="url(#tile)"/>
|
||||
<path d="M64 30c0 0 26 28 26 44a26 26 0 0 1-52 0c0-16 26-44 26-44z"
|
||||
fill="#FFFFFF" fill-opacity="0.94"/>
|
||||
<path d="M50 76a14 14 0 0 0 10 13" stroke="#3E93A8" stroke-width="5"
|
||||
stroke-linecap="round" fill="none" opacity="0.55"/>
|
||||
<g fill="#FFFFFF" opacity="0.9">
|
||||
<path d="M96 34l2.6 6.4L105 43l-6.4 2.6L96 52l-2.6-6.4L87 43l6.4-2.6z"/>
|
||||
<circle cx="34" cy="40" r="3.2"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,25 @@
|
||||
[Desktop Entry]
|
||||
# The room's browser, installed to /usr/local/share/applications, which
|
||||
# XDG_DATA_DIRS searches before /usr/share. Chrome's own entry is left
|
||||
# where Chrome's package put it and is simply never the one that is found.
|
||||
#
|
||||
# It has to carry Chrome's file name rather than a name of our own. Plasma
|
||||
# matches a window to its launcher by the application id the window
|
||||
# reports, and Chrome reports "google-chrome". A launcher under any other
|
||||
# name gives a teacher two buttons for one browser: a launcher that always
|
||||
# looks closed, and a window that appears beside it. That was measured, not
|
||||
# assumed — it is what the first build did.
|
||||
Type=Application
|
||||
Name=Browser
|
||||
GenericName=Web browser
|
||||
Comment=YouTube and the rest of the web
|
||||
Icon=google-chrome
|
||||
Exec=/usr/local/bin/classroom-browser %U
|
||||
Terminal=false
|
||||
Categories=Network;WebBrowser;
|
||||
StartupNotify=true
|
||||
StartupWMClass=google-chrome
|
||||
MimeType=text/html;x-scheme-handler/http;x-scheme-handler/https;
|
||||
# Chrome's own entry offers a new window and an incognito window from the
|
||||
# launcher's right-click menu. Neither belongs in a shared room.
|
||||
Actions=
|
||||
@@ -0,0 +1,13 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=DVD
|
||||
Comment=Play the disc in the drive
|
||||
Exec=/usr/local/bin/classroom-dvd
|
||||
Icon=media-optical-dvd
|
||||
Terminal=false
|
||||
Categories=AudioVideo;Player;
|
||||
StartupNotify=true
|
||||
StartupWMClass=vlc
|
||||
# Never in a menu or a launcher by itself. The DVD appears when a disc is
|
||||
# in the drive, through Plasma's own device notifier, and goes away with it.
|
||||
NoDisplay=true
|
||||
@@ -0,0 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Parent Call
|
||||
Comment=Ask for a child's parent to come to the room
|
||||
Exec=/usr/local/bin/classroom-parent-call
|
||||
Icon=ekklesia-parent-call
|
||||
Terminal=false
|
||||
Categories=Utility;
|
||||
StartupNotify=false
|
||||
NoDisplay=false
|
||||
@@ -0,0 +1,15 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Wonder Ink
|
||||
GenericName=Lesson
|
||||
Comment=The Wonder Ink lesson for this room
|
||||
Exec=/usr/local/bin/classroom-wonderink
|
||||
Icon=ekklesia-wonderink
|
||||
Terminal=false
|
||||
Categories=Education;
|
||||
StartupNotify=true
|
||||
# How the panel knows that the window on screen belongs to this launcher.
|
||||
# Chrome derives an app id from the --app URL, and this must match it
|
||||
# exactly or the launcher and the window become two separate buttons.
|
||||
StartupWMClass=chrome-app.wonderink.org__-Default
|
||||
X-GNOME-SingleWindow=true
|
||||
@@ -0,0 +1,155 @@
|
||||
# Ekklesia Classroom — dark. The default.
|
||||
#
|
||||
# One set of tokens for the whole session: Plasma reads this file for the
|
||||
# panel, the notifications, the window decorations and every Qt dialog, so
|
||||
# there is one place to change a colour rather than a stylesheet per surface.
|
||||
#
|
||||
# The hues come from the classroom wallpaper — sage, teal, blue, lavender —
|
||||
# so the desktop sits on the landscape rather than in front of it.
|
||||
[General]
|
||||
Name=Ekklesia Classroom Dark
|
||||
ColorScheme=EkklesiaDark
|
||||
shadeSortColumn=true
|
||||
accentActiveTitlebar=false
|
||||
|
||||
[ColorEffects:Disabled]
|
||||
ChangeSelectionColor=
|
||||
Color=56,66,71
|
||||
ColorAmount=0
|
||||
ColorEffect=0
|
||||
ContrastAmount=0.5
|
||||
ContrastEffect=1
|
||||
Enable=
|
||||
IntensityAmount=0
|
||||
IntensityEffect=0
|
||||
|
||||
[ColorEffects:Inactive]
|
||||
ChangeSelectionColor=true
|
||||
Color=112,111,110
|
||||
ColorAmount=0.025
|
||||
ColorEffect=2
|
||||
ContrastAmount=0.1
|
||||
ContrastEffect=2
|
||||
Enable=false
|
||||
IntensityAmount=0
|
||||
IntensityEffect=0
|
||||
|
||||
[Colors:Button]
|
||||
BackgroundAlternate=30,42,47
|
||||
BackgroundNormal=25,35,40
|
||||
DecorationFocus=79,179,168
|
||||
DecorationHover=79,179,168
|
||||
ForegroundActive=79,179,168
|
||||
ForegroundInactive=147,165,170
|
||||
ForegroundLink=126,196,255
|
||||
ForegroundNegative=227,106,106
|
||||
ForegroundNeutral=224,177,92
|
||||
ForegroundNormal=230,237,239
|
||||
ForegroundPositive=111,207,151
|
||||
ForegroundVisited=156,138,222
|
||||
|
||||
[Colors:Selection]
|
||||
BackgroundAlternate=79,179,168
|
||||
BackgroundNormal=79,179,168
|
||||
DecorationFocus=79,179,168
|
||||
DecorationHover=79,179,168
|
||||
ForegroundActive=14,21,24
|
||||
ForegroundInactive=14,21,24
|
||||
ForegroundLink=14,21,24
|
||||
ForegroundNegative=14,21,24
|
||||
ForegroundNeutral=14,21,24
|
||||
ForegroundNormal=10,16,18
|
||||
ForegroundPositive=14,21,24
|
||||
ForegroundVisited=14,21,24
|
||||
|
||||
[Colors:Tooltip]
|
||||
BackgroundAlternate=25,35,40
|
||||
BackgroundNormal=20,28,32
|
||||
DecorationFocus=79,179,168
|
||||
DecorationHover=79,179,168
|
||||
ForegroundActive=79,179,168
|
||||
ForegroundInactive=147,165,170
|
||||
ForegroundLink=126,196,255
|
||||
ForegroundNegative=227,106,106
|
||||
ForegroundNeutral=224,177,92
|
||||
ForegroundNormal=230,237,239
|
||||
ForegroundPositive=111,207,151
|
||||
ForegroundVisited=156,138,222
|
||||
|
||||
[Colors:View]
|
||||
BackgroundAlternate=20,28,32
|
||||
BackgroundNormal=15,23,26
|
||||
DecorationFocus=79,179,168
|
||||
DecorationHover=79,179,168
|
||||
ForegroundActive=79,179,168
|
||||
ForegroundInactive=147,165,170
|
||||
ForegroundLink=126,196,255
|
||||
ForegroundNegative=227,106,106
|
||||
ForegroundNeutral=224,177,92
|
||||
ForegroundNormal=230,237,239
|
||||
ForegroundPositive=111,207,151
|
||||
ForegroundVisited=156,138,222
|
||||
|
||||
[Colors:Window]
|
||||
BackgroundAlternate=25,35,40
|
||||
BackgroundNormal=20,28,32
|
||||
DecorationFocus=79,179,168
|
||||
DecorationHover=79,179,168
|
||||
ForegroundActive=79,179,168
|
||||
ForegroundInactive=147,165,170
|
||||
ForegroundLink=126,196,255
|
||||
ForegroundNegative=227,106,106
|
||||
ForegroundNeutral=224,177,92
|
||||
ForegroundNormal=230,237,239
|
||||
ForegroundPositive=111,207,151
|
||||
ForegroundVisited=156,138,222
|
||||
|
||||
[Colors:Complementary]
|
||||
BackgroundAlternate=25,35,40
|
||||
BackgroundNormal=20,28,32
|
||||
DecorationFocus=79,179,168
|
||||
DecorationHover=79,179,168
|
||||
ForegroundActive=79,179,168
|
||||
ForegroundInactive=147,165,170
|
||||
ForegroundLink=126,196,255
|
||||
ForegroundNegative=227,106,106
|
||||
ForegroundNeutral=224,177,92
|
||||
ForegroundNormal=230,237,239
|
||||
ForegroundPositive=111,207,151
|
||||
ForegroundVisited=156,138,222
|
||||
|
||||
[Colors:Header]
|
||||
BackgroundAlternate=25,35,40
|
||||
BackgroundNormal=18,26,30
|
||||
DecorationFocus=79,179,168
|
||||
DecorationHover=79,179,168
|
||||
ForegroundActive=79,179,168
|
||||
ForegroundInactive=147,165,170
|
||||
ForegroundLink=126,196,255
|
||||
ForegroundNegative=227,106,106
|
||||
ForegroundNeutral=224,177,92
|
||||
ForegroundNormal=230,237,239
|
||||
ForegroundPositive=111,207,151
|
||||
ForegroundVisited=156,138,222
|
||||
|
||||
[Colors:Header][Inactive]
|
||||
BackgroundAlternate=20,28,32
|
||||
BackgroundNormal=16,23,26
|
||||
DecorationFocus=79,179,168
|
||||
DecorationHover=79,179,168
|
||||
ForegroundActive=79,179,168
|
||||
ForegroundInactive=125,142,147
|
||||
ForegroundLink=126,196,255
|
||||
ForegroundNegative=227,106,106
|
||||
ForegroundNeutral=224,177,92
|
||||
ForegroundNormal=170,186,191
|
||||
ForegroundPositive=111,207,151
|
||||
ForegroundVisited=156,138,222
|
||||
|
||||
[WM]
|
||||
activeBackground=18,26,30
|
||||
activeBlend=79,179,168
|
||||
activeForeground=230,237,239
|
||||
inactiveBackground=16,23,26
|
||||
inactiveBlend=147,165,170
|
||||
inactiveForeground=147,165,170
|
||||
@@ -0,0 +1,158 @@
|
||||
# Ekklesia Classroom — light.
|
||||
#
|
||||
# GENERATED from EkklesiaDark.colors by tools/build-light-scheme.
|
||||
# Edit the dark scheme and regenerate; do not edit this file by hand.
|
||||
#
|
||||
# One set of tokens for the whole session: Plasma reads this file for the
|
||||
# panel, the notifications, the window decorations and every Qt dialog, so
|
||||
# there is one place to change a colour rather than a stylesheet per surface.
|
||||
#
|
||||
# The hues come from the classroom wallpaper — sage, teal, blue, lavender —
|
||||
# so the desktop sits on the landscape rather than in front of it.
|
||||
[General]
|
||||
Name=Ekklesia Classroom Light
|
||||
ColorScheme=EkklesiaLight
|
||||
shadeSortColumn=true
|
||||
accentActiveTitlebar=false
|
||||
|
||||
[ColorEffects:Disabled]
|
||||
ChangeSelectionColor=
|
||||
Color=56,66,71
|
||||
ColorAmount=0
|
||||
ColorEffect=0
|
||||
ContrastAmount=0.5
|
||||
ContrastEffect=1
|
||||
Enable=
|
||||
IntensityAmount=0
|
||||
IntensityEffect=0
|
||||
|
||||
[ColorEffects:Inactive]
|
||||
ChangeSelectionColor=true
|
||||
Color=112,111,110
|
||||
ColorAmount=0.025
|
||||
ColorEffect=2
|
||||
ContrastAmount=0.1
|
||||
ContrastEffect=2
|
||||
Enable=false
|
||||
IntensityAmount=0
|
||||
IntensityEffect=0
|
||||
|
||||
[Colors:Button]
|
||||
BackgroundAlternate=225,231,230
|
||||
BackgroundNormal=233,238,237
|
||||
DecorationFocus=46,140,130
|
||||
DecorationHover=46,140,130
|
||||
ForegroundActive=46,140,130
|
||||
ForegroundInactive=96,116,122
|
||||
ForegroundLink=26,110,180
|
||||
ForegroundNegative=192,57,57
|
||||
ForegroundNeutral=166,116,24
|
||||
ForegroundNormal=22,35,42
|
||||
ForegroundPositive=38,142,86
|
||||
ForegroundVisited=104,80,180
|
||||
|
||||
[Colors:Selection]
|
||||
BackgroundAlternate=46,140,130
|
||||
BackgroundNormal=46,140,130
|
||||
DecorationFocus=46,140,130
|
||||
DecorationHover=46,140,130
|
||||
ForegroundActive=255,255,255
|
||||
ForegroundInactive=255,255,255
|
||||
ForegroundLink=255,255,255
|
||||
ForegroundNegative=255,255,255
|
||||
ForegroundNeutral=255,255,255
|
||||
ForegroundNormal=255,255,255
|
||||
ForegroundPositive=255,255,255
|
||||
ForegroundVisited=255,255,255
|
||||
|
||||
[Colors:Tooltip]
|
||||
BackgroundAlternate=233,238,237
|
||||
BackgroundNormal=242,245,244
|
||||
DecorationFocus=46,140,130
|
||||
DecorationHover=46,140,130
|
||||
ForegroundActive=46,140,130
|
||||
ForegroundInactive=96,116,122
|
||||
ForegroundLink=26,110,180
|
||||
ForegroundNegative=192,57,57
|
||||
ForegroundNeutral=166,116,24
|
||||
ForegroundNormal=22,35,42
|
||||
ForegroundPositive=38,142,86
|
||||
ForegroundVisited=104,80,180
|
||||
|
||||
[Colors:View]
|
||||
BackgroundAlternate=242,245,244
|
||||
BackgroundNormal=255,255,255
|
||||
DecorationFocus=46,140,130
|
||||
DecorationHover=46,140,130
|
||||
ForegroundActive=46,140,130
|
||||
ForegroundInactive=96,116,122
|
||||
ForegroundLink=26,110,180
|
||||
ForegroundNegative=192,57,57
|
||||
ForegroundNeutral=166,116,24
|
||||
ForegroundNormal=22,35,42
|
||||
ForegroundPositive=38,142,86
|
||||
ForegroundVisited=104,80,180
|
||||
|
||||
[Colors:Window]
|
||||
BackgroundAlternate=233,238,237
|
||||
BackgroundNormal=242,245,244
|
||||
DecorationFocus=46,140,130
|
||||
DecorationHover=46,140,130
|
||||
ForegroundActive=46,140,130
|
||||
ForegroundInactive=96,116,122
|
||||
ForegroundLink=26,110,180
|
||||
ForegroundNegative=192,57,57
|
||||
ForegroundNeutral=166,116,24
|
||||
ForegroundNormal=22,35,42
|
||||
ForegroundPositive=38,142,86
|
||||
ForegroundVisited=104,80,180
|
||||
|
||||
[Colors:Complementary]
|
||||
BackgroundAlternate=233,238,237
|
||||
BackgroundNormal=242,245,244
|
||||
DecorationFocus=46,140,130
|
||||
DecorationHover=46,140,130
|
||||
ForegroundActive=46,140,130
|
||||
ForegroundInactive=96,116,122
|
||||
ForegroundLink=26,110,180
|
||||
ForegroundNegative=192,57,57
|
||||
ForegroundNeutral=166,116,24
|
||||
ForegroundNormal=22,35,42
|
||||
ForegroundPositive=38,142,86
|
||||
ForegroundVisited=104,80,180
|
||||
|
||||
[Colors:Header]
|
||||
BackgroundAlternate=233,238,237
|
||||
BackgroundNormal=236,241,240
|
||||
DecorationFocus=46,140,130
|
||||
DecorationHover=46,140,130
|
||||
ForegroundActive=46,140,130
|
||||
ForegroundInactive=96,116,122
|
||||
ForegroundLink=26,110,180
|
||||
ForegroundNegative=192,57,57
|
||||
ForegroundNeutral=166,116,24
|
||||
ForegroundNormal=22,35,42
|
||||
ForegroundPositive=38,142,86
|
||||
ForegroundVisited=104,80,180
|
||||
|
||||
[Colors:Header][Inactive]
|
||||
BackgroundAlternate=242,245,244
|
||||
BackgroundNormal=228,234,233
|
||||
DecorationFocus=46,140,130
|
||||
DecorationHover=46,140,130
|
||||
ForegroundActive=46,140,130
|
||||
ForegroundInactive=120,138,144
|
||||
ForegroundLink=26,110,180
|
||||
ForegroundNegative=192,57,57
|
||||
ForegroundNeutral=166,116,24
|
||||
ForegroundNormal=80,99,105
|
||||
ForegroundPositive=38,142,86
|
||||
ForegroundVisited=104,80,180
|
||||
|
||||
[WM]
|
||||
activeBackground=236,241,240
|
||||
activeBlend=46,140,130
|
||||
activeForeground=22,35,42
|
||||
inactiveBackground=228,234,233
|
||||
inactiveBlend=96,116,122
|
||||
inactiveForeground=96,116,122
|
||||
@@ -0,0 +1,31 @@
|
||||
# Everything the classroom's appearance is made of, in one place.
|
||||
#
|
||||
# Plasma reads this when the look and feel is applied, so the panel, the
|
||||
# window decorations, the notifications and every Qt dialog in the session
|
||||
# are described here rather than in a stylesheet per surface.
|
||||
|
||||
[kdeglobals][KDE]
|
||||
widgetStyle=Breeze
|
||||
|
||||
[kdeglobals][General]
|
||||
ColorScheme=EkklesiaDark
|
||||
AccentColor=79,179,168
|
||||
|
||||
[kdeglobals][Icons]
|
||||
Theme=breeze-dark
|
||||
|
||||
[plasmarc][Theme]
|
||||
name=default
|
||||
|
||||
[kcminputrc][Mouse]
|
||||
cursorTheme=breeze_cursors
|
||||
|
||||
[kwinrc][org.kde.kdecoration2]
|
||||
library=org.kde.breeze
|
||||
theme=Breeze
|
||||
|
||||
[Wallpaper]
|
||||
Image=/usr/share/backgrounds/ekklesia/classroom-calm.png
|
||||
|
||||
[KSplash]
|
||||
Theme=None
|
||||
@@ -0,0 +1,124 @@
|
||||
// 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.
|
||||
var parentCall = panel.addWidget("org.kde.plasma.icon");
|
||||
parentCall.currentConfigGroup = ["General"];
|
||||
parentCall.writeConfig(
|
||||
"url",
|
||||
"file:///usr/share/applications/ekklesia-parent-call.desktop"
|
||||
);
|
||||
|
||||
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"];
|
||||
tasks.writeConfig("launchers", [
|
||||
"applications:ekklesia-wonderink.desktop",
|
||||
"applications:google-chrome.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.
|
||||
//
|
||||
// Four 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");
|
||||
panel.addWidget("org.kde.plasma.volume");
|
||||
|
||||
// Present only while there is something in a drive. Plasma's own Solid
|
||||
// device notifier is what makes the DVD appear with the disc and leave
|
||||
// with it, so nothing in the classroom polls for media.
|
||||
panel.addWidget("org.kde.plasma.devicenotifier");
|
||||
|
||||
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");
|
||||
// Left to itself the clock grows to the height of the bar and becomes the
|
||||
// largest text in the room. It is status, not a headline.
|
||||
clock.writeConfig("autoFontAndSize", false);
|
||||
clock.writeConfig("fontSize", 15);
|
||||
clock.writeConfig("fontWeight", 500);
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"KPackageStructure": "Plasma/LookAndFeel",
|
||||
"KPlugin": {
|
||||
"Authors": [
|
||||
{
|
||||
"Name": "Ekklesia"
|
||||
}
|
||||
],
|
||||
"Category": "",
|
||||
"Description": "The classroom appliance desktop",
|
||||
"Id": "org.ekklesia.classroom.desktop",
|
||||
"License": "GPLv2+",
|
||||
"Name": "Ekklesia Classroom",
|
||||
"Website": "https://riverofglorymn.org"
|
||||
},
|
||||
"X-Plasma-APIVersion": "2"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
# Solid decides when this exists. Plasma's device notifier offers it while
|
||||
# a video DVD is in the drive and withdraws it when the disc is ejected, so
|
||||
# a room without a drive shows nothing and a room with one needs no setting
|
||||
# changed. Nothing polls.
|
||||
X-KDE-Solid-Predicate=[[ StorageVolume.ignored == false AND StorageVolume.usage == 'Other' ] AND [ OpticalDisc.availableContent & 'VideoDvd' ]]
|
||||
Actions=Play;
|
||||
|
||||
[Desktop Action Play]
|
||||
Name=Play the DVD
|
||||
Icon=media-optical-dvd
|
||||
Exec=/usr/local/bin/classroom-dvd %f
|
||||
@@ -0,0 +1,60 @@
|
||||
# Ekklesia Classroom session policy.
|
||||
#
|
||||
# Installed to /etc/xdg/kdeglobals, where it is the bottom of Plasma's
|
||||
# configuration cascade. Every group is marked [$i] — immutable — so a
|
||||
# teacher, a stray click or a misbehaving application cannot override it
|
||||
# from the user's own configuration. This is KDE's own Kiosk mechanism:
|
||||
# nothing here is achieved by deleting a binary or hiding a menu entry.
|
||||
#
|
||||
# Lifting a restriction for maintenance is a one-line edit to this file
|
||||
# followed by a session restart, which is what makes the appliance
|
||||
# serviceable rather than merely locked.
|
||||
|
||||
[KDE Action Restrictions][$i]
|
||||
# No way to reach a shell, a command line, or an arbitrary program.
|
||||
action/kdesktop_rmb=false
|
||||
action/kwin_rmb=false
|
||||
action/openwith=false
|
||||
action/switch_user=false
|
||||
action/start_new_session=false
|
||||
action/lock_screen=false
|
||||
run_command=false
|
||||
shell_access=false
|
||||
logout=false
|
||||
# The desktop and the panel are a fixed part of the appliance.
|
||||
editable_desktop_icons=false
|
||||
editable_bookmarks=false
|
||||
movable_toolbars=false
|
||||
plasma/plasmashell/unlockedDesktop=false
|
||||
plasma-desktop/scripting_console=false
|
||||
# Nothing in the classroom should offer to file a bug or open a manual.
|
||||
action/help_report_bug=false
|
||||
action/help_about_kde=false
|
||||
action/help_contents=false
|
||||
|
||||
[General][$i]
|
||||
ColorScheme=EkklesiaDark
|
||||
AccentColor=79,179,168
|
||||
# The teacher's own words are not decoration: keep text rendering plain
|
||||
# and readable rather than styled.
|
||||
XftAntialias=true
|
||||
XftHintStyle=hintslight
|
||||
XftSubPixel=rgb
|
||||
|
||||
[KDE][$i]
|
||||
widgetStyle=Breeze
|
||||
LookAndFeelPackage=org.ekklesia.classroom.desktop
|
||||
SingleClick=false
|
||||
AnimationDurationFactor=0.5
|
||||
|
||||
[Icons][$i]
|
||||
Theme=breeze-dark
|
||||
|
||||
[KFileDialog Settings][$i]
|
||||
Allow Expansion=false
|
||||
Automatically select filename extension=true
|
||||
Show Bookmarks=false
|
||||
Show Full Path=false
|
||||
Show Inline Previews=false
|
||||
Show Speedbar=false
|
||||
Sort directories first=true
|
||||
@@ -0,0 +1,9 @@
|
||||
# KRunner is a command line with a nicer face. The classroom has neither.
|
||||
[General][$i]
|
||||
Enabled=false
|
||||
ActivateWhenTypingOnDesktop=false
|
||||
[Plugins][$i]
|
||||
shellEnabled=false
|
||||
baloosearchEnabled=false
|
||||
krunner_appstreamEnabled=false
|
||||
krunner_shellEnabled=false
|
||||
@@ -0,0 +1,9 @@
|
||||
# A classroom appliance must never present a password prompt to a teacher.
|
||||
# There is no lock screen, and nothing can bring one up: the action itself
|
||||
# is disabled in kdeglobals as well, so a keyboard shortcut cannot reach it.
|
||||
[Daemon][$i]
|
||||
Autolock=false
|
||||
LockOnResume=false
|
||||
LockOnStart=false
|
||||
LockGrace=0
|
||||
Timeout=0
|
||||
@@ -0,0 +1,8 @@
|
||||
# The room is not somebody's account. Every session starts from the same
|
||||
# empty desktop, so what the last teacher left open is never the first
|
||||
# thing the next one sees.
|
||||
[General][$i]
|
||||
loginMode=emptySession
|
||||
confirmLogout=false
|
||||
offerShutdown=false
|
||||
shutdownType=0
|
||||
@@ -0,0 +1,102 @@
|
||||
# The classroom's window manager.
|
||||
#
|
||||
# The shape of this file is the argument for the whole architecture: window
|
||||
# stacking, minimising, dialog placement and full-screen media are settings
|
||||
# here, not code somewhere in the classroom.
|
||||
|
||||
[Compositing][$i]
|
||||
Enabled=true
|
||||
# Let KWin choose between OpenGL and software rendering by itself. A
|
||||
# classroom machine that loses acceleration after a kernel update should
|
||||
# come up slower, not blank.
|
||||
WindowsBlockCompositing=true
|
||||
AllowTearing=false
|
||||
LatencyPolicy=Medium
|
||||
|
||||
[Desktops][$i]
|
||||
Number=1
|
||||
Rows=1
|
||||
# One desktop, so a teacher cannot land on an empty one and conclude the
|
||||
# computer has lost their work.
|
||||
|
||||
[Windows][$i]
|
||||
Placement=Centered
|
||||
FocusPolicy=ClickToFocus
|
||||
AutoRaise=false
|
||||
DelayFocus=0
|
||||
FocusStealingPreventionLevel=1
|
||||
# A dialog belongs to the window that opened it and stays with it. This is
|
||||
# what keeps a print dialog in front of the page it is printing without
|
||||
# anything in the classroom arranging it.
|
||||
SeparateScreenFocus=false
|
||||
ActiveMouseScreen=false
|
||||
TitlebarDoubleClickCommand=Maximize
|
||||
MaximizeButtonLeftClickCommand=Maximize
|
||||
MaximizeButtonMiddleClickCommand=Maximize
|
||||
MaximizeButtonRightClickCommand=Maximize
|
||||
|
||||
[MouseBindings][$i]
|
||||
CommandAllKey=Meta
|
||||
CommandAll1=Move
|
||||
CommandAll2=Nothing
|
||||
CommandAll3=Nothing
|
||||
CommandTitlebarWheel=Nothing
|
||||
CommandAllWheel=Nothing
|
||||
|
||||
[TabBox][$i]
|
||||
# No window switcher overlay. The bottom bar is the way between windows.
|
||||
ShowTabBox=false
|
||||
|
||||
[Plugins][$i]
|
||||
# Effects the classroom uses, and nothing else. Every line that is false is
|
||||
# an effect that will not be loaded at all.
|
||||
blurEnabled=true
|
||||
contrastEnabled=true
|
||||
kwin4_effect_fadeEnabled=true
|
||||
kwin4_effect_translucencyEnabled=false
|
||||
kwin4_effect_dialogparentEnabled=true
|
||||
kwin4_effect_squashEnabled=true
|
||||
kwin4_effect_maximizeEnabled=true
|
||||
kwin4_effect_scaleEnabled=true
|
||||
kwin4_effect_fullscreenEnabled=true
|
||||
slidingpopupsEnabled=true
|
||||
screenedgeEnabled=false
|
||||
cubeEnabled=false
|
||||
desktopgridEnabled=false
|
||||
overviewEnabled=false
|
||||
windowviewEnabled=false
|
||||
wobblywindowsEnabled=false
|
||||
magiclampEnabled=false
|
||||
slideEnabled=false
|
||||
zoomEnabled=false
|
||||
mouseclickEnabled=false
|
||||
showfpsEnabled=false
|
||||
thumbnailasideEnabled=false
|
||||
kwin4_effect_dimscreenEnabled=false
|
||||
kwin4_effect_morphingpopupsEnabled=false
|
||||
|
||||
[Effect-blur][$i]
|
||||
BlurStrength=8
|
||||
NoiseStrength=2
|
||||
|
||||
[org.kde.kdecoration2][$i]
|
||||
library=org.kde.breeze
|
||||
theme=Breeze
|
||||
# A pin and a close button, and nothing else.
|
||||
#
|
||||
# The pin is the Live View story: keeping a window above the others is a
|
||||
# window-manager state, not a feature the classroom has to invent. There is
|
||||
# deliberately no minimise button, because a minimised window is the one
|
||||
# thing a teacher cannot see the state of — measured, not assumed. Double
|
||||
# clicking the title bar still maximises, so nothing is unreachable.
|
||||
ButtonsOnLeft=
|
||||
ButtonsOnRight=FX
|
||||
ShowToolTips=false
|
||||
BorderSize=None
|
||||
BorderSizeAuto=false
|
||||
|
||||
[Script-desktopchangeosd][$i]
|
||||
Enabled=false
|
||||
|
||||
[Xwayland][$i]
|
||||
Scale=1
|
||||
@@ -0,0 +1,48 @@
|
||||
# Window rules.
|
||||
#
|
||||
# There are three, they are all about size, and none of them is about
|
||||
# stacking. Dialogs staying in front of the window that opened them,
|
||||
# secondary windows floating over the main one instead of resizing it, and
|
||||
# a print dialog being the window in front are all ordinary window-manager
|
||||
# behaviour here, so there is nothing to write down.
|
||||
#
|
||||
# `types=1` is NET::Normal only. Without it a rule that maximises would
|
||||
# also maximise the dialogs, which is exactly the behaviour the classroom
|
||||
# is moving away from.
|
||||
|
||||
[General]
|
||||
count=3
|
||||
rules=classroom-browser,classroom-wonderink,classroom-video
|
||||
|
||||
[classroom-browser]
|
||||
Description=The classroom browser fills the screen
|
||||
wmclass=google-chrome
|
||||
wmclassmatch=1
|
||||
wmclasscomplete=false
|
||||
types=1
|
||||
maximizehoriz=true
|
||||
maximizehorizrule=3
|
||||
maximizevert=true
|
||||
maximizevertrule=3
|
||||
|
||||
[classroom-wonderink]
|
||||
Description=Wonder Ink fills the screen
|
||||
# Chrome derives this from the --app URL. Measured on a running session
|
||||
# rather than guessed; it is also what the launcher's StartupWMClass says,
|
||||
# and the two have to agree or the panel shows two buttons for one app.
|
||||
wmclass=chrome-app.wonderink.org__-Default
|
||||
wmclassmatch=1
|
||||
wmclasscomplete=false
|
||||
types=1
|
||||
maximizehoriz=true
|
||||
maximizehorizrule=3
|
||||
maximizevert=true
|
||||
maximizevertrule=3
|
||||
|
||||
[classroom-video]
|
||||
Description=Video is an appliance screen, not a window
|
||||
wmclass=vlc
|
||||
wmclassmatch=2
|
||||
wmclasscomplete=false
|
||||
noborder=true
|
||||
noborderrule=2
|
||||
@@ -0,0 +1,16 @@
|
||||
# Small cards, top right, out of the way of the bottom bar and of anything
|
||||
# a teacher is reading. Plasma's own notification service does this; the
|
||||
# classroom does not run a notification daemon of its own.
|
||||
[Notifications][$i]
|
||||
PopupPosition=TopRight
|
||||
PopupTimeout=6000
|
||||
LowPriorityPopups=false
|
||||
LowPriorityHistory=false
|
||||
|
||||
[Jobs][$i]
|
||||
PermanentPopups=false
|
||||
InNotifications=true
|
||||
|
||||
[DoNotDisturb][$i]
|
||||
WhenFullscreen=true
|
||||
WhenScreensMirrored=false
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 208 KiB |
Reference in New Issue
Block a user