293 lines
11 KiB
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
|
|
];
|
|
}
|