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
@@ -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
|
||||
Reference in New Issue
Block a user