Rebase to flake parts #10

This commit is contained in:
2026-05-15 00:24:13 -03:00
parent f02606902c
commit fba5a7a2aa
24 changed files with 565 additions and 83 deletions
+6 -3
View File
@@ -7,9 +7,12 @@
powerManagement.enable = true;
# ─────────────────────── logind: lid & power button ───────────────────────
# Closing the lid suspends, even on AC — Duet 3 is a tablet, treat it like one.
# Short press on power: suspend (matches ChromeOS/iOS); long press: poweroff.
# The DMS bar power menu is the way to reboot / shut down explicitly.
# Tablet form factor: lid close = suspend (even on AC), short power-press = suspend, long
# power-press = poweroff. Niri's own power-key handler must stay disabled — see the
# `input.disable-power-key-handling` flag in `_private/touch-tablet.nix` — otherwise niri's
# `block` inhibitor on `handle-power-key` pre-empts logind and turns the wake-from-suspend
# press (which the EC re-delivers as KEY_POWER) into an immediate re-suspend loop
# (https://github.com/niri-wm/niri/issues/2233).
services.logind.settings.Login = {
HandleLidSwitch = "suspend";
HandleLidSwitchExternalPower = "suspend";
+34 -17
View File
@@ -1,17 +1,10 @@
# Host-only: ideapad tablet ergonomics — touchscreen calibration, IIO sensors, virtual keyboard,
# and per-session helper daemons (tablet-mode toggle + auto-rotation via iio-sensor-proxy) for both
# Niri and Hyprland.
# touch-controller resume fix, and per-session helper daemons (tablet-mode toggle + auto-rotation
# via iio-sensor-proxy) for both Niri and Hyprland. Lives at the NixOS layer because the hardware
# bits are system-wide; the per-compositor autostart hooks are gated on `chiasson.desktop.<wm>.enable`
# so they stay dormant if you pick the other session at the greeter.
#
# Why all of this lives at the *NixOS* layer (not the home-manager catalog under wisdom/):
# - The hardware bits (`hardware.sensor.iio.enable`, the udev calibration matrix) are system-wide
# and tied to this exact device, so they belong with the host module.
# - The compositor helpers run via session-specific autostart hooks (Niri `spawn-at-startup`,
# Hyprland `exec-once`); the wiring is gated on the matching `chiasson.desktop.<wm>.enable`,
# so picking a different session at the greeter just leaves them dormant.
#
# Two compositor flavours of each daemon:
# - Hyprland (CW transforms via `hyprctl`) — original; matches the old NixOS-New setup.
# - Niri (CCW transforms via `niri msg output`) — needed because Niri is the V2 default.
# Hyprland uses CW transforms via `hyprctl`; Niri uses CCW transforms via `niri msg output`.
{
config,
lib,
@@ -268,15 +261,33 @@ in
# ─────────────────────── Hardware ───────────────────────
hardware.sensor.iio.enable = true;
# Touchscreen calibration — solved empirically with `niri msg output DSI-1 transform normal`
# in the natural kb-down pose. The panel's touch hardware reports raw coordinates already
# aligned with the panel-native frame (HW(visual_top_left) = (0,0), etc.), so identity is
# correct. `niri input.touch.map-to-output = "DSI-1"` then handles per-orientation rotation
# on top — never re-tune this matrix per orientation; rotate the *output* instead.
# Touchscreen calibration — identity matrix is correct: hardware coordinates are already aligned
# with the panel-native frame, and per-orientation rotation is handled by `niri msg output`,
# not by re-tuning this matrix. Rotate the *output*, never this matrix.
services.udev.extraRules = ''
SUBSYSTEM=="input", ENV{ID_INPUT_TOUCHSCREEN}=="1", ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0"
'';
# ─────────────────────── Touch controller resume fix ───────────────────────
# The hid-over-i2c touch controller at i2c bus 4-0001 wedges across S3 suspend: after resume it
# re-enumerates with the correct capabilities but reports zero events on touch. Cycling the
# `i2c_hid_of` driver (unbind + bind) un-wedges it. systemd-sleep runs every executable in
# `/etc/systemd/system-sleep/` with `$1 = pre|post`; we only act on `post`. Driver name is
# discovered at runtime so a future kernel rename to `i2c_hid` doesn't break this.
environment.etc."systemd/system-sleep/ideapad-touch-rebind".source =
pkgs.writeShellScript "ideapad-touch-rebind" ''
set -eu
[ "$1" = post ] || exit 0
dev=4-0001
dev_dir=/sys/bus/i2c/devices/$dev
[ -L "$dev_dir/driver" ] || exit 0
drv=$(${pkgs.coreutils}/bin/basename "$(${pkgs.coreutils}/bin/readlink "$dev_dir/driver")")
echo "ideapad-touch-rebind: cycling $drv for $dev" >&2
echo "$dev" > "/sys/bus/i2c/drivers/$drv/unbind" || true
${pkgs.coreutils}/bin/sleep 0.3
echo "$dev" > "/sys/bus/i2c/drivers/$drv/bind"
'';
# ─────────────────────── User-facing tools ───────────────────────
# System-wide so any user session (Niri or Hyprland) can launch wvkbd / hyprctl / niri-msg helpers.
environment.systemPackages = [
@@ -297,6 +308,12 @@ in
chiasson.desktop.niri.extraSettings = lib.mkIf config.chiasson.desktop.niri.enable {
input.touch.map-to-output = "DSI-1";
# Required for logind's `HandlePowerKey` in `_private/platform.nix` to take effect: otherwise
# niri grabs a `block` inhibitor on `handle-power-key` and suspends via D-Bus, including on
# the EC's wake-from-suspend KEY_POWER event → instant re-suspend loop.
# https://github.com/niri-wm/niri/issues/2233
input."disable-power-key-handling" = _: { };
# wrapper-modules schema: each entry is a `command argv` list of strings (or a single string).
spawn-at-startup = [
[ "ideapad-niri-autorotate-daemon" ]