git: 2e07486a80c4 - main - x11/framework-autorotate: New port

Devin Teske <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.ports
Message-ID <[email protected]>
The branch main has been updated by dteske:

URL: https://cgit.FreeBSD.org/ports/commit/?id=2e07486a80c4afc2d3659c78d4847b03a938b5a9

commit 2e07486a80c4afc2d3659c78d4847b03a938b5a9
Author:     Devin Teske <[email protected]>
AuthorDate: 2026-08-13 02:31:53 +0000
Commit:     Devin Teske <[email protected]>
CommitDate: 2026-08-13 02:31:53 +0000

    x11/framework-autorotate: New port
    
    Framework Laptop 12 X11 display autorotate: Chrome EC memmap
    accelerometer and TBMD drive RandR on the built-in panel, ILIT
    touch/stylus remap, XDM greeter recovery, and an optional
    per-user chrome hook.
    
    Reviewed by:    jrm
    Differential Revision:  https://reviews.freebsd.org/D58651
---
 x11/Makefile                                       |   1 +
 x11/framework-autorotate/Makefile                  |  49 +++++++
 x11/framework-autorotate/distinfo                  |   3 +
 .../files/framework_autorotate.in                  | 143 +++++++++++++++++++++
 x11/framework-autorotate/pkg-descr                 |   8 ++
 x11/framework-autorotate/pkg-message               |  16 +++
 x11/framework-autorotate/pkg-plist                 |   6 +
 7 files changed, 226 insertions(+)

diff --git a/x11/Makefile b/x11/Makefile
index 371e316c9f3d..06acf874ee64 100644
--- a/x11/Makefile
+++ b/x11/Makefile
@@ -91,6 +91,7 @@
     SUBDIR += flruler
     SUBDIR += fnott
     SUBDIR += foot
+    SUBDIR += framework-autorotate
     SUBDIR += fstobdf
     SUBDIR += fuzzel
     SUBDIR += gbsddialog
