<message>Update the cloud-init scripts to improve GTK theme settings by enforcing dark mode through gsettings and preserving the icon theme for a cohesive user experience. Additionally, enhance the first-boot script to install a Chromium kiosk launcher icon on the desktop and in the application menu, along with a five-tap close functionality for Chromium. These changes streamline the user interface and ensure a consistent dark theme across applications and the taskbar.
90 lines
2.4 KiB
Python
90 lines
2.4 KiB
Python
#!/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 subprocess
|
|
import sys
|
|
|
|
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:
|
|
sys.stderr.write("five-tap-close-chromium: need PyGObject Gtk: %s\n" % 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:
|
|
return 800, 1280
|
|
monitor = display.get_monitor(0) if display.get_n_monitors() else None
|
|
if monitor:
|
|
geom = monitor.get_geometry()
|
|
return geom.width, geom.height
|
|
return 800, 1280
|
|
|
|
|
|
def on_button_press(widget, event, data):
|
|
count, reset_timer = data
|
|
count[0] += 1
|
|
if reset_timer[0]:
|
|
GLib.source_remove(reset_timer[0])
|
|
if count[0] >= 5:
|
|
count[0] = 0
|
|
try:
|
|
subprocess.run(CHROMIUM_KILL_CMD, timeout=2, capture_output=True)
|
|
except Exception:
|
|
pass
|
|
if reset_timer[0]:
|
|
GLib.source_remove(reset_timer[0])
|
|
reset_timer[0] = None
|
|
return
|
|
def reset():
|
|
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()
|
|
# Position top-right (after realization so we have a display)
|
|
w, h = get_screen_size()
|
|
x = max(0, w - CORNER_SIZE)
|
|
win.move(x, 0)
|
|
win.show_all()
|
|
Gtk.main()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|