Update first-boot configuration and scripts for enhanced kiosk functionality</message>
<message>Modify the first-boot configuration to include the gir1.2-gtklayershell-0.1 package for improved GTK layer shell support. Update the first-boot script to enhance the portal status reporting with connection timeouts. Additionally, implement a restart mechanism for the kanshi service in rotation scripts to ensure immediate application of configuration changes. Introduce a Chromium kiosk extension to disable text selection, improving user experience in kiosk mode. These changes streamline the setup process and enhance the overall functionality of the kiosk environment.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#!/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.
|
||||
# Uses wlr-layer-shell to create an overlay surface above all windows (including fullscreen).
|
||||
# Falls back to a regular GTK window on X11.
|
||||
# Run from session autostart. Requires: python3, PyGObject (Gtk3), gir1.2-gtklayershell-0.1.
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
@@ -23,25 +25,19 @@ except Exception as e:
|
||||
log.error("need PyGObject Gtk: %s", e)
|
||||
sys.exit(1)
|
||||
|
||||
HAS_LAYER_SHELL = False
|
||||
try:
|
||||
gi.require_version("GtkLayerShell", "0.1")
|
||||
from gi.repository import GtkLayerShell
|
||||
HAS_LAYER_SHELL = True
|
||||
except Exception:
|
||||
log.warning("GtkLayerShell not available, falling back to regular window")
|
||||
|
||||
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
|
||||
@@ -69,6 +65,40 @@ def on_button_press(widget, event, data):
|
||||
return False
|
||||
|
||||
|
||||
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 make_window_layer_shell(win):
|
||||
"""Anchor an overlay surface to the top-right corner via wlr-layer-shell."""
|
||||
GtkLayerShell.init_for_window(win)
|
||||
GtkLayerShell.set_layer(win, GtkLayerShell.Layer.OVERLAY)
|
||||
GtkLayerShell.set_anchor(win, GtkLayerShell.Edge.TOP, True)
|
||||
GtkLayerShell.set_anchor(win, GtkLayerShell.Edge.RIGHT, True)
|
||||
GtkLayerShell.set_keyboard_mode(win, GtkLayerShell.KeyboardMode.NONE)
|
||||
log.info("layer-shell overlay anchored top-right (%dx%d)", CORNER_SIZE, CORNER_SIZE)
|
||||
|
||||
|
||||
def make_window_fallback(win):
|
||||
"""X11 fallback: position with move() and hope keep-above works."""
|
||||
win.set_keep_above(True)
|
||||
win.realize()
|
||||
w, _h = get_screen_size()
|
||||
x = max(0, w - CORNER_SIZE)
|
||||
win.move(x, 0)
|
||||
log.info("X11 fallback: window positioned at x=%d y=0", x)
|
||||
|
||||
|
||||
def main():
|
||||
win = Gtk.Window()
|
||||
win.set_decorated(False)
|
||||
@@ -76,27 +106,33 @@ def main():
|
||||
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
|
||||
|
||||
# Make the window nearly invisible
|
||||
screen = win.get_screen()
|
||||
visual = screen.get_rgba_visual()
|
||||
if visual:
|
||||
win.set_visual(visual)
|
||||
win.set_app_paintable(True)
|
||||
win.connect("draw", lambda w, cr: (cr.set_source_rgba(0, 0, 0, 0.01), cr.paint()))
|
||||
|
||||
if HAS_LAYER_SHELL and GtkLayerShell.is_supported():
|
||||
make_window_layer_shell(win)
|
||||
else:
|
||||
make_window_fallback(win)
|
||||
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user