diff --git a/x11/framework-autorotate/Makefile b/x11/framework-autorotate/Makefile
new file mode 100644
index 000000000000..6a2702cef375
--- /dev/null
+++ b/x11/framework-autorotate/Makefile
@@ -0,0 +1,49 @@
+PORTNAME=	framework-autorotate
+DISTVERSION=	1.0
+CATEGORIES=	x11
+
+MAINTAINER=	[email protected]
+COMMENT=	Framework Laptop 12 X11 display autorotate
+WWW=		https://github.com/FrauBSD/framework-autorotate
+
+LICENSE=	BSD2CLAUSE
+LICENSE_FILE=	${WRKSRC}/LICENSE
+
+RUN_DEPENDS=	xdpyinfo:x11/xdpyinfo \
+		xinput:x11/xinput \
+		xrandr:x11/xrandr \
+		xset:x11/xset
+
+USES=		localbase:ldflags xorg
+USE_GITHUB=	yes
+GH_ACCOUNT=	FrauBSD
+USE_RC_SUBR=	framework_autorotate
+USE_XORG=	x11 xrandr
+
+CFLAGS+=	-Wall -Wextra
+
+EXAMPLESDIR=	${PREFIX}/share/examples/framework_autorotate
+
+OPTIONS_DEFINE=		EXAMPLES
+OPTIONS_DEFAULT=	EXAMPLES
+OPTIONS_SUB=		yes
+
+do-install:
+	${INSTALL_PROGRAM} ${WRKSRC}/framework_autorotate \
+		${STAGEDIR}${PREFIX}/sbin
+	@${MKDIR} ${STAGEDIR}${PREFIX}/libexec/framework_autorotate
+	${INSTALL_PROGRAM} ${WRKSRC}/xlogin_recenter \
+		${STAGEDIR}${PREFIX}/libexec/framework_autorotate
+	${INSTALL_SCRIPT} ${WRKSRC}/libexec/map-touchscreen \
+		${STAGEDIR}${PREFIX}/libexec/framework_autorotate
+	${INSTALL_MAN} ${WRKSRC}/framework_autorotate.8 \
+		${STAGEDIR}${PREFIX}/share/man/man8
+
+post-install-EXAMPLES-on:
+	@${MKDIR} ${STAGEDIR}${EXAMPLESDIR}
+	${INSTALL_DATA} ${WRKSRC}/examples/dot.framework_autorotate.fvwm \
+		${STAGEDIR}${EXAMPLESDIR}
+	${INSTALL_DATA} ${WRKSRC}/examples/dot.framework_autorotate.bvwm \
+		${STAGEDIR}${EXAMPLESDIR}
+
+.include <bsd.port.mk>
diff --git a/x11/framework-autorotate/distinfo b/x11/framework-autorotate/distinfo
new file mode 100644
index 000000000000..a2c9bd834999
--- /dev/null
+++ b/x11/framework-autorotate/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1786585556
+SHA256 (FrauBSD-framework-autorotate-1.0_GH0.tar.gz) = a520b96eaf004fe2712f8c0b8dd247b17faf4fdb7f76daab388cc8ffbcd15c19
+SIZE (FrauBSD-framework-autorotate-1.0_GH0.tar.gz) = 28054
diff --git a/x11/framework-autorotate/files/framework_autorotate.in b/x11/framework-autorotate/files/framework_autorotate.in
new file mode 100644
index 000000000000..26f3dd352ac4
--- /dev/null
+++ b/x11/framework-autorotate/files/framework_autorotate.in
@@ -0,0 +1,143 @@
+#!/bin/sh
+
+# PROVIDE: framework_autorotate
+# REQUIRE: LOGIN
+# KEYWORD: nojail shutdown
+#
+# Framework Laptop 12 autorotate (Chrome EC accel + TBMD -> RandR/CTM).
+# Safe with XDM greeter.  KDE/GNOME/XFCE typically need no chrome hook;
+# optional ~/.framework_autorotate is opt-in (e.g. FVWM taskbar refresh).
+#
+# Enable in /etc/rc.conf:
+#	framework_autorotate_enable="YES"
+#
+# Mode (always vs tablet-gated):
+#	framework_autorotate_mode="always"	# default: rotate whenever accel says
+#	framework_autorotate_mode="tablet"	# only while EC TBMD=1; else normal
+#
+# Optional:
+#	framework_autorotate_display=":0"
+#	framework_autorotate_hook=".framework_autorotate"	# under $HOME
+#	framework_autorotate_flags=""
+#	framework_autorotate_xlogin_recenter="%%PREFIX%%/libexec/framework_autorotate/xlogin_recenter"
+#	framework_autorotate_logfile="/var/log/framework_autorotate.log"	# opt-in; empty = no log
+#
+# Chrome-hook login is always auto-detected (non-root X client; FvwmMFL
+# owner if present).
+#
+# Per-user chrome hook (~/.framework_autorotate), spirit of .xinitrc:
+# if that file exists in the logged-in user's home, it is run after each
+# rotate as that user with CHROME_WIDTH / CHROME_HEIGHT /
+# FRAMEWORK_AUTOROTATE_ROTATION set.  Absent = no-op (usual for KDE/GNOME/XFCE).
+#
+# daemon(8) note: -p/-o/-P enable supervision mode.  The pidfile must track
+# the *supervisor* (-P), not the child (-p).  With -p, stop waits for the
+# child then start races the still-locked supervisor -> "already running"
+# and status says not running (child gone, lock remains).
+#
+
+. /etc/rc.subr
+
+name="framework_autorotate"
+rcvar=framework_autorotate_enable
+desc="Framework Laptop 12 display autorotate"
+
+load_rc_config $name
+
+: ${framework_autorotate_enable:=NO}
+: ${framework_autorotate_mode:=always}
+: ${framework_autorotate_display:=:0}
+: ${framework_autorotate_hook:=.framework_autorotate}
+: ${framework_autorotate_flags:=}
+: ${framework_autorotate_xlogin_recenter:=%%PREFIX%%/libexec/framework_autorotate/xlogin_recenter}
+: ${framework_autorotate_logfile:=}
+
+pidfile="/var/run/${name}.pid"
+# Supervisor is what holds the pidfile lock under daemon(8) -P.
+procname="/usr/sbin/daemon"
+command="/usr/sbin/daemon"
+framework_autorotate_bin="%%PREFIX%%/sbin/framework_autorotate"
+start_precmd="${name}_prestart"
+start_cmd="${name}_start"
+
+framework_autorotate_prestart()
+{
+	if [ ! -x "$framework_autorotate_bin" ]; then
+		err 1 "$framework_autorotate_bin not installed"
+	fi
+	case "$framework_autorotate_mode" in
+	always|tablet) : ok ;;
+	*)
+		err 1 "framework_autorotate_mode must be always or tablet"
+		;;
+	esac
+	if [ ! -c /dev/io ]; then
+		warn "/dev/io missing; autorotate needs io privilege"
+	fi
+}
+
+framework_autorotate_start()
+{
+	local auth
+
+	#
+	# XDM often starts from ttys after LOGIN.  The daemon itself pauses
+	# until DISPLAY is ready; pick the newest :0 cookie if present.
+	# Chrome-hook login is resolved per-rotate inside the binary.
+	#
+	auth=$( ls -t /var/db/xdm/authdir/authfiles/A:0-* 2> /dev/null |
+	    head -1 )
+
+	# -P: supervisor PID in pidfile (rc.subr stop/status target).
+	# -t: setproctitle for admin visibility.
+	# -o: opt-in log capture only when framework_autorotate_logfile is set.
+	# -v on the binary likewise only when logging (otherwise discarded).
+	if [ -n "$framework_autorotate_logfile" ]; then
+		/usr/sbin/daemon -f -P "$pidfile" -t framework_autorotate \
+		    -o "$framework_autorotate_logfile" \
+		    /usr/bin/env \
+		    DISPLAY="$framework_autorotate_display" \
+		    ${auth:+XAUTHORITY="$auth"} \
+		    FRAMEWORK_AUTOROTATE_HOOK_NAME="$framework_autorotate_hook" \
+		    FRAMEWORK_AUTOROTATE_XLOGIN_RECENTER="$framework_autorotate_xlogin_recenter" \
+		    PATH="/sbin:/bin:/usr/sbin:/usr/bin:%%PREFIX%%/sbin:%%PREFIX%%/bin" \
+		    "$framework_autorotate_bin" -i 500 -m "$framework_autorotate_mode" -v \
+		    $framework_autorotate_flags
+	else
+		/usr/sbin/daemon -f -P "$pidfile" -t framework_autorotate \
+		    /usr/bin/env \
+		    DISPLAY="$framework_autorotate_display" \
+		    ${auth:+XAUTHORITY="$auth"} \
+		    FRAMEWORK_AUTOROTATE_HOOK_NAME="$framework_autorotate_hook" \
+		    FRAMEWORK_AUTOROTATE_XLOGIN_RECENTER="$framework_autorotate_xlogin_recenter" \
+		    PATH="/sbin:/bin:/usr/sbin:/usr/bin:%%PREFIX%%/sbin:%%PREFIX%%/bin" \
+		    "$framework_autorotate_bin" -i 500 -m "$framework_autorotate_mode" \
+		    $framework_autorotate_flags
+	fi
+
+	#
+	# daemon(8) creates pidfile/logfile mode 0600 regardless of umask.
+	# World-readable like xdm.pid/sshd.pid so unprivileged
+	# `service framework_autorotate status` works (rc.subr check_pidfile
+	# does `read < pidfile`; unreadable yields a spurious
+	# "eval: cannot open … Permission denied" from /bin/sh — not an eval
+	# in this script).
+	#
+	chmod 644 "$pidfile" 2> /dev/null || true
+	if [ -n "$framework_autorotate_logfile" ]; then
+		chmod 644 "$framework_autorotate_logfile" 2> /dev/null || true
+	fi
+}
+
+#
+# rc.subr snapshots ${name}_user for su(1) before start_precmd. Chrome-hook
+# login is resolved inside the binary — never via this knob — so drop it
+# before run_rc_command lest a curious rc.conf entry wrap start/stop in su
+# and break stop/restart.
+#
+if [ "${framework_autorotate_user:-}" ]; then
+	warn "ignoring framework_autorotate_user (rc.subr su target;" \
+	    "chrome-hook login is auto-detected)"
+	unset framework_autorotate_user
+fi
+run_rc_command "$1"
diff --git a/x11/framework-autorotate/pkg-descr b/x11/framework-autorotate/pkg-descr
new file mode 100644
index 000000000000..0ee12aedd39b
--- /dev/null
+++ b/x11/framework-autorotate/pkg-descr
@@ -0,0 +1,8 @@
+framework-autorotate orients the built-in display of a Framework Laptop 12
+under FreeBSD X11 by reading the Chrome Embedded Controller (EC) memmap
+accelerometer and tablet-mode bit (TBMD), applying xrandr to the internal
+panel (eDP/LVDS/DSI), and remapping absolute touch and stylus devices.
+
+It is intended for use with an X display manager greeter as well as an
+interactive session.  Framework Laptop 13 Pro, even with the touchscreen
+kit, is a clamshell, not a convertible.
diff --git a/x11/framework-autorotate/pkg-message b/x11/framework-autorotate/pkg-message
new file mode 100644
index 000000000000..4f3d4467dea5
--- /dev/null
+++ b/x11/framework-autorotate/pkg-message
@@ -0,0 +1,16 @@
+[
+{ type: install
+  message: <<EOM
+framework-autorotate provides Framework Laptop 12 X11 display autorotate
+via framework_autorotate(8).
+
+To enable at boot:
+
+  sysrc framework_autorotate_enable=YES
+  service framework_autorotate start
+
+Optional: framework_autorotate_mode=always|tablet and
+framework_autorotate_logfile.  See framework_autorotate(8).
+EOM
+}
+]
diff --git a/x11/framework-autorotate/pkg-plist b/x11/framework-autorotate/pkg-plist
new file mode 100644
index 000000000000..8bd1363314f3
--- /dev/null
+++ b/x11/framework-autorotate/pkg-plist
@@ -0,0 +1,6 @@
+sbin/framework_autorotate
+libexec/framework_autorotate/map-touchscreen
+libexec/framework_autorotate/xlogin_recenter
+share/man/man8/framework_autorotate.8.gz
+%%PORTEXAMPLES%%%%EXAMPLESDIR%%/dot.framework_autorotate.bvwm
+%%PORTEXAMPLES%%%%EXAMPLESDIR%%/dot.framework_autorotate.fvwm
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.