feat: scale the shell to the room's television
A 32" panel a few feet from the children and a 65" set across a hall want the same design at different sizes. UI_SCALE in device.conf now sets that, and nobody has to edit CSS or source to tune a room. The stylesheet and the notification config become templates carrying measurement tokens. classroom-dock resolves the stylesheet in memory at startup; classroom-notifications resolves the notification config into the session's runtime directory and execs mako on it, so the process is still just mako and everything that looks for it by name still finds it. Neither template is rewritten on disk, so an update cannot lose a room's setting and a room cannot drift from the packaged design. Dock height and the reserved strip, corner radii, padding, button size, spacing, every icon, the clock and its inset, and the notification geometry all follow the scale. Colours, translucency and the hairline borders do not: those are the design, not the size. At UI_SCALE=1.0 the rendered stylesheet is byte-identical to the one the shell used before any of this existed, which is the property worth keeping. Values outside 0.8 to 1.5 are clamped and anything that is not a number falls back to 1.0, so a typo in device.conf cannot produce an unusable classroom. Device configuration moves into a shared module, since the dock and the notification daemon now have to agree about what a setting means. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
02094a6931
commit
428eb27a74
@@ -1,3 +1,11 @@
|
||||
/* Ekklesia Classroom dock
|
||||
*
|
||||
* A template, not plain CSS. classroom-dock substitutes the bracketed
|
||||
* measurements at startup from UI_SCALE in device.conf, so a room can
|
||||
* be tuned for its TV without anyone editing this file. At UI_SCALE=1.0
|
||||
* every token resolves to the value it had before scaling existed.
|
||||
*/
|
||||
|
||||
window#classroom-dock,
|
||||
window#classroom-clock {
|
||||
background-color: transparent;
|
||||
@@ -12,9 +20,9 @@ window#classroom-clock {
|
||||
background-color: rgba(34, 38, 50, 0.62);
|
||||
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 24px;
|
||||
border-radius: @dock-radius@px;
|
||||
|
||||
padding: 8px 10px;
|
||||
padding: @dock-padding-v@px @dock-padding-h@px;
|
||||
|
||||
/* Important: no shadow here.
|
||||
GTK was clipping it against the rectangular window edge. */
|
||||
@@ -28,13 +36,13 @@ button.dock-button {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
border-radius: @button-radius@px;
|
||||
|
||||
padding: 6px;
|
||||
padding: @button-padding@px;
|
||||
margin: 0;
|
||||
|
||||
min-width: 44px;
|
||||
min-height: 44px;
|
||||
min-width: @button-size@px;
|
||||
min-height: @button-size@px;
|
||||
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
@@ -74,11 +82,11 @@ button.dock-button image {
|
||||
background-color: rgba(34, 38, 50, 0.62);
|
||||
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 16px;
|
||||
border-radius: @clock-radius@px;
|
||||
|
||||
padding: 7px 12px;
|
||||
padding: @clock-padding-v@px @clock-padding-h@px;
|
||||
|
||||
font-size: 17px;
|
||||
font-size: @clock-font@px;
|
||||
font-weight: 600;
|
||||
|
||||
box-shadow: none;
|
||||
@@ -4,8 +4,13 @@
|
||||
# Matched to the dock: same dark slate (#222632), same hairline white
|
||||
# border, same rounded corners, white text. Kept slightly more opaque
|
||||
# than the dock so text stays readable over the wallpaper and over video.
|
||||
#
|
||||
# A template, not a finished config. classroom-notifications resolves the
|
||||
# bracketed measurements from UI_SCALE in device.conf and starts mako on
|
||||
# the result. At UI_SCALE=1.0 they resolve to the values they had before
|
||||
# scaling existed.
|
||||
|
||||
font=DejaVu Sans 12
|
||||
font=DejaVu Sans @font-size@
|
||||
|
||||
background-color=#222632e6
|
||||
text-color=#ffffffff
|
||||
@@ -13,13 +18,13 @@ border-color=#ffffff21
|
||||
progress-color=over #464b5ae6
|
||||
|
||||
border-size=1
|
||||
border-radius=18
|
||||
border-radius=@radius@
|
||||
|
||||
padding=14,18
|
||||
margin=18
|
||||
padding=@padding-v@,@padding-h@
|
||||
margin=@margin@
|
||||
|
||||
width=380
|
||||
height=160
|
||||
width=@width@
|
||||
height=@height@
|
||||
|
||||
anchor=top-right
|
||||
layer=overlay
|
||||
@@ -30,7 +35,7 @@ markup=1
|
||||
format=<b>%s</b>\n%b
|
||||
|
||||
icons=1
|
||||
max-icon-size=48
|
||||
max-icon-size=@icon-size@
|
||||
|
||||
default-timeout=6000
|
||||
|
||||
+3
-3
@@ -7,9 +7,9 @@ set $mod Mod4
|
||||
output * bg /usr/share/backgrounds/ekklesia/classroom-default.png fill
|
||||
|
||||
# Notifications, started before the dock so nothing can race D-Bus into
|
||||
# activating an unstyled mako first. mako only ever searches ~/.config,
|
||||
# so the packaged config has to be named explicitly.
|
||||
exec --no-startup-id /usr/bin/mako --config /etc/ekklesia-classroom/mako/config
|
||||
# activating an unstyled mako first. The wrapper resolves the styling at
|
||||
# the room's UI scale and execs mako, so the process is still just mako.
|
||||
exec --no-startup-id /usr/local/bin/classroom-notifications
|
||||
|
||||
# Ekklesia Classroom dock
|
||||
exec --no-startup-id /usr/local/bin/classroom-dock
|
||||
|
||||
@@ -11,6 +11,17 @@ before promoting to stable with `./update_stable.sh`.
|
||||
- [ ] Dock appears, centred
|
||||
- [ ] Clock appears, bottom right
|
||||
|
||||
## UI scale
|
||||
|
||||
- [ ] `UI_SCALE=1.0` looks exactly as it did before scaling existed
|
||||
- [ ] `UI_SCALE=1.25`, then `sudo systemctl restart getty@tty1`:
|
||||
dock, icons, clock and notifications all grow together
|
||||
- [ ] `UI_SCALE=0.8` shrinks them together
|
||||
- [ ] The reserved bottom strip grows and shrinks with the dock, and a
|
||||
maximised Chrome window still stops above it
|
||||
- [ ] A nonsense value (`UI_SCALE=banana`) still gives a working shell
|
||||
- [ ] An extreme value (`UI_SCALE=9`) is clamped, not obeyed
|
||||
|
||||
## Reserved bottom shell (regression)
|
||||
|
||||
The bottom strip is one full-width layer-shell surface with a 76px
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# UI scale
|
||||
|
||||
Every classroom gets the same design at a size that suits its TV. A 32"
|
||||
panel a few feet from the children and a 65" set across a hall want
|
||||
different sizes of the same dock, not different docks.
|
||||
|
||||
## Changing it
|
||||
|
||||
Edit `/etc/ekklesia-classroom/device.conf` on that endpoint:
|
||||
|
||||
```
|
||||
UI_SCALE=1.25
|
||||
```
|
||||
|
||||
Then restart the classroom shell:
|
||||
|
||||
```
|
||||
sudo systemctl restart getty@tty1
|
||||
```
|
||||
|
||||
That ends the session and the autologin brings it straight back with the
|
||||
new size. A reboot does the same thing. Nothing else needs touching, and
|
||||
no CSS or source file is ever edited to change a room's size.
|
||||
|
||||
## Values
|
||||
|
||||
| UI_SCALE | Roughly |
|
||||
| --- | --- |
|
||||
| 0.8 | Small or close-up panel |
|
||||
| 1.0 | Default. 1080p classroom TV, 32–50" |
|
||||
| 1.25 | Large room, or a set viewed from further back |
|
||||
| 1.5 | 65"+ |
|
||||
|
||||
Anything outside 0.8–1.5 is clamped to that range, and anything that is
|
||||
not a number at all falls back to 1.0, so a typo in device.conf cannot
|
||||
produce an unusable shell.
|
||||
|
||||
## What it scales
|
||||
|
||||
- Dock height, and the reserved strip at the bottom of the screen
|
||||
- Dock corner radius, padding and the spacing between buttons
|
||||
- Button size, padding and corner radius
|
||||
- Every dock icon
|
||||
- Clock text size, padding, corner radius and its inset from the edge
|
||||
- Notification width, height, padding, margin, corner radius, text size
|
||||
and icon size
|
||||
|
||||
Colours, translucency and the hairline borders do not scale: those are
|
||||
the design, not the size. At `UI_SCALE=1.0` the rendered stylesheet is
|
||||
byte-identical to the one the shell used before scaling existed.
|
||||
|
||||
## How it works
|
||||
|
||||
`/etc/ekklesia-classroom/dock/style.css.in` and
|
||||
`/etc/ekklesia-classroom/mako/config.in` are templates carrying
|
||||
measurement tokens. `classroom-dock` resolves the stylesheet in memory at
|
||||
startup; `classroom-notifications` resolves the notification config into
|
||||
the session's runtime directory and hands it to mako. Neither template is
|
||||
ever rewritten on disk, so an update cannot lose a room's setting and a
|
||||
room's setting cannot drift from the packaged design.
|
||||
@@ -0,0 +1,65 @@
|
||||
"""Device configuration for the Ekklesia Classroom shell.
|
||||
|
||||
Everything that has to agree about /etc/ekklesia-classroom/device.conf
|
||||
reads it through here, so the dock, the notification daemon and the DVD
|
||||
commands cannot drift apart over what a setting means.
|
||||
"""
|
||||
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
CONFIG_FILE = Path("/etc/ekklesia-classroom/device.conf")
|
||||
|
||||
TRUTHY = {"1", "true", "yes", "on", "enabled"}
|
||||
|
||||
# The dock is tuned for a 1080p classroom TV at 1.0. Smaller rooms with a
|
||||
# 32" panel sit near the bottom of this range, a 65" set near the top.
|
||||
UI_SCALE_DEFAULT = 1.0
|
||||
UI_SCALE_MIN = 0.8
|
||||
UI_SCALE_MAX = 1.5
|
||||
|
||||
|
||||
def read_device_config(path=None):
|
||||
config = {}
|
||||
path = Path(path) if path is not None else CONFIG_FILE
|
||||
|
||||
if not path.exists():
|
||||
return config
|
||||
|
||||
for raw_line in path.read_text().splitlines():
|
||||
line = raw_line.strip()
|
||||
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
|
||||
key, value = line.split("=", 1)
|
||||
config[key.strip()] = value.strip()
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def enabled(config, key, default=False):
|
||||
if key not in config:
|
||||
return default
|
||||
|
||||
return config[key].lower() in TRUTHY
|
||||
|
||||
|
||||
def ui_scale(config):
|
||||
"""UI_SCALE, clamped to something a classroom can actually use."""
|
||||
raw = config.get("UI_SCALE", "")
|
||||
|
||||
try:
|
||||
value = float(raw)
|
||||
except (TypeError, ValueError):
|
||||
return UI_SCALE_DEFAULT
|
||||
|
||||
if not math.isfinite(value):
|
||||
return UI_SCALE_DEFAULT
|
||||
|
||||
return min(max(value, UI_SCALE_MIN), UI_SCALE_MAX)
|
||||
|
||||
|
||||
def scaled(value, scale):
|
||||
"""A pixel measurement at the configured scale, never smaller than 1."""
|
||||
return max(1, int(round(value * scale)))
|
||||
@@ -22,6 +22,7 @@ chmod 0755 /usr/local/bin/classroom-window
|
||||
chmod 0755 /usr/local/bin/classroom-dvd
|
||||
chmod 0755 /usr/local/bin/classroom-dvd-css-setup
|
||||
chmod 0755 /usr/local/bin/classroom-notify-test
|
||||
chmod 0755 /usr/local/bin/classroom-notifications
|
||||
|
||||
# Reading the optical drive needs group cdrom. Takes effect at the next
|
||||
# login, which the OTA reboot provides.
|
||||
@@ -38,13 +39,18 @@ CHANNEL=stable
|
||||
|
||||
# Set to true on classrooms that have a DVD drive.
|
||||
DVD_ENABLED=false
|
||||
|
||||
# Size of the dock, clock and notifications, 0.8 to 1.5.
|
||||
# Larger rooms and larger TVs want a larger number.
|
||||
UI_SCALE=1.0
|
||||
CONFIG
|
||||
|
||||
chmod 0644 /etc/ekklesia-classroom/device.conf
|
||||
fi
|
||||
|
||||
# Make the DVD option discoverable on classrooms installed before it
|
||||
# existed. false is what those rooms already do, so nothing changes.
|
||||
# Make the settings discoverable on classrooms installed before they
|
||||
# existed. Both defaults are what those rooms already do, so nothing
|
||||
# about their behaviour changes.
|
||||
if ! grep -q '^DVD_ENABLED=' /etc/ekklesia-classroom/device.conf; then
|
||||
cat >> /etc/ekklesia-classroom/device.conf <<'CONFIG'
|
||||
|
||||
@@ -53,6 +59,15 @@ DVD_ENABLED=false
|
||||
CONFIG
|
||||
fi
|
||||
|
||||
if ! grep -q '^UI_SCALE=' /etc/ekklesia-classroom/device.conf; then
|
||||
cat >> /etc/ekklesia-classroom/device.conf <<'CONFIG'
|
||||
|
||||
# Size of the dock, clock and notifications, 0.8 to 1.5.
|
||||
# Larger rooms and larger TVs want a larger number.
|
||||
UI_SCALE=1.0
|
||||
CONFIG
|
||||
fi
|
||||
|
||||
systemctl daemon-reload || true
|
||||
|
||||
systemctl enable ekklesia-classroom-update.timer || true
|
||||
|
||||
+77
-48
@@ -12,53 +12,38 @@ gi.require_version("GtkLayerShell", "0.1")
|
||||
|
||||
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib, GtkLayerShell
|
||||
|
||||
sys.path.insert(0, "/usr/local/lib/ekklesia-classroom")
|
||||
|
||||
from classroom_config import ( # noqa: E402
|
||||
enabled,
|
||||
read_device_config,
|
||||
scaled,
|
||||
ui_scale,
|
||||
)
|
||||
|
||||
# Optional on purpose. The dock is the one thing the classroom cannot
|
||||
# afford to lose, so a missing DVD helper simply disables disc detection
|
||||
# instead of taking the whole shell down.
|
||||
sys.path.insert(0, "/usr/local/lib/ekklesia-classroom")
|
||||
|
||||
try:
|
||||
import classroom_optical as optical
|
||||
except ImportError:
|
||||
optical = None
|
||||
|
||||
|
||||
CONFIG_FILE = Path("/etc/ekklesia-classroom/device.conf")
|
||||
CSS_FILE = Path("/etc/ekklesia-classroom/dock/style.css")
|
||||
CSS_FILE = Path("/etc/ekklesia-classroom/dock/style.css.in")
|
||||
ICON_DIR = Path("/etc/ekklesia-classroom/icons")
|
||||
|
||||
DVD_POLL_SECONDS = 2
|
||||
|
||||
# Every measurement in the shell, at UI_SCALE=1.0. The CSS template
|
||||
# carries the same numbers; these are the ones GTK needs in Python.
|
||||
SHELL_HEIGHT = 76
|
||||
DOCK_SPACING = 10
|
||||
CLOCK_EDGE_PADDING = 20
|
||||
|
||||
def read_device_config():
|
||||
config = {}
|
||||
|
||||
if not CONFIG_FILE.exists():
|
||||
return config
|
||||
|
||||
for raw_line in CONFIG_FILE.read_text().splitlines():
|
||||
line = raw_line.strip()
|
||||
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
|
||||
key, value = line.split("=", 1)
|
||||
config[key.strip()] = value.strip()
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def enabled(config, key, default=False):
|
||||
if key not in config:
|
||||
return default
|
||||
|
||||
return config[key].lower() in {
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
"enabled",
|
||||
}
|
||||
BROWSER_ICON_SIZE = 28
|
||||
DVD_ICON_SIZE = 40
|
||||
SANCTUARY_ICON_SIZE = 38
|
||||
|
||||
|
||||
def launch(command):
|
||||
@@ -122,6 +107,7 @@ class ClassroomShell(Gtk.Window):
|
||||
self.set_resizable(False)
|
||||
|
||||
self.config = read_device_config()
|
||||
self.scale = ui_scale(self.config)
|
||||
|
||||
self.dvd_image = None
|
||||
self.disc_ready = None
|
||||
@@ -148,14 +134,16 @@ class ClassroomShell(Gtk.Window):
|
||||
True,
|
||||
)
|
||||
|
||||
GtkLayerShell.set_exclusive_zone(self, 76)
|
||||
shell_height = scaled(SHELL_HEIGHT, self.scale)
|
||||
|
||||
GtkLayerShell.set_exclusive_zone(self, shell_height)
|
||||
GtkLayerShell.set_keyboard_interactivity(
|
||||
self,
|
||||
False,
|
||||
)
|
||||
|
||||
layout = Gtk.Overlay()
|
||||
layout.set_size_request(-1, 76)
|
||||
layout.set_size_request(-1, shell_height)
|
||||
|
||||
dock = self.build_dock()
|
||||
|
||||
@@ -181,7 +169,7 @@ class ClassroomShell(Gtk.Window):
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
20,
|
||||
scaled(CLOCK_EDGE_PADDING, self.scale),
|
||||
)
|
||||
clock_align.add(self.clock)
|
||||
|
||||
@@ -199,7 +187,7 @@ class ClassroomShell(Gtk.Window):
|
||||
def build_dock(self):
|
||||
dock = Gtk.Box(
|
||||
orientation=Gtk.Orientation.HORIZONTAL,
|
||||
spacing=10,
|
||||
spacing=scaled(DOCK_SPACING, self.scale),
|
||||
)
|
||||
dock.get_style_context().add_class("dock")
|
||||
|
||||
@@ -262,9 +250,11 @@ class ClassroomShell(Gtk.Window):
|
||||
return button
|
||||
|
||||
def browser_icon(self):
|
||||
size = scaled(BROWSER_ICON_SIZE, self.scale)
|
||||
|
||||
image = custom_icon(
|
||||
"browser.svg",
|
||||
28,
|
||||
size,
|
||||
)
|
||||
|
||||
if image is not None:
|
||||
@@ -274,14 +264,16 @@ class ClassroomShell(Gtk.Window):
|
||||
"web-browser-symbolic",
|
||||
"internet-web-browser-symbolic",
|
||||
)
|
||||
image.set_pixel_size(28)
|
||||
image.set_pixel_size(size)
|
||||
|
||||
return image
|
||||
|
||||
def dvd_icon(self):
|
||||
size = scaled(DVD_ICON_SIZE, self.scale)
|
||||
|
||||
image = custom_icon(
|
||||
"dvd.svg",
|
||||
40,
|
||||
size,
|
||||
)
|
||||
|
||||
if image is not None:
|
||||
@@ -292,7 +284,7 @@ class ClassroomShell(Gtk.Window):
|
||||
"media-optical-symbolic",
|
||||
"media-optical",
|
||||
)
|
||||
image.set_pixel_size(28)
|
||||
image.set_pixel_size(size)
|
||||
|
||||
return image
|
||||
|
||||
@@ -309,9 +301,11 @@ class ClassroomShell(Gtk.Window):
|
||||
else "live-off.svg"
|
||||
)
|
||||
|
||||
size = scaled(SANCTUARY_ICON_SIZE, self.scale)
|
||||
|
||||
image = custom_icon(
|
||||
filename,
|
||||
38,
|
||||
size,
|
||||
)
|
||||
|
||||
if image is not None:
|
||||
@@ -321,7 +315,7 @@ class ClassroomShell(Gtk.Window):
|
||||
"video-display-symbolic",
|
||||
"video-display",
|
||||
)
|
||||
image.set_pixel_size(28)
|
||||
image.set_pixel_size(size)
|
||||
|
||||
return image
|
||||
|
||||
@@ -364,12 +358,47 @@ class ClassroomShell(Gtk.Window):
|
||||
return True
|
||||
|
||||
|
||||
def load_css():
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_path(
|
||||
str(CSS_FILE)
|
||||
def render_css(scale):
|
||||
"""Resolve the measurement tokens in the stylesheet template."""
|
||||
css = CSS_FILE.read_text()
|
||||
|
||||
measurements = {
|
||||
"dock-radius": 24,
|
||||
"dock-padding-v": 8,
|
||||
"dock-padding-h": 10,
|
||||
"button-radius": 16,
|
||||
"button-padding": 6,
|
||||
"button-size": 44,
|
||||
"clock-radius": 16,
|
||||
"clock-padding-v": 7,
|
||||
"clock-padding-h": 12,
|
||||
"clock-font": 17,
|
||||
}
|
||||
|
||||
for token, value in measurements.items():
|
||||
css = css.replace(
|
||||
f"@{token}@",
|
||||
str(scaled(value, scale)),
|
||||
)
|
||||
|
||||
return css
|
||||
|
||||
|
||||
def load_css(scale):
|
||||
# Styling is worth losing before the dock is. A stylesheet that will
|
||||
# not parse leaves an unstyled but working shell rather than no shell.
|
||||
try:
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_data(
|
||||
render_css(scale).encode("utf-8")
|
||||
)
|
||||
except (OSError, GLib.Error) as error:
|
||||
print(
|
||||
f"classroom-dock: stylesheet not applied: {error}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return
|
||||
|
||||
screen = Gdk.Screen.get_default()
|
||||
|
||||
Gtk.StyleContext.add_provider_for_screen(
|
||||
@@ -380,7 +409,7 @@ def load_css():
|
||||
|
||||
|
||||
def main():
|
||||
load_css()
|
||||
load_css(ui_scale(read_device_config()))
|
||||
|
||||
shell = ClassroomShell()
|
||||
shell.connect(
|
||||
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Starts mako with the classroom styling at the room's UI scale.
|
||||
|
||||
mako only reads ~/.config, and its measurements have to follow UI_SCALE,
|
||||
so the packaged template is resolved into the session's runtime directory
|
||||
and mako is pointed at the result.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, "/usr/local/lib/ekklesia-classroom")
|
||||
|
||||
from classroom_config import read_device_config, scaled, ui_scale # noqa: E402
|
||||
|
||||
MAKO = "/usr/bin/mako"
|
||||
TEMPLATE = Path("/etc/ekklesia-classroom/mako/config.in")
|
||||
|
||||
# The same measurements the template carries, at UI_SCALE=1.0.
|
||||
MEASUREMENTS = {
|
||||
"font-size": 12,
|
||||
"radius": 18,
|
||||
"padding-v": 14,
|
||||
"padding-h": 18,
|
||||
"margin": 18,
|
||||
"width": 380,
|
||||
"height": 160,
|
||||
"icon-size": 48,
|
||||
}
|
||||
|
||||
|
||||
def runtime_directory():
|
||||
base = os.environ.get("XDG_RUNTIME_DIR") or "/tmp"
|
||||
|
||||
directory = Path(base) / "ekklesia-classroom"
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
return directory
|
||||
|
||||
|
||||
def render(scale):
|
||||
config = TEMPLATE.read_text()
|
||||
|
||||
for token, value in MEASUREMENTS.items():
|
||||
config = config.replace(
|
||||
f"@{token}@",
|
||||
str(scaled(value, scale)),
|
||||
)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def main():
|
||||
scale = ui_scale(read_device_config())
|
||||
|
||||
try:
|
||||
path = runtime_directory() / "mako.config"
|
||||
path.write_text(render(scale))
|
||||
config_argument = str(path)
|
||||
except OSError as error:
|
||||
# Better plain notifications than none at all.
|
||||
print(
|
||||
f"classroom-notifications: falling back to the unscaled template: {error}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
config_argument = str(TEMPLATE)
|
||||
|
||||
os.execv(MAKO, [MAKO, "--config", config_argument])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+15
-7
@@ -113,7 +113,15 @@ install -Dm755 \
|
||||
"$ROOT/scripts/classroom-notify-test" \
|
||||
"$STAGE/usr/local/bin/classroom-notify-test"
|
||||
|
||||
# Shared helpers imported by the dock and by classroom-dvd.
|
||||
install -Dm755 \
|
||||
"$ROOT/scripts/classroom-notifications" \
|
||||
"$STAGE/usr/local/bin/classroom-notifications"
|
||||
|
||||
# Shared helpers imported by the classroom commands.
|
||||
install -Dm644 \
|
||||
"$ROOT/lib/classroom_config.py" \
|
||||
"$STAGE/usr/local/lib/ekklesia-classroom/classroom_config.py"
|
||||
|
||||
install -Dm644 \
|
||||
"$ROOT/lib/classroom_optical.py" \
|
||||
"$STAGE/usr/local/lib/ekklesia-classroom/classroom_optical.py"
|
||||
@@ -126,15 +134,15 @@ install -Dm755 \
|
||||
"$ROOT/scripts/classroom-dock" \
|
||||
"$STAGE/usr/local/bin/classroom-dock"
|
||||
|
||||
# Stylesheet and notification templates. Both carry measurement tokens
|
||||
# that are resolved from UI_SCALE when the session starts.
|
||||
install -Dm644 \
|
||||
"$ROOT/config/dock/style.css" \
|
||||
"$STAGE/etc/ekklesia-classroom/dock/style.css"
|
||||
"$ROOT/config/dock/style.css.in" \
|
||||
"$STAGE/etc/ekklesia-classroom/dock/style.css.in"
|
||||
|
||||
# Notification styling, matched to the dock. mako only searches
|
||||
# ~/.config, so sway starts it with an explicit --config path.
|
||||
install -Dm644 \
|
||||
"$ROOT/config/mako/config" \
|
||||
"$STAGE/etc/ekklesia-classroom/mako/config"
|
||||
"$ROOT/config/mako/config.in" \
|
||||
"$STAGE/etc/ekklesia-classroom/mako/config.in"
|
||||
|
||||
# Chrome enterprise policy: suppress first-run and sign-in nags, and pin
|
||||
# Home to Wonder Ink. Nothing here restricts where teachers can browse.
|
||||
|
||||
Reference in New Issue
Block a user