Files
nix-config/home/panotaka/common/optional/desktops/niri/zenbook-screen.nix

293 lines
11 KiB
Nix

{pkgs, ...}: let
# Configuration variables from your script
preferred_resolution = "2880x1800";
refresh_rate = "120";
ui_scale = "1.5";
y_offset = "1200";
# Debug script
zenbook-debug = pkgs.writeShellScriptBin "zenbook-debug" ''
echo "=== Zenbook Duo Debug Info ==="
echo ""
echo "1. USB Devices:"
echo " Looking for keyboard (0b05:1b2c)..."
${pkgs.usbutils}/bin/lsusb | grep 0b05:1b2c && echo " Keyboard USB ID found!" || echo " Keyboard USB ID NOT found"
echo ""
echo " All ASUS devices:"
${pkgs.usbutils}/bin/lsusb | grep -i asus || echo " (none)"
echo ""
echo " Full lsusb output:"
${pkgs.usbutils}/bin/lsusb
echo ""
echo "2. Niri Outputs:"
${pkgs.niri}/bin/niri msg outputs || echo " ERROR: Could not get niri outputs"
echo ""
echo "3. Systemd Services:"
systemctl --user status zenbook-autostart 2>&1 | head -3 || echo " Not found"
systemctl --user status zenbook-inotify-monitor 2>&1 | head -3 || echo " Not found"
echo ""
echo "4. Log Files:"
[ -f /tmp/zenbook-lsusb.log ] && cat /tmp/zenbook-lsusb.log || echo " (no log file yet)"
echo ""
echo "5. Manual Test Commands:"
echo " - zenbook-normal # Run keyboard detection"
echo " - zenbook-top # Force top screen only"
echo " - zenbook-both # Force both screens"
echo " - journalctl --user -u zenbook-inotify-monitor -f # Watch logs"
'';
# Inline scripts adapted for niri
# Stage 3: Configuration - applies the display setup
zenbook-top = pkgs.writeShellScriptBin "zenbook-top" ''
echo "[DEBUG] zenbook-top: Setting to top screen only"
echo "[DEBUG] Configuring eDP-1..."
${pkgs.niri}/bin/niri msg output eDP-1 on || echo "[ERROR] Failed to turn on eDP-1"
${pkgs.niri}/bin/niri msg output eDP-1 mode ${preferred_resolution}@${refresh_rate} || echo "[ERROR] Failed to set eDP-1 mode"
${pkgs.niri}/bin/niri msg output eDP-1 scale ${ui_scale} || echo "[ERROR] Failed to set eDP-1 scale"
${pkgs.niri}/bin/niri msg output eDP-1 position set 0 0 || echo "[ERROR] Failed to set eDP-1 position"
echo "[DEBUG] Disabling eDP-2..."
${pkgs.niri}/bin/niri msg output eDP-2 off || echo "[ERROR] Failed to turn off eDP-2"
# Force disable by setting power mode off (if supported)
${pkgs.niri}/bin/niri msg output eDP-2 disable 2>/dev/null || echo "[DEBUG] disable command not available, using off"
echo "[DEBUG] zenbook-top: Complete"
'';
zenbook-bottom = pkgs.writeShellScriptBin "zenbook-bottom" ''
echo "Setting to bottom screen only"
${pkgs.niri}/bin/niri msg output eDP-2 on
${pkgs.niri}/bin/niri msg output eDP-2 mode ${preferred_resolution}@${refresh_rate}
${pkgs.niri}/bin/niri msg output eDP-2 scale ${ui_scale}
${pkgs.niri}/bin/niri msg output eDP-2 position set 0 0
${pkgs.niri}/bin/niri msg output eDP-1 off
# Force disable by setting power mode off (if supported)
${pkgs.niri}/bin/niri msg output eDP-1 disable 2>/dev/null || echo "[DEBUG] disable command not available, using off"
'';
zenbook-both = pkgs.writeShellScriptBin "zenbook-both" ''
echo "[DEBUG] zenbook-both: Setting to both screens"
echo "[DEBUG] Configuring eDP-1..."
${pkgs.niri}/bin/niri msg output eDP-1 on || echo "[ERROR] Failed to turn on eDP-1"
${pkgs.niri}/bin/niri msg output eDP-1 mode ${preferred_resolution}@${refresh_rate} || echo "[ERROR] Failed to set eDP-1 mode"
${pkgs.niri}/bin/niri msg output eDP-1 scale ${ui_scale} || echo "[ERROR] Failed to set eDP-1 scale"
${pkgs.niri}/bin/niri msg output eDP-1 position set 0 0 || echo "[ERROR] Failed to set eDP-1 position"
echo "[DEBUG] Configuring eDP-2..."
${pkgs.niri}/bin/niri msg output eDP-2 on || echo "[ERROR] Failed to turn on eDP-2"
${pkgs.niri}/bin/niri msg output eDP-2 mode ${preferred_resolution}@${refresh_rate} || echo "[ERROR] Failed to set eDP-2 mode"
${pkgs.niri}/bin/niri msg output eDP-2 scale ${ui_scale} || echo "[ERROR] Failed to set eDP-2 scale"
${pkgs.niri}/bin/niri msg output eDP-2 position set 0 ${y_offset} || echo "[ERROR] Failed to set eDP-2 position"
echo "[DEBUG] zenbook-both: Complete"
'';
zenbook-left-up = pkgs.writeShellScriptBin "zenbook-left-up" ''
echo "Setting to left-right layout"
${pkgs.niri}/bin/niri msg output eDP-2 on
${pkgs.niri}/bin/niri msg output eDP-2 mode ${preferred_resolution}@${refresh_rate}
${pkgs.niri}/bin/niri msg output eDP-2 scale ${ui_scale}
${pkgs.niri}/bin/niri msg output eDP-2 position set 0 0
${pkgs.niri}/bin/niri msg output eDP-1 on
${pkgs.niri}/bin/niri msg output eDP-1 mode ${preferred_resolution}@${refresh_rate}
${pkgs.niri}/bin/niri msg output eDP-1 scale ${ui_scale}
${pkgs.niri}/bin/niri msg output eDP-1 position set ${y_offset} 0
'';
zenbook-right-up = pkgs.writeShellScriptBin "zenbook-right-up" ''
echo "Setting to right-left layout"
${pkgs.niri}/bin/niri msg output eDP-1 on
${pkgs.niri}/bin/niri msg output eDP-1 mode ${preferred_resolution}@${refresh_rate}
${pkgs.niri}/bin/niri msg output eDP-1 scale ${ui_scale}
${pkgs.niri}/bin/niri msg output eDP-1 position set 0 0
${pkgs.niri}/bin/niri msg output eDP-2 on
${pkgs.niri}/bin/niri msg output eDP-2 mode ${preferred_resolution}@${refresh_rate}
${pkgs.niri}/bin/niri msg output eDP-2 scale ${ui_scale}
${pkgs.niri}/bin/niri msg output eDP-2 position set ${y_offset} 0
'';
# Stage 2: Detection - determines which configuration to apply
zenbook-detect = pkgs.writeShellScriptBin "zenbook-detect" ''
# Simple keyboard detection based on the original duo script
echo "[DEBUG] zenbook-detect: Starting detection"
echo "[DEBUG] Running lsusb to find keyboard..."
${pkgs.usbutils}/bin/lsusb > /tmp/zenbook-lsusb.log
echo "[DEBUG] lsusb output saved to /tmp/zenbook-lsusb.log"
# Check if keyboard is attached (USB device ID 0b05:1b2c)
if ${pkgs.usbutils}/bin/lsusb | grep -q 0b05:1b2c; then
echo "[DEBUG] Keyboard detected (0b05:1b2c found)"
echo "Keyboard attached top screen only"
${zenbook-top}/bin/zenbook-top
else
echo "[DEBUG] Keyboard NOT detected (0b05:1b2c not found)"
echo "[DEBUG] Checking for any ASUS devices..."
${pkgs.usbutils}/bin/lsusb | grep -i asus || echo "[DEBUG] No ASUS devices found"
echo "Normal mode both screens"
${zenbook-both}/bin/zenbook-both
fi
'';
# Legacy alias for compatibility
zenbook-normal = pkgs.writeShellScriptBin "zenbook-normal" ''
${zenbook-detect}/bin/zenbook-detect
'';
zenbook-toggle = pkgs.writeShellScriptBin "zenbook-toggle" ''
# Check current state and toggle
enabled_count=$(${pkgs.niri}/bin/niri msg outputs | grep -c "eDP.*" || echo "0")
if [ "$enabled_count" -eq 1 ]; then
${zenbook-both}/bin/zenbook-both
else
${zenbook-top}/bin/zenbook-top
fi
'';
# Stage 1: Watch service - monitors for changes and triggers detection
zenbook-watch-displays = pkgs.writeShellScriptBin "zenbook-watch-displays" ''
echo "[DEBUG] zenbook-watch-displays: Starting"
echo "[DEBUG] Running initial detection"
# Run initial detection
${zenbook-detect}/bin/zenbook-detect
echo "[DEBUG] Starting USB device monitoring on /dev/bus/usb/*/"
# Track last run time to debounce rapid-fire events
last_run=0
debounce_seconds=3
# Watch for USB device changes (keyboard attach/detach)
while ${pkgs.inotify-tools}/bin/inotifywait -e attrib /dev/bus/usb/*/; do
current_time=$(date +%s)
time_diff=$((current_time - last_run))
if [ $time_diff -ge $debounce_seconds ]; then
echo "[DEBUG] USB device change detected at $(date) (debounced)"
sleep 0.5
${zenbook-detect}/bin/zenbook-detect
last_run=$current_time
else
echo "[DEBUG] USB device change ignored (debounce: $time_diff < $debounce_seconds seconds)"
fi
done
'';
# Legacy wrapper - calls detect directly
zenbook-set-displays = pkgs.writeShellScriptBin "zenbook-set-displays" ''
sleep 0.5
${zenbook-detect}/bin/zenbook-detect
'';
# Simplified auto-run display setup on startup (based on original duo approach)
zenbook-autostart = pkgs.writeShellScriptBin "zenbook-autostart" ''
echo "Running initial display setup"
sleep 1
${zenbook-detect}/bin/zenbook-detect
'';
in {
# Zenbook dual-screen display configuration for niri
# NOTE: We only configure eDP-1 statically and let scripts manage eDP-2 dynamically
# This allows the off command to actually work
programs.niri.settings = {
outputs = {
"eDP-1" = {
mode = {
width = 2880;
height = 1800;
refresh = 120.0;
};
scale = 1.5;
position = {
x = 0;
y = 0;
};
variable-refresh-rate = true;
};
# eDP-2 is managed dynamically by zenbook-detect scripts
};
# Keybind to run zenbook-detect via UWSM
binds."Mod+Z".action.spawn = ["uwsm" "app" "--" "${zenbook-detect}/bin/zenbook-detect"];
};
# Migrate to systemd user services for UWSM integration
systemd.user.services = {
# Initial display setup
zenbook-autostart = {
Unit = {
Description = "ZenBook Duo Initial Display Setup";
After = ["graphical-session.target"];
PartOf = ["graphical-session.target"];
};
Service = {
Type = "oneshot";
ExecStart = "${zenbook-autostart}/bin/zenbook-autostart";
RemainAfterExit = false;
};
Install = {
WantedBy = ["graphical-session.target"];
};
};
# Secondary display setup after delay
zenbook-delayed-setup = {
Unit = {
Description = "ZenBook Duo Delayed Display Setup";
After = ["graphical-session.target" "zenbook-autostart.service"];
PartOf = ["graphical-session.target"];
};
Service = {
Type = "oneshot";
ExecStartPre = "${pkgs.coreutils}/bin/sleep 5";
ExecStart = "${zenbook-set-displays}/bin/zenbook-set-displays";
RemainAfterExit = false;
};
Install = {
WantedBy = ["graphical-session.target"];
};
};
# Monitor USB device changes for keyboard attach/detach
zenbook-inotify-monitor = {
Unit = {
Description = "ZenBook Duo USB Device Monitor";
After = ["graphical-session.target"];
PartOf = ["graphical-session.target"];
};
Service = {
Type = "simple";
ExecStart = "${zenbook-watch-displays}/bin/zenbook-watch-displays";
Restart = "always";
RestartSec = "5";
};
Install = {
WantedBy = ["graphical-session.target"];
};
};
# DISABLED: udev monitor - not needed with inotify approach
# zenbook-udev-monitor service removed to prevent conflicts
};
# DISABLED: swayidle hook was running zenbook-detect every second, causing conflicts
# The zenbook-inotify-monitor service handles USB detection automatically
# services.swayidle.timeouts = lib.mkAfter [
# {
# timeout = 1;
# command = "${zenbook-detect}/bin/zenbook-detect";
# resumeCommand = "${zenbook-detect}/bin/zenbook-detect";
# }
# ];
# Add the scripts to home packages
home.packages = [
zenbook-debug
zenbook-top
zenbook-bottom
zenbook-both
zenbook-left-up
zenbook-right-up
zenbook-detect
zenbook-normal
zenbook-toggle
zenbook-watch-displays
zenbook-set-displays
zenbook-autostart
];
}