fix: put the popup close button in the dock, and clear the printer location
Three things, none of them redesigns. The close affordance for a secondary Chrome window was a separate layer-shell surface anchored to that window's corner, repositioned by a five-per-second poll. Any position change tore the surface down and built another, so on real hardware it chased the window and flickered. Removed entirely: the GTK button process, the geometry maths that placed it, the --close-button mode that spawned it, and the poll loop that drove it. The window helper no longer imports GTK at all. The behaviour underneath it was right and is kept. The first Chrome top-level is the classroom browser, tiled and borderless; later ones float centred at about three quarters of the output. Creation order is the only thing that can tell them apart — confirmed on a real session, where every Chrome top-level shares app_id, shell, PID and a null transient_for, and sway exposes no window properties for Wayland toplevels at all. Titles are still not used. It now follows sway's own window events instead of polling, so dragging a popup costs nothing. Close moved into the dock, which was already on screen and does not move, so it cannot chase anything. It appears only while a secondary window is focused and runs kill on that one container. The helper publishes which window that is; the dock watches the file rather than polling. A stock sway title bar has no close button, so restoring the border would not have solved this either. Two bugs found by looking rather than by testing state. Chrome renegotiates the size of a popup opened with explicit dimensions after the resize returns, which left windows centred for a width they no longer had; placement now settles and repeats once, at creation only, so dragging is still free. And the dock's Close button came up empty because show_all does not recurse into a no-show-all widget. The printer's Location is now blank. CUPS prints it under the queue name in every dialog, so "Ekklesia Classroom" was a second line the teacher had to read past; the identity is one word. The already-configured check includes Location, so a machine set up before this is corrected rather than left as close enough. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a1d8150d7c
commit
f65c814eff
+106
-21
@@ -1,24 +1,34 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Configure the one explicitly managed classroom printer. The Ricoh Aficio
|
||||
# MP C3502 supports PCL 6 as standard; Debian Trixie's compressed Foomatic
|
||||
# Configure the one explicitly managed church printer. The Ricoh Aficio MP
|
||||
# C3502 supports PCL 6 as standard; Debian Trixie's compressed Foomatic
|
||||
# database supplies this generic color PCL 6/PCL XL path without vendor code.
|
||||
|
||||
QUEUE="Classroom_Color"
|
||||
QUEUE="Elmer"
|
||||
LEGACY_QUEUE="Classroom_Color"
|
||||
DEFAULT_URI="socket://10.10.0.155:9100"
|
||||
DRIVER="foomatic-db-compressed-ppds:0/ppd/foomatic-ppd/Generic-PCL_6_PCL_XL_Printer-pxlcolor.ppd"
|
||||
MAKE_MODEL="Ricoh Aficio MP C3502 (Generic PCL 6 Color)"
|
||||
LOCATION="Ekklesia Classroom"
|
||||
DESCRIPTION="Elmer"
|
||||
# Blank on purpose. CUPS shows Location under the queue name in every
|
||||
# print dialog, and the teacher-facing identity of this printer is
|
||||
# simply "Elmer".
|
||||
LOCATION=""
|
||||
MAKE_DEFAULT=true
|
||||
COMMAND_TIMEOUT=10
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Usage: classroom-printer-setup [--no-default] PRINTER-IP-OR-URI
|
||||
Usage: classroom-printer-setup [--no-default] [PRINTER-IP-OR-URI]
|
||||
|
||||
Examples:
|
||||
sudo classroom-printer-setup 10.20.30.40
|
||||
sudo classroom-printer-setup
|
||||
sudo classroom-printer-setup 10.10.0.155
|
||||
sudo classroom-printer-setup socket://printer.example.org:9100
|
||||
|
||||
With no address, configures the church Ricoh as Elmer at
|
||||
socket://10.10.0.155:9100.
|
||||
|
||||
An IP address or hostname uses JetDirect/AppSocket on port 9100. Explicit
|
||||
socket://, ipp://, ipps:// and lpd:// URIs are also accepted.
|
||||
USAGE
|
||||
@@ -34,7 +44,7 @@ fail() {
|
||||
}
|
||||
|
||||
if [[ "${CLASSROOM_PRINTER_SETUP_TESTING:-false}" != "true" && $EUID -ne 0 ]]; then
|
||||
fail "run this command as root: sudo classroom-printer-setup <printer-ip>"
|
||||
fail "run this command as root: sudo classroom-printer-setup"
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "--no-default" ]]; then
|
||||
@@ -42,13 +52,13 @@ if [[ "${1:-}" == "--no-default" ]]; then
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $# -ne 1 || "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
if [[ $# -gt 1 || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
usage
|
||||
[[ $# -eq 1 ]] && exit 0
|
||||
[[ $# -le 1 ]] && exit 0
|
||||
exit 2
|
||||
fi
|
||||
|
||||
address="$1"
|
||||
address="${1:-$DEFAULT_URI}"
|
||||
|
||||
case "$address" in
|
||||
socket://*|ipp://*|ipps://*|lpd://*)
|
||||
@@ -65,20 +75,78 @@ case "$address" in
|
||||
;;
|
||||
esac
|
||||
|
||||
for command in lpadmin lpinfo lpstat cupsenable cupsaccept; do
|
||||
for command in timeout lpadmin lpinfo lpoptions lpstat cupsenable cupsaccept; do
|
||||
command -v "$command" >/dev/null 2>&1 || \
|
||||
fail "$command is missing; reinstall the ekklesia-classroom package"
|
||||
done
|
||||
|
||||
if ! lpstat -r >/dev/null 2>&1; then
|
||||
run_bounded() {
|
||||
timeout \
|
||||
--signal=TERM \
|
||||
--kill-after=2s \
|
||||
"${COMMAND_TIMEOUT}s" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
disable_discovery() {
|
||||
command -v systemctl >/dev/null 2>&1 || return 0
|
||||
|
||||
# cups-browsed creates local queues for advertised printers. CUPS can also
|
||||
# enumerate DNS-SD destinations through Avahi even without cups-browsed,
|
||||
# so disable both Avahi activation paths on this single-purpose appliance.
|
||||
run_bounded systemctl disable --now cups-browsed.service \
|
||||
>/dev/null 2>&1 || true
|
||||
run_bounded systemctl disable --now \
|
||||
avahi-daemon.socket avahi-daemon.service >/dev/null 2>&1 || true
|
||||
run_bounded systemctl mask \
|
||||
avahi-daemon.socket avahi-daemon.service >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
disable_discovery
|
||||
|
||||
if ! run_bounded lpstat -r >/dev/null 2>&1; then
|
||||
command -v systemctl >/dev/null 2>&1 && \
|
||||
systemctl start cups.service >/dev/null 2>&1 || true
|
||||
run_bounded systemctl start cups.service >/dev/null 2>&1 || true
|
||||
|
||||
# systemctl can return as the service begins starting. Give the local
|
||||
# scheduler a short, bounded chance to create its socket.
|
||||
for _ in {1..20}; do
|
||||
run_bounded lpstat -r >/dev/null 2>&1 && break
|
||||
sleep 0.25
|
||||
done
|
||||
fi
|
||||
|
||||
lpstat -r >/dev/null 2>&1 || \
|
||||
run_bounded lpstat -r >/dev/null 2>&1 || \
|
||||
fail "CUPS is not running; check: systemctl status cups"
|
||||
|
||||
models="$(lpinfo -m)" || fail "CUPS could not list installed printer drivers"
|
||||
if run_bounded lpstat -p "$LEGACY_QUEUE" >/dev/null 2>&1; then
|
||||
log "removing legacy ${LEGACY_QUEUE} queue"
|
||||
run_bounded lpadmin -x "$LEGACY_QUEUE" || \
|
||||
fail "CUPS could not remove legacy queue ${LEGACY_QUEUE}"
|
||||
fi
|
||||
|
||||
device="$(run_bounded lpstat -v "$QUEUE" 2>/dev/null || true)"
|
||||
status="$(run_bounded lpstat -p "$QUEUE" 2>/dev/null || true)"
|
||||
accepting="$(run_bounded lpstat -a "$QUEUE" 2>/dev/null || true)"
|
||||
default="$(run_bounded lpstat -d 2>/dev/null || true)"
|
||||
details="$(run_bounded lpstat -l -p "$QUEUE" 2>/dev/null || true)"
|
||||
options="$(run_bounded lpoptions -p "$QUEUE" -l 2>/dev/null || true)"
|
||||
|
||||
if grep -Fq ": ${uri}" <<< "$device" \
|
||||
&& grep -Fq "printer ${QUEUE}" <<< "$status" \
|
||||
&& grep -Fq " enabled " <<< " ${status} " \
|
||||
&& grep -Fq "${QUEUE} accepting requests" <<< "$accepting" \
|
||||
&& grep -Fq "system default destination: ${QUEUE}" <<< "$default" \
|
||||
&& grep -Fq "Description: ${DESCRIPTION}" <<< "$details" \
|
||||
&& grep -Eq '^[[:space:]]*Location:[[:space:]]*$' <<< "$details" \
|
||||
&& grep -Eq '^PrintoutMode/.*:.*\*Normal([[:space:]]|$)' <<< "$options" \
|
||||
&& grep -Eq '^ColorModel/.*:.*\*Color([[:space:]]|$)' <<< "$options"; then
|
||||
log "${QUEUE} is already correctly configured."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
models="$(run_bounded lpinfo -m)" || \
|
||||
fail "CUPS could not list installed printer drivers"
|
||||
|
||||
if ! grep -q "^${DRIVER} " <<< "$models"; then
|
||||
fail "the Debian generic color PCL 6 driver is not installed"
|
||||
@@ -88,18 +156,34 @@ log "configuring ${QUEUE} at ${uri}"
|
||||
|
||||
# Repeating this command updates the same named queue; it never creates a
|
||||
# second destination. None of these operations connects to the printer.
|
||||
lpadmin \
|
||||
run_bounded lpadmin \
|
||||
-p "$QUEUE" \
|
||||
-v "$uri" \
|
||||
-m "$DRIVER" \
|
||||
-D "$MAKE_MODEL" \
|
||||
-D "$DESCRIPTION" \
|
||||
-L "$LOCATION" || fail "CUPS could not configure ${QUEUE}"
|
||||
|
||||
cupsenable "$QUEUE" || fail "CUPS could not enable ${QUEUE}"
|
||||
cupsaccept "$QUEUE" || fail "CUPS could not accept jobs for ${QUEUE}"
|
||||
# CUPS on Trixie does not reliably retain PPD choices supplied in the same
|
||||
# request that selects the driver. Apply the physically verified defaults in a
|
||||
# second request after the PPD exists.
|
||||
run_bounded lpadmin \
|
||||
-p "$QUEUE" \
|
||||
-o PrintoutMode=Normal \
|
||||
-o ColorModel=Color || fail "CUPS could not set the color defaults for ${QUEUE}"
|
||||
|
||||
options="$(run_bounded lpoptions -p "$QUEUE" -l 2>/dev/null || true)"
|
||||
|
||||
grep -Eq '^PrintoutMode/.*:.*\*Normal([[:space:]]|$)' <<< "$options" \
|
||||
|| fail "CUPS did not retain PrintoutMode=Normal for ${QUEUE}"
|
||||
grep -Eq '^ColorModel/.*:.*\*Color([[:space:]]|$)' <<< "$options" \
|
||||
|| fail "CUPS did not retain ColorModel=Color for ${QUEUE}"
|
||||
|
||||
run_bounded cupsenable "$QUEUE" || fail "CUPS could not enable ${QUEUE}"
|
||||
run_bounded cupsaccept "$QUEUE" || fail "CUPS could not accept jobs for ${QUEUE}"
|
||||
|
||||
if [[ "$MAKE_DEFAULT" == true ]]; then
|
||||
lpadmin -d "$QUEUE" || fail "CUPS could not make ${QUEUE} the default"
|
||||
run_bounded lpadmin -d "$QUEUE" || \
|
||||
fail "CUPS could not make ${QUEUE} the default"
|
||||
fi
|
||||
|
||||
log "${QUEUE} is configured, enabled and accepting jobs."
|
||||
@@ -108,4 +192,5 @@ if [[ "$MAKE_DEFAULT" == true ]]; then
|
||||
log "${QUEUE} is the system default printer."
|
||||
fi
|
||||
|
||||
log "Print defaults: PrintoutMode=Normal, ColorModel=Color."
|
||||
log "The printer may remain offline until it is reachable; this does not affect boot."
|
||||
|
||||
Reference in New Issue
Block a user