Remove deprecated one-shot scripts and update first-boot configuration for improved provisioning</message>
<message>Delete obsolete one-shot scripts for setting screen rotation and wallpaper, as well as related Python and shell scripts. Update the first-boot configuration to streamline the provisioning process by removing references to these scripts. This cleanup enhances maintainability and focuses on the essential steps required for the first boot experience, ensuring a more efficient setup for users.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=01 Set rotation once
|
||||
Exec=/home/pi/01-set-rotation-once.sh
|
||||
X-GNOME-Autostart-enabled=true
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
# Revision: 2
|
||||
# One-shot: set screen rotation via kanshi (same as Control Center), then remove self.
|
||||
# Reads video=DSI-1:rotate=N from kernel cmdline and writes ~/.config/kanshi/config.
|
||||
# Runs once as user pi at first login; deletes its autostart and this script so it never runs again.
|
||||
# Logs to /var/log/first-boot.log.
|
||||
FIRST_BOOT_LOG="/var/log/first-boot.log"
|
||||
BASE="$(basename "$0" .sh)"
|
||||
log() { echo "[$(date -Iseconds)] [$BASE] $*" >> "$FIRST_BOOT_LOG" 2>/dev/null || true; }
|
||||
|
||||
ROTATE="270"
|
||||
for f in /boot/firmware/cmdline.txt /boot/cmdline.txt; do
|
||||
if [[ -f "$f" ]]; then
|
||||
val=$(grep -o 'video=DSI-1:rotate=[0-9]*' "$f" 2>/dev/null | head -1)
|
||||
val="${val#*rotate=}"
|
||||
if [[ "$val" =~ ^(90|180|270)$ ]]; then ROTATE="$val"; break; fi
|
||||
fi
|
||||
done
|
||||
log "writing kanshi config with transform $ROTATE (from cmdline)"
|
||||
|
||||
KANSHI_DIR="$HOME/.config/kanshi"
|
||||
KANSHI_CONFIG="$KANSHI_DIR/config"
|
||||
mkdir -p "$KANSHI_DIR"
|
||||
cat > "$KANSHI_CONFIG" << EOF
|
||||
profile {
|
||||
output DSI-1 enable scale 1.000000 mode 800x1280@60.000 position 0,0 transform $ROTATE
|
||||
}
|
||||
EOF
|
||||
log "kanshi config written to $KANSHI_CONFIG"
|
||||
|
||||
# Set GTK dark theme (same as first-boot step 08) and force dark mode via gsettings
|
||||
GTK_THEME_NAME="PiXnoir"
|
||||
[[ -d /usr/share/themes/Adwaita-dark ]] && ! [[ -d /usr/share/themes/PiXnoir ]] && GTK_THEME_NAME="Adwaita-dark"
|
||||
GTK_SETTINGS="$HOME/.config/gtk-3.0/settings.ini"
|
||||
mkdir -p "$(dirname "$GTK_SETTINGS")"
|
||||
if [[ ! -f "$GTK_SETTINGS" ]]; then
|
||||
printf '%s\n' '[Settings]' 'gtk-application-prefer-dark-theme=1' "gtk-theme-name=$GTK_THEME_NAME" > "$GTK_SETTINGS"
|
||||
else
|
||||
grep -q '^gtk-application-prefer-dark-theme=' "$GTK_SETTINGS" && sed -i 's/^gtk-application-prefer-dark-theme=.*/gtk-application-prefer-dark-theme=1/' "$GTK_SETTINGS" || echo 'gtk-application-prefer-dark-theme=1' >> "$GTK_SETTINGS"
|
||||
grep -q '^gtk-theme-name=' "$GTK_SETTINGS" && sed -i "s/^gtk-theme-name=.*/gtk-theme-name=$GTK_THEME_NAME/" "$GTK_SETTINGS" || echo "gtk-theme-name=$GTK_THEME_NAME" >> "$GTK_SETTINGS"
|
||||
fi
|
||||
if [[ -d /usr/share/icons/PiXtrix ]]; then
|
||||
grep -q '^gtk-icon-theme-name=' "$GTK_SETTINGS" && sed -i 's/^gtk-icon-theme-name=.*/gtk-icon-theme-name=PiXtrix/' "$GTK_SETTINGS" || echo 'gtk-icon-theme-name=PiXtrix' >> "$GTK_SETTINGS"
|
||||
fi
|
||||
if command -v gsettings >/dev/null 2>&1; then
|
||||
gsettings set org.gnome.desktop.interface gtk-theme "$GTK_THEME_NAME" 2>/dev/null || true
|
||||
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' 2>/dev/null || true
|
||||
fi
|
||||
log "Set dark theme ($GTK_THEME_NAME) in gtk-3.0/settings.ini"
|
||||
|
||||
log "removing one-shot desktop and script"
|
||||
rm -f "$HOME/.config/autostart/${BASE}.desktop" "$HOME/${BASE}.sh"
|
||||
log "finished"
|
||||
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=02 Set wallpaper once
|
||||
Exec=/home/pi/02-set-wallpaper-once.sh
|
||||
X-GNOME-Autostart-enabled=true
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
# Revision: 2
|
||||
# One-shot: set desktop wallpaper for labwc (swaybg) and persist via labwc autostart, then remove self.
|
||||
# Runs as user pi at first login. Logs to /var/log/first-boot.log.
|
||||
FIRST_BOOT_LOG="/var/log/first-boot.log"
|
||||
BASE="$(basename "$0" .sh)"
|
||||
log() { echo "[$(date -Iseconds)] [$BASE] $*" >> "$FIRST_BOOT_LOG" 2>/dev/null || true; }
|
||||
|
||||
WALLPAPER="/usr/share/rpd-wallpaper/splash.png"
|
||||
LABWC_AUTOSTART="$HOME/.config/labwc/autostart"
|
||||
|
||||
log "started (labwc/swaybg)"
|
||||
log "waiting 8s for compositor ..."
|
||||
sleep 8
|
||||
|
||||
if [[ ! -f "$WALLPAPER" ]]; then
|
||||
log "WARNING: wallpaper not found $WALLPAPER"
|
||||
else
|
||||
mkdir -p "$(dirname "$LABWC_AUTOSTART")"
|
||||
if [[ ! -f "$LABWC_AUTOSTART" ]]; then
|
||||
echo '#!/bin/sh' > "$LABWC_AUTOSTART"
|
||||
chmod +x "$LABWC_AUTOSTART"
|
||||
fi
|
||||
if ! grep -q 'swaybg.*splash.png' "$LABWC_AUTOSTART" 2>/dev/null; then
|
||||
echo "swaybg -i $WALLPAPER -m fill &" >> "$LABWC_AUTOSTART"
|
||||
log "added swaybg to labwc autostart"
|
||||
fi
|
||||
if command -v swaybg &>/dev/null; then
|
||||
log "applying wallpaper now: $WALLPAPER"
|
||||
swaybg -i "$WALLPAPER" -m fill &
|
||||
else
|
||||
log "WARNING: swaybg not installed"
|
||||
fi
|
||||
fi
|
||||
|
||||
log "removing one-shot desktop and script"
|
||||
rm -f "$HOME/.config/autostart/${BASE}.desktop" "$HOME/${BASE}.sh"
|
||||
log "finished"
|
||||
@@ -0,0 +1,3 @@
|
||||
[Seat:*]
|
||||
user-session=rpd-labwc
|
||||
autologin-session=rpd-labwc
|
||||
@@ -0,0 +1,3 @@
|
||||
[greeter]
|
||||
wallpaper=/usr/share/rpd-wallpaper/splash.png
|
||||
wallpaper_mode=crop
|
||||
35
emmc-provisioning/cloud-init/fileserver/README.md
Normal file
35
emmc-provisioning/cloud-init/fileserver/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# fileserver/
|
||||
|
||||
All files in this directory are synced to the portal's file server and served
|
||||
at `http://<portal>:5000/files/first-boot/`. The `first-boot.sh` script
|
||||
downloads them during provisioning via the `FILE_SERVER` variable.
|
||||
|
||||
Sync to the LXC with:
|
||||
|
||||
```bash
|
||||
../scripts/sync-portal-files-to-lxc.sh root@<lxc-ip>
|
||||
```
|
||||
|
||||
## Layout
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `steps/01-hostname.sh` … `steps/13-reboot.sh` | Step scripts sourced by `first-boot.sh` |
|
||||
| `start-chromium.sh` | Chromium kiosk launcher |
|
||||
| `five-tap-close-chromium.py` | 5-tap overlay to close Chromium |
|
||||
| `chromium-kiosk.desktop` | Autostart for Chromium kiosk |
|
||||
| `chromium-kiosk-launcher.desktop` | Desktop icon to restart Chromium |
|
||||
| `five-tap-close-chromium.desktop` | Autostart for the 5-tap overlay |
|
||||
| `set-rotation-at-login.sh` / `.desktop` | Per-login kanshi rotation from cmdline |
|
||||
| `01-set-rotation-once.sh` / `.desktop` | One-shot: first-login rotation + dark theme |
|
||||
| `02-set-wallpaper-once.sh` / `.desktop` | One-shot: wallpaper via swaybg |
|
||||
| `fix-reterminal-display.sh` | Utility: re-apply DSI driver fix |
|
||||
| `99-default-session.conf` | LightDM → rpd-labwc session |
|
||||
| `99-wallpaper.conf` | LightDM greeter wallpaper |
|
||||
| `maliit-keyboard.desktop` | Maliit on-screen keyboard autostart |
|
||||
| `gtk.css` | GTK3 CSS override (dark menus/popovers) |
|
||||
| `wf-panel-pi.ini` | Dark taskbar config |
|
||||
| `panel-theme.css` | Dark taskbar CSS |
|
||||
| `custom.plymouth` / `custom.script` | Plymouth boot splash theme |
|
||||
| `splash.png` | Boot splash + wallpaper image (binary) |
|
||||
| `start-here.png` | Taskbar start button icon (binary, optional) |
|
||||
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Start Chromium Kiosk
|
||||
Comment=Start Chromium in kiosk mode (use if the browser was closed)
|
||||
Exec=/home/pi/start-chromium.sh
|
||||
Icon=chromium-browser
|
||||
Terminal=false
|
||||
Categories=Utility;Kiosk;
|
||||
StartupNotify=false
|
||||
@@ -0,0 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Chromium Fullscreen
|
||||
Exec=/home/pi/start-chromium.sh
|
||||
Hidden=false
|
||||
NoDisplay=false
|
||||
X-GNOME-Autostart-enabled=true
|
||||
8
emmc-provisioning/cloud-init/fileserver/custom.plymouth
Normal file
8
emmc-provisioning/cloud-init/fileserver/custom.plymouth
Normal file
@@ -0,0 +1,8 @@
|
||||
[Plymouth Theme]
|
||||
Name=Custom Splash
|
||||
Description=Custom boot splash screen
|
||||
ModuleName=script
|
||||
|
||||
[script]
|
||||
ImageDir=/usr/share/plymouth/themes/custom
|
||||
ScriptFile=/usr/share/plymouth/themes/custom/custom.script
|
||||
40
emmc-provisioning/cloud-init/fileserver/custom.script
Normal file
40
emmc-provisioning/cloud-init/fileserver/custom.script
Normal file
@@ -0,0 +1,40 @@
|
||||
screen_width = Window.GetWidth();
|
||||
screen_height = Window.GetHeight();
|
||||
|
||||
theme_image = Image("splash.png");
|
||||
image_width = theme_image.GetWidth();
|
||||
image_height = theme_image.GetHeight();
|
||||
|
||||
scale_x = image_width / screen_width;
|
||||
scale_y = image_height / screen_height;
|
||||
|
||||
if (scale_x > 1 || scale_y > 1)
|
||||
{
|
||||
if (scale_x > scale_y)
|
||||
{
|
||||
resized_image = theme_image.Scale(screen_width, image_height / scale_x);
|
||||
image_x = 0;
|
||||
image_y = (screen_height - ((image_height * screen_width) / image_width)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
resized_image = theme_image.Scale(image_width / scale_y, screen_height);
|
||||
image_x = (screen_width - ((image_width * screen_height) / image_height)) / 2;
|
||||
image_y = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resized_image = theme_image.Scale(image_width, image_height);
|
||||
image_x = (screen_width - image_width) / 2;
|
||||
image_y = (screen_height - image_height) / 2;
|
||||
}
|
||||
|
||||
if (Plymouth.GetMode() != "shutdown")
|
||||
{
|
||||
sprite = Sprite(resized_image);
|
||||
sprite.SetPosition(image_x, image_y, -100);
|
||||
}
|
||||
|
||||
fun message_callback(text) {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Five-tap close Chromium
|
||||
Comment=5 taps in top-right corner close Chromium kiosk (hidden at startup)
|
||||
Exec=/home/pi/five-tap-close-chromium.py
|
||||
Hidden=false
|
||||
NoDisplay=true
|
||||
X-GNOME-Autostart-enabled=true
|
||||
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python3
|
||||
# 5 taps in the top-right corner of the screen close Chromium (kiosk).
|
||||
# Run from session autostart. Requires: python3, PyGObject (Gtk), Wayland or X11.
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
LOG_TAG = "five-tap"
|
||||
logging.basicConfig(
|
||||
stream=sys.stderr,
|
||||
level=logging.DEBUG,
|
||||
format=f"{LOG_TAG}: %(message)s",
|
||||
)
|
||||
log = logging.getLogger(LOG_TAG)
|
||||
|
||||
try:
|
||||
import gi
|
||||
gi.require_version("Gdk", "3.0")
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gdk, Gtk, GLib
|
||||
except Exception as e:
|
||||
log.error("need PyGObject Gtk: %s", e)
|
||||
sys.exit(1)
|
||||
|
||||
CORNER_SIZE = 80
|
||||
TAP_WINDOW_SEC = 2.0
|
||||
CHROMIUM_KILL_CMD = ["pkill", "-f", "chromium"]
|
||||
|
||||
|
||||
def get_screen_size():
|
||||
display = Gdk.Display.get_default()
|
||||
if not display:
|
||||
log.warning("no display found, using fallback 800x1280")
|
||||
return 800, 1280
|
||||
monitor = display.get_monitor(0) if display.get_n_monitors() else None
|
||||
if monitor:
|
||||
geom = monitor.get_geometry()
|
||||
log.info("screen size: %dx%d", geom.width, geom.height)
|
||||
return geom.width, geom.height
|
||||
log.warning("no monitor found, using fallback 800x1280")
|
||||
return 800, 1280
|
||||
|
||||
|
||||
def on_button_press(widget, event, data):
|
||||
count, reset_timer = data
|
||||
count[0] += 1
|
||||
log.debug("tap %d of 5 at (%.0f, %.0f)", count[0], event.x_root, event.y_root)
|
||||
if reset_timer[0]:
|
||||
GLib.source_remove(reset_timer[0])
|
||||
if count[0] >= 5:
|
||||
count[0] = 0
|
||||
log.info("5 taps reached — killing chromium")
|
||||
try:
|
||||
result = subprocess.run(CHROMIUM_KILL_CMD, timeout=2, capture_output=True)
|
||||
log.info("pkill returncode=%d", result.returncode)
|
||||
except Exception as e:
|
||||
log.error("pkill failed: %s", e)
|
||||
if reset_timer[0]:
|
||||
GLib.source_remove(reset_timer[0])
|
||||
reset_timer[0] = None
|
||||
return
|
||||
def reset():
|
||||
log.debug("tap count reset (%.1fs timeout)", TAP_WINDOW_SEC)
|
||||
count[0] = 0
|
||||
reset_timer[0] = None
|
||||
return False
|
||||
reset_timer[0] = GLib.timeout_add(int(TAP_WINDOW_SEC * 1000), reset)
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
win = Gtk.Window()
|
||||
win.set_decorated(False)
|
||||
win.set_resizable(False)
|
||||
win.set_default_size(CORNER_SIZE, CORNER_SIZE)
|
||||
win.set_skip_taskbar_hint(True)
|
||||
win.set_skip_pager_hint(True)
|
||||
win.set_keep_above(True)
|
||||
win.set_opacity(0.01)
|
||||
win.set_accept_focus(False)
|
||||
win.set_focus_on_map(False)
|
||||
# Allow closing from compositor / taskbar
|
||||
win.connect("destroy", Gtk.main_quit)
|
||||
# Count 5 taps
|
||||
count = [0]
|
||||
reset_timer = [None]
|
||||
win.connect("button-press-event", on_button_press, (count, reset_timer))
|
||||
# Touch events often come as button-press with button=1
|
||||
win.set_events(
|
||||
win.get_events()
|
||||
| Gdk.EventMask.BUTTON_PRESS_MASK
|
||||
| Gdk.EventMask.TOUCH_MASK
|
||||
)
|
||||
win.realize()
|
||||
w, h = get_screen_size()
|
||||
x = max(0, w - CORNER_SIZE)
|
||||
win.move(x, 0)
|
||||
log.info("window %dx%d positioned at x=%d y=0", CORNER_SIZE, CORNER_SIZE, x)
|
||||
win.show_all()
|
||||
log.info("listening for taps (5 within %.1fs to kill chromium)", TAP_WINDOW_SEC)
|
||||
Gtk.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
49
emmc-provisioning/cloud-init/fileserver/gtk.css
Normal file
49
emmc-provisioning/cloud-init/fileserver/gtk.css
Normal file
@@ -0,0 +1,49 @@
|
||||
/* User GTK3 override: force start menu and all menus/popovers to full dark.
|
||||
* Colors match Adwaita-dark (menu/popover #2d2d2d, text #e0e0e0).
|
||||
* Placed in ~/.config/gtk-3.0/gtk.css.
|
||||
*/
|
||||
|
||||
/* Adwaita-dark menu/popover background */
|
||||
menu,
|
||||
.menu,
|
||||
menubar,
|
||||
.menubar,
|
||||
popover,
|
||||
.popover,
|
||||
popover.menu {
|
||||
background-color: #2d2d2d !important;
|
||||
background: #2d2d2d !important;
|
||||
color: #e0e0e0 !important;
|
||||
}
|
||||
|
||||
/* Inner content (often the cause of light background) */
|
||||
menu contents,
|
||||
.menu contents,
|
||||
popover contents,
|
||||
popover list,
|
||||
popover flowbox,
|
||||
popover box {
|
||||
background-color: #2d2d2d !important;
|
||||
background: #2d2d2d !important;
|
||||
color: #e0e0e0 !important;
|
||||
}
|
||||
|
||||
menu menuitem,
|
||||
.menu menuitem,
|
||||
menubar menuitem,
|
||||
popover modelbutton,
|
||||
popover menuitem {
|
||||
background-color: transparent !important;
|
||||
background: transparent !important;
|
||||
color: #e0e0e0 !important;
|
||||
}
|
||||
|
||||
menu menuitem:hover,
|
||||
.menu menuitem:hover,
|
||||
menubar menuitem:hover,
|
||||
popover modelbutton:hover,
|
||||
popover menuitem:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1) !important;
|
||||
background: rgba(255, 255, 255, 0.1) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Maliit Keyboard
|
||||
Exec=maliit-keyboard -r
|
||||
X-GNOME-Autostart-enabled=true
|
||||
42
emmc-provisioning/cloud-init/fileserver/panel-theme.css
Normal file
42
emmc-provisioning/cloud-init/fileserver/panel-theme.css
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Minimal dark taskbar – flat, touch-friendly
|
||||
* Colors match Adwaita-dark (window bg #242424) so taskbar fits dark mode.
|
||||
* Icon theme PiXtrix (start-here) set in gtk-3.0/settings.ini.
|
||||
*/
|
||||
|
||||
window {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* Flat bar: Adwaita-dark window bg so theme is consistent */
|
||||
window box {
|
||||
background-color: #242424;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
padding: 4px 8px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Touch-friendly buttons: min 32px, clear hit area */
|
||||
button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
button:active {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
label {
|
||||
color: #e0e0e0;
|
||||
font-size: 11pt;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Set rotation at login
|
||||
Exec=/home/pi/set-rotation-at-login.sh
|
||||
X-GNOME-Autostart-enabled=true
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
# Revision: 2
|
||||
# Set screen rotation via kanshi (same as Control Center). Reads video=DSI-1:rotate=N
|
||||
# from kernel cmdline and writes ~/.config/kanshi/config. Kanshi auto-reloads when the file changes.
|
||||
# Also sets GTK dark theme (PiXnoir / Adwaita-dark). Runs from autostart when user pi logs in; does not remove itself.
|
||||
ROTATE="270"
|
||||
for f in /boot/firmware/cmdline.txt /boot/cmdline.txt; do
|
||||
[[ -f "$f" ]] || continue
|
||||
val=$(grep -o 'video=DSI-1:rotate=[0-9]*' "$f" 2>/dev/null | head -1)
|
||||
val="${val#*rotate=}"
|
||||
[[ "$val" =~ ^(90|180|270)$ ]] && ROTATE="$val" && break
|
||||
done
|
||||
KANSHI_DIR="$HOME/.config/kanshi"
|
||||
KANSHI_CONFIG="$KANSHI_DIR/config"
|
||||
mkdir -p "$KANSHI_DIR"
|
||||
cat > "$KANSHI_CONFIG" << EOF
|
||||
profile {
|
||||
output DSI-1 enable scale 1.000000 mode 800x1280@60.000 position 0,0 transform $ROTATE
|
||||
}
|
||||
EOF
|
||||
|
||||
# Set GTK dark theme (same as first-boot step 08) and force dark mode via gsettings
|
||||
GTK_THEME_NAME="PiXnoir"
|
||||
[[ -d /usr/share/themes/Adwaita-dark ]] && ! [[ -d /usr/share/themes/PiXnoir ]] && GTK_THEME_NAME="Adwaita-dark"
|
||||
GTK_SETTINGS="$HOME/.config/gtk-3.0/settings.ini"
|
||||
mkdir -p "$(dirname "$GTK_SETTINGS")"
|
||||
if [[ ! -f "$GTK_SETTINGS" ]]; then
|
||||
printf '%s\n' '[Settings]' 'gtk-application-prefer-dark-theme=1' "gtk-theme-name=$GTK_THEME_NAME" > "$GTK_SETTINGS"
|
||||
else
|
||||
grep -q '^gtk-application-prefer-dark-theme=' "$GTK_SETTINGS" && sed -i 's/^gtk-application-prefer-dark-theme=.*/gtk-application-prefer-dark-theme=1/' "$GTK_SETTINGS" || echo 'gtk-application-prefer-dark-theme=1' >> "$GTK_SETTINGS"
|
||||
grep -q '^gtk-theme-name=' "$GTK_SETTINGS" && sed -i "s/^gtk-theme-name=.*/gtk-theme-name=$GTK_THEME_NAME/" "$GTK_SETTINGS" || echo "gtk-theme-name=$GTK_THEME_NAME" >> "$GTK_SETTINGS"
|
||||
fi
|
||||
# Force dark mode system-wide (GNOME/GTK apps that read gsettings)
|
||||
if command -v gsettings >/dev/null 2>&1; then
|
||||
gsettings set org.gnome.desktop.interface gtk-theme "$GTK_THEME_NAME" 2>/dev/null || true
|
||||
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' 2>/dev/null || true
|
||||
fi
|
||||
# Preserve icon theme (PiXtrix = custom start-here)
|
||||
if [[ -d /usr/share/icons/PiXtrix ]]; then
|
||||
grep -q '^gtk-icon-theme-name=' "$GTK_SETTINGS" && sed -i 's/^gtk-icon-theme-name=.*/gtk-icon-theme-name=PiXtrix/' "$GTK_SETTINGS" || echo 'gtk-icon-theme-name=PiXtrix' >> "$GTK_SETTINGS"
|
||||
fi
|
||||
BIN
emmc-provisioning/cloud-init/fileserver/splash.png
Normal file
BIN
emmc-provisioning/cloud-init/fileserver/splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 205 KiB |
43
emmc-provisioning/cloud-init/fileserver/start-chromium.sh
Executable file
43
emmc-provisioning/cloud-init/fileserver/start-chromium.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
# Revision: 2
|
||||
# Start Chromium in app mode. Optional env vars:
|
||||
# CHROMIUM_APP_URL - URL to open (default: http://127.0.0.1:8080)
|
||||
# CHROMIUM_MODE - "kiosk" (default, fills whole screen) or "fullscreen"
|
||||
#
|
||||
# Touch long-press → right-click: In Chromium on Wayland, long-press often does *not*
|
||||
# open the context menu (Chromium handles touch itself). Elsewhere (e.g. desktop) it may
|
||||
# work. For long-press right-click *inside* Chromium, use evdev-right-click-emulation
|
||||
# at the input layer so all apps (including Chromium) receive real right-click events:
|
||||
# https://github.com/PeterCxy/evdev-right-click-emulation
|
||||
#
|
||||
# Disable keyring prompts
|
||||
export GNOME_KEYRING_CONTROL=""
|
||||
|
||||
# Wayland + labwc compositor.
|
||||
export GDK_BACKEND=wayland
|
||||
# Wait for compositor
|
||||
for i in {1..60}; do
|
||||
if [ -S "${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/$WAYLAND_DISPLAY" ]; then
|
||||
pgrep -x labwc >/dev/null 2>&1 && break
|
||||
fi
|
||||
sleep 0.5
|
||||
done
|
||||
# URL to open in Chromium (app mode)
|
||||
#CHROMIUM_APP_URL="${CHROMIUM_APP_URL:-http://127.0.0.1:8080}"
|
||||
CHROMIUM_APP_URL="${CHROMIUM_APP_URL:-https://tototheo.com}"
|
||||
|
||||
# Mode: "kiosk" (fills whole screen, no taskbar gap) or "fullscreen"
|
||||
CHROMIUM_MODE="${CHROMIUM_MODE:-kiosk}"
|
||||
|
||||
CHROMIUM_OPTS="--noerrdialogs --disable-infobars --disable-session-crashed-bubble --disable-restore-session-state --no-first-run --password-store=basic --use-mock-keychain --ozone-platform=wayland --enable-features=WaylandWindowDecorations --disable-features=UseChromeOSDirectVideoDecoder --app=${CHROMIUM_APP_URL}"
|
||||
|
||||
case "${CHROMIUM_MODE}" in
|
||||
kiosk) CHROMIUM_OPTS="--kiosk ${CHROMIUM_OPTS}" ;;
|
||||
*) CHROMIUM_OPTS="--start-fullscreen ${CHROMIUM_OPTS}" ;;
|
||||
esac
|
||||
|
||||
sleep 3
|
||||
/usr/bin/chromium $CHROMIUM_OPTS &
|
||||
|
||||
# Keep script running
|
||||
wait
|
||||
BIN
emmc-provisioning/cloud-init/fileserver/start-here.png
Normal file
BIN
emmc-provisioning/cloud-init/fileserver/start-here.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
12
emmc-provisioning/cloud-init/fileserver/steps/01-hostname.sh
Normal file
12
emmc-provisioning/cloud-init/fileserver/steps/01-hostname.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
# Step 01: Set hostname and /etc/hosts
|
||||
|
||||
step_01_hostname() {
|
||||
echo "$HOSTNAME" > /etc/hostname
|
||||
hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || true
|
||||
if ! grep -q "127.0.1.1[[:space:]]*$HOSTNAME" /etc/hosts 2>/dev/null; then
|
||||
sed -i "/127.0.1.1[[:space:]].*$/d" /etc/hosts
|
||||
echo "127.0.1.1 $HOSTNAME" >> /etc/hosts
|
||||
fi
|
||||
log "Hostname set to $HOSTNAME"
|
||||
}
|
||||
10
emmc-provisioning/cloud-init/fileserver/steps/02-packages.sh
Normal file
10
emmc-provisioning/cloud-init/fileserver/steps/02-packages.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# Step 02: Install packages
|
||||
|
||||
step_02_packages() {
|
||||
log "Running apt-get update ..."
|
||||
apt-get update -qq
|
||||
log "Installing: $PACKAGES"
|
||||
apt-get install -y -qq $PACKAGES
|
||||
log "Packages installed"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Step 03: Install reTerminal DM drivers (Seeed device-tree overlays)
|
||||
|
||||
step_03_reterminal_drivers() {
|
||||
if [[ -z "$RETERMINAL_REPO_URL" ]]; then
|
||||
log "Skipping reTerminal drivers (RETERMINAL_REPO_URL not set)"
|
||||
return 0
|
||||
fi
|
||||
local repo="/tmp/seeed-linux-dtoverlays"
|
||||
log "Cloning seeed-linux-dtoverlays ..."
|
||||
git clone --depth 1 "$RETERMINAL_REPO_URL" "$repo"
|
||||
log "Running reTerminal.sh --device $RETERMINAL_DEVICE ..."
|
||||
if ( cd "$repo" && "$repo/scripts/reTerminal.sh" --device "$RETERMINAL_DEVICE" ); then
|
||||
log "reTerminal DM drivers installed (reboot will apply)"
|
||||
else
|
||||
log "WARNING: reTerminal.sh failed; display/touch may still work"
|
||||
fi
|
||||
rm -rf "$repo"
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Step 04: Download kiosk scripts and launcher files from file server
|
||||
|
||||
step_04_kiosk_files() {
|
||||
mkdir -p "$AUTOSTART" "$PI_HOME/Desktop" "$PI_HOME/.local/share/applications"
|
||||
|
||||
curl -fsSL "${FILE_SERVER}/start-chromium.sh" -o "$PI_HOME/start-chromium.sh"
|
||||
curl -fsSL "${FILE_SERVER}/chromium-kiosk.desktop" -o "$AUTOSTART/chromium-kiosk.desktop"
|
||||
chmod 755 "$PI_HOME/start-chromium.sh"
|
||||
chmod 644 "$AUTOSTART/chromium-kiosk.desktop"
|
||||
chown "$PI_USER:$PI_USER" "$PI_HOME/start-chromium.sh" "$AUTOSTART/chromium-kiosk.desktop"
|
||||
|
||||
# Desktop launcher icon
|
||||
if curl -fsSL "${FILE_SERVER}/chromium-kiosk-launcher.desktop" -o /tmp/chromium-kiosk-launcher.desktop 2>/dev/null; then
|
||||
sed "s|/home/pi|$PI_HOME|g" /tmp/chromium-kiosk-launcher.desktop > "$PI_HOME/Desktop/Chromium Kiosk.desktop"
|
||||
sed "s|/home/pi|$PI_HOME|g" /tmp/chromium-kiosk-launcher.desktop > "$PI_HOME/.local/share/applications/chromium-kiosk-launcher.desktop"
|
||||
chmod 755 "$PI_HOME/Desktop/Chromium Kiosk.desktop"
|
||||
chmod 644 "$PI_HOME/.local/share/applications/chromium-kiosk-launcher.desktop"
|
||||
chown "$PI_USER:$PI_USER" "$PI_HOME/Desktop/Chromium Kiosk.desktop" "$PI_HOME/.local/share/applications/chromium-kiosk-launcher.desktop"
|
||||
rm -f /tmp/chromium-kiosk-launcher.desktop
|
||||
log "Chromium kiosk launcher installed"
|
||||
fi
|
||||
|
||||
# 5-tap close Chromium overlay
|
||||
if curl -fsSL "${FILE_SERVER}/five-tap-close-chromium.py" -o "$PI_HOME/five-tap-close-chromium.py" 2>/dev/null; then
|
||||
chmod 755 "$PI_HOME/five-tap-close-chromium.py"
|
||||
if curl -fsSL "${FILE_SERVER}/five-tap-close-chromium.desktop" -o "$AUTOSTART/five-tap-close-chromium.desktop" 2>/dev/null; then
|
||||
sed -i "s|/home/pi|$PI_HOME|g" "$AUTOSTART/five-tap-close-chromium.desktop"
|
||||
chmod 644 "$AUTOSTART/five-tap-close-chromium.desktop"
|
||||
chown "$PI_USER:$PI_USER" "$PI_HOME/five-tap-close-chromium.py" "$AUTOSTART/five-tap-close-chromium.desktop"
|
||||
log "5-tap close Chromium installed"
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Kiosk files installed"
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# Step 05: Boot splash (Plymouth) and desktop wallpaper
|
||||
|
||||
step_05_splash_wallpaper() {
|
||||
mkdir -p "$PLYMOUTH_DIR" /usr/share/rpd-wallpaper
|
||||
|
||||
if ! curl -fsSL "${FILE_SERVER}/splash.png" -o "$PLYMOUTH_DIR/splash.png"; then
|
||||
log "WARNING: Could not download splash.png"; return 0
|
||||
fi
|
||||
cp "$PLYMOUTH_DIR/splash.png" "$WALLPAPER_PATH"
|
||||
chmod 644 "$PLYMOUTH_DIR/splash.png" "$WALLPAPER_PATH"
|
||||
|
||||
# Plymouth theme
|
||||
if curl -fsSL "${FILE_SERVER}/custom.plymouth" -o "$PLYMOUTH_DIR/custom.plymouth" \
|
||||
&& curl -fsSL "${FILE_SERVER}/custom.script" -o "$PLYMOUTH_DIR/custom.script"; then
|
||||
chmod 644 "$PLYMOUTH_DIR/custom.plymouth" "$PLYMOUTH_DIR/custom.script"
|
||||
log "Plymouth theme installed"
|
||||
fi
|
||||
grep -q '^Theme=custom' /etc/plymouth/plymouthd.conf 2>/dev/null \
|
||||
|| printf '%s\n' '[Daemon]' 'Theme=custom' >> /etc/plymouth/plymouthd.conf
|
||||
log "Running update-initramfs ..."
|
||||
update-initramfs -u -k all 2>/dev/null || true
|
||||
|
||||
# LightDM wallpaper
|
||||
mkdir -p /etc/lightdm/lightdm.conf.d
|
||||
curl -fsSL "${FILE_SERVER}/99-wallpaper.conf" -o /etc/lightdm/lightdm.conf.d/99-wallpaper.conf 2>/dev/null || true
|
||||
|
||||
# Desktop wallpaper (pcmanfm)
|
||||
for PROFILE in LXDE-pi default; do
|
||||
local conf="$PI_HOME/.config/pcmanfm/$PROFILE/desktop-items-0.conf"
|
||||
mkdir -p "$(dirname "$conf")"
|
||||
if [[ ! -f "$conf" ]]; then
|
||||
printf '%s\n' '[*]' "wallpaper=$WALLPAPER_PATH" "wallpaper_mode=$WALLPAPER_MODE" 'wallpaper_common=1' 'show_trash=0' > "$conf"
|
||||
else
|
||||
grep -q '^wallpaper=' "$conf" && sed -i "s|^wallpaper=.*|wallpaper=$WALLPAPER_PATH|" "$conf" || echo "wallpaper=$WALLPAPER_PATH" >> "$conf"
|
||||
grep -q '^wallpaper_mode=' "$conf" && sed -i "s/^wallpaper_mode=.*/wallpaper_mode=$WALLPAPER_MODE/" "$conf" || echo "wallpaper_mode=$WALLPAPER_MODE" >> "$conf"
|
||||
grep -q '^show_trash=' "$conf" && sed -i 's/^show_trash=.*/show_trash=0/' "$conf" || echo 'show_trash=0' >> "$conf"
|
||||
fi
|
||||
chown -R "$PI_USER:$PI_USER" "$(dirname "$conf")"
|
||||
done
|
||||
|
||||
# Taskbar start-here icon
|
||||
if curl -fsSL "${FILE_SERVER}/start-here.png" -o /tmp/start-here.png 2>/dev/null; then
|
||||
local icons="/usr/share/icons/PiXtrix"
|
||||
if [[ -d "$icons/32x32/places" ]]; then
|
||||
for s in 16 24 32 48 64 96; do
|
||||
local dest="$icons/${s}x${s}/places/start-here.png"
|
||||
[[ -d "$(dirname "$dest")" ]] || continue
|
||||
rm -f "$dest"
|
||||
if command -v convert >/dev/null 2>&1; then
|
||||
convert /tmp/start-here.png -resize "${s}x${s}" "$dest" 2>/dev/null || cp /tmp/start-here.png "$dest"
|
||||
else
|
||||
cp /tmp/start-here.png "$dest"
|
||||
fi
|
||||
chmod 644 "$dest"
|
||||
done
|
||||
log "Taskbar start-here icon installed"
|
||||
fi
|
||||
rm -f /tmp/start-here.png
|
||||
fi
|
||||
|
||||
log "Splash and wallpaper configured"
|
||||
}
|
||||
39
emmc-provisioning/cloud-init/fileserver/steps/06-lightdm.sh
Normal file
39
emmc-provisioning/cloud-init/fileserver/steps/06-lightdm.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
# Step 06: LightDM session config + DSI panel wait service
|
||||
|
||||
step_06_lightdm() {
|
||||
mkdir -p /etc/lightdm/lightdm.conf.d
|
||||
|
||||
curl -fsSL "${FILE_SERVER}/99-default-session.conf" \
|
||||
-o /etc/lightdm/lightdm.conf.d/99-default-session.conf 2>/dev/null || true
|
||||
|
||||
if [[ -f /etc/lightdm/lightdm.conf ]]; then
|
||||
sed -i "s/^user-session=.*/user-session=$LIGHTDM_SESSION/" /etc/lightdm/lightdm.conf
|
||||
sed -i "s/^autologin-session=.*/autologin-session=$LIGHTDM_SESSION/" /etc/lightdm/lightdm.conf
|
||||
log "LightDM session set to $LIGHTDM_SESSION"
|
||||
fi
|
||||
|
||||
# Wait for DSI panel to report "connected" before LightDM starts (max 30s)
|
||||
mkdir -p /etc/systemd/system/lightdm.service.d
|
||||
cat > /etc/systemd/system/cm4-await-display.service << 'AWAITSVC'
|
||||
[Unit]
|
||||
Description=Wait for reTerminal DM DSI panel before LightDM
|
||||
Before=lightdm.service
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/bin/sh -c 'echo "Waiting for DSI panel..."; for i in $(seq 1 30); do for f in /sys/class/drm/card*-DSI-1/status; do [ -f "$f" ] && [ "$(cat "$f" 2>/dev/null)" = "connected" ] && echo "DSI connected." && exit 0; done; sleep 1; done; echo "DSI timeout (30s), starting anyway."'
|
||||
TimeoutStartSec=35
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical.target
|
||||
AWAITSVC
|
||||
|
||||
printf '%s\n' '[Unit]' 'After=cm4-await-display.service' \
|
||||
> /etc/systemd/system/lightdm.service.d/99-await-display.conf
|
||||
systemctl daemon-reload
|
||||
systemctl enable cm4-await-display.service 2>/dev/null || true
|
||||
log "cm4-await-display.service installed (wait for DSI, max 30s)"
|
||||
}
|
||||
10
emmc-provisioning/cloud-init/fileserver/steps/07-maliit.sh
Normal file
10
emmc-provisioning/cloud-init/fileserver/steps/07-maliit.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# Step 07: Maliit on-screen keyboard autostart
|
||||
|
||||
step_07_maliit() {
|
||||
mkdir -p "$AUTOSTART"
|
||||
curl -fsSL "${FILE_SERVER}/maliit-keyboard.desktop" \
|
||||
-o "$AUTOSTART/maliit-keyboard.desktop" 2>/dev/null \
|
||||
&& log "maliit-keyboard.desktop installed" \
|
||||
|| log "WARNING: Could not download maliit-keyboard.desktop"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
# Step 08: Dark theme (GTK3 settings, GTK CSS, taskbar theme)
|
||||
|
||||
step_08_dark_theme() {
|
||||
local theme_name="$GTK_THEME_NAME"
|
||||
[[ ! -d "/usr/share/themes/$theme_name" ]] && [[ -d /usr/share/themes/Adwaita-dark ]] \
|
||||
&& theme_name="Adwaita-dark" && log "Using Adwaita-dark (PiXnoir not found)"
|
||||
|
||||
local icon_theme=""
|
||||
[[ -d /usr/share/icons/PiXtrix ]] && icon_theme="PiXtrix"
|
||||
|
||||
# GTK3 settings
|
||||
local gtk_ini="$PI_HOME/.config/gtk-3.0/settings.ini"
|
||||
mkdir -p "$(dirname "$gtk_ini")"
|
||||
if [[ ! -f "$gtk_ini" ]]; then
|
||||
{ printf '%s\n' '[Settings]' 'gtk-application-prefer-dark-theme=1' "gtk-theme-name=$theme_name"
|
||||
[[ -n "$icon_theme" ]] && echo "gtk-icon-theme-name=$icon_theme"
|
||||
} > "$gtk_ini"
|
||||
else
|
||||
_set_ini() { grep -q "^$1=" "$gtk_ini" && sed -i "s/^$1=.*/$1=$2/" "$gtk_ini" || echo "$1=$2" >> "$gtk_ini"; }
|
||||
_set_ini gtk-application-prefer-dark-theme 1
|
||||
_set_ini gtk-theme-name "$theme_name"
|
||||
[[ -n "$icon_theme" ]] && _set_ini gtk-icon-theme-name "$icon_theme"
|
||||
fi
|
||||
log "GTK theme: $theme_name" && [[ -n "$icon_theme" ]] && log "Icon theme: $icon_theme"
|
||||
|
||||
# GTK4/Libadwaita dark preference
|
||||
if [[ -f "$PI_HOME/.profile" ]] && ! grep -q 'ADW_DEBUG_COLOR_SCHEME' "$PI_HOME/.profile" 2>/dev/null; then
|
||||
printf '\n%s\n' 'export ADW_DEBUG_COLOR_SCHEME=prefer-dark' >> "$PI_HOME/.profile"
|
||||
chown "$PI_USER:$PI_USER" "$PI_HOME/.profile"
|
||||
log "Added prefer-dark to .profile"
|
||||
fi
|
||||
|
||||
# Custom GTK CSS (dark menus/popovers)
|
||||
curl -fsSL "${FILE_SERVER}/gtk.css" -o "$PI_HOME/.config/gtk-3.0/gtk.css" 2>/dev/null \
|
||||
&& log "gtk.css installed" || true
|
||||
|
||||
# Taskbar theme
|
||||
local panel_dir="$PI_HOME/.config/wf-panel-pi"
|
||||
mkdir -p "$panel_dir"
|
||||
if curl -fsSL "${FILE_SERVER}/wf-panel-pi.ini" -o "$panel_dir/wf-panel-pi.ini" 2>/dev/null; then
|
||||
sed -i "s|/home/pi|$PI_HOME|g" "$panel_dir/wf-panel-pi.ini"
|
||||
curl -fsSL "${FILE_SERVER}/panel-theme.css" -o "$panel_dir/panel-theme.css" 2>/dev/null || true
|
||||
log "Taskbar theme installed"
|
||||
fi
|
||||
|
||||
chown -R "$PI_USER:$PI_USER" "$PI_HOME/.config"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
# Step 09: Re-apply Plymouth splash theme after driver install
|
||||
|
||||
step_09_reapply_splash() {
|
||||
local cfg="/boot/firmware/config.txt"
|
||||
[[ -f "$cfg" ]] || cfg="/boot/config.txt"
|
||||
if [[ -f "$cfg" ]] && grep -q '^disable_splash=1' "$cfg"; then
|
||||
sed -i 's/^disable_splash=1$/disable_splash=0/' "$cfg"
|
||||
log "Set disable_splash=0"
|
||||
fi
|
||||
|
||||
if [[ -f /etc/plymouth/plymouthd.conf ]]; then
|
||||
sed -i '/^Theme=/d; /^\[Daemon\]$/d' /etc/plymouth/plymouthd.conf
|
||||
grep -q '^\[Daemon\]' /etc/plymouth/plymouthd.conf || echo '[Daemon]' >> /etc/plymouth/plymouthd.conf
|
||||
echo 'Theme=custom' >> /etc/plymouth/plymouthd.conf
|
||||
fi
|
||||
|
||||
log "Running update-initramfs ..."
|
||||
update-initramfs -u -k all 2>/dev/null || true
|
||||
}
|
||||
17
emmc-provisioning/cloud-init/fileserver/steps/10-cmdline.sh
Normal file
17
emmc-provisioning/cloud-init/fileserver/steps/10-cmdline.sh
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
# Step 10: Kernel command line (swiotlb + DSI rotation)
|
||||
|
||||
step_10_cmdline() {
|
||||
local cmdline="/boot/firmware/cmdline.txt"
|
||||
[[ -f "$cmdline" ]] || cmdline="/boot/cmdline.txt"
|
||||
[[ -f "$cmdline" ]] || { log "WARNING: cmdline.txt not found"; return 0; }
|
||||
|
||||
if [[ -n "$SWIOTLB_SIZE" ]] && ! grep -q 'swiotlb=' "$cmdline"; then
|
||||
sed -i "s/rootwait/rootwait swiotlb=$SWIOTLB_SIZE/" "$cmdline"
|
||||
log "Added swiotlb=$SWIOTLB_SIZE to cmdline"
|
||||
fi
|
||||
if [[ -n "$DSI_ROTATE" ]] && ! grep -q 'video=DSI-1:rotate=' "$cmdline"; then
|
||||
sed -i "s/\$/ video=DSI-1:rotate=$DSI_ROTATE/" "$cmdline"
|
||||
log "Added video=DSI-1:rotate=$DSI_ROTATE to cmdline"
|
||||
fi
|
||||
}
|
||||
28
emmc-provisioning/cloud-init/fileserver/steps/11-oneshots.sh
Normal file
28
emmc-provisioning/cloud-init/fileserver/steps/11-oneshots.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
# Step 11: Install one-shot and per-login scripts
|
||||
|
||||
step_11_oneshots() {
|
||||
# Rotation: install set-rotation-at-login (re-applies kanshi config every login)
|
||||
if [[ -n "$DSI_ROTATE" ]]; then
|
||||
log "Rotation $DSI_ROTATE set via cmdline"
|
||||
if curl -fsSL "${FILE_SERVER}/set-rotation-at-login.sh" -o "$PI_HOME/set-rotation-at-login.sh" 2>/dev/null; then
|
||||
chmod 755 "$PI_HOME/set-rotation-at-login.sh"
|
||||
chown "$PI_USER:$PI_USER" "$PI_HOME/set-rotation-at-login.sh"
|
||||
if curl -fsSL "${FILE_SERVER}/set-rotation-at-login.desktop" -o /tmp/sral.desktop 2>/dev/null; then
|
||||
sed "s|/home/pi|$PI_HOME|g" /tmp/sral.desktop > "$AUTOSTART/set-rotation-at-login.desktop"
|
||||
chown "$PI_USER:$PI_USER" "$AUTOSTART/set-rotation-at-login.desktop"
|
||||
rm -f /tmp/sral.desktop
|
||||
log "set-rotation-at-login installed"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Additional one-shots from config
|
||||
if [[ -n "$ONESHOT_SCRIPTS" ]]; then
|
||||
for _name in $ONESHOT_SCRIPTS; do
|
||||
install_oneshot "$_name" || true
|
||||
done
|
||||
else
|
||||
log "No additional one-shot scripts"
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
# Step 12: Make log file appendable by the pi user
|
||||
|
||||
step_12_log_permissions() {
|
||||
chmod 666 "$LOGFILE"
|
||||
log "Log $LOGFILE now appendable by $PI_USER"
|
||||
}
|
||||
11
emmc-provisioning/cloud-init/fileserver/steps/13-reboot.sh
Normal file
11
emmc-provisioning/cloud-init/fileserver/steps/13-reboot.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
# Step 13: Report completion and reboot
|
||||
|
||||
step_13_reboot() {
|
||||
local ip
|
||||
ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||||
report_status "done" "First-boot complete" "13" "reboot" "$ip"
|
||||
log "Device IP: ${ip:-unknown}"
|
||||
log "=== first-boot.sh finished, rebooting ==="
|
||||
reboot
|
||||
}
|
||||
20
emmc-provisioning/cloud-init/fileserver/wf-panel-pi.ini
Normal file
20
emmc-provisioning/cloud-init/fileserver/wf-panel-pi.ini
Normal file
@@ -0,0 +1,20 @@
|
||||
# wf-panel-pi – minimal dark taskbar, touch-friendly
|
||||
# Copy to ~/.config/wf-panel-pi/wf-panel-pi.ini (user pi)
|
||||
# Set css_path to panel-theme.css. Restart panel: pkill wf-panel-pi
|
||||
# Icon theme (start-here) is set in gtk-3.0/settings.ini (PiXtrix) so custom icon from first-boot is used.
|
||||
|
||||
[panel]
|
||||
css_path = /home/pi/.config/wf-panel-pi/panel-theme.css
|
||||
# Left: start menu (uses start-here from PiXtrix), launchers, window list
|
||||
widgets_left = smenu spacing0 spacing2 launchers spacing4 window-list
|
||||
widgets_center = none
|
||||
# Right: tray, network, volume, clock, power (minimal set, touch-friendly)
|
||||
widgets_right = tray spacing2 netman spacing2 volumepulse spacing2 clock spacing2 power
|
||||
# Touch-friendly size (32px min target)
|
||||
icon_size = 32
|
||||
minimal_height = 36
|
||||
position = top
|
||||
# Match Adwaita-dark window bg (#242424) so taskbar fits dark theme
|
||||
background_color = #242424FF
|
||||
autohide = false
|
||||
autohide_duration = 300
|
||||
Reference in New Issue
Block a user