chore: initialize gentoo-setup documentation repository
Add comprehensive documentation for Lenovo ThinkPad Gentoo Linux setup including: - Complete system configuration guides (power, Bluetooth, WiFi, audio) - Hardware setup documentation (touchpad, touchscreen, DisplayLink) - Management scripts with ZSH completions - Kernel configuration (6.12.41-gentoo-x86_64) - Lid automation and monitor management - Battery conservation system - User guides and troubleshooting Repository includes .gitignore to exclude logs, temporary files, and secrets. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
427
Lid-Automation-Implementation.md
Normal file
427
Lid-Automation-Implementation.md
Normal file
@@ -0,0 +1,427 @@
|
||||
# Lid Automation with Suspend/Resume
|
||||
|
||||
## Overview
|
||||
|
||||
Automated lid handling system that intelligently manages displays and power states based on whether external monitors are connected. Provides seamless docking/undocking experience with proper suspend/resume support.
|
||||
|
||||
## Requirements Met
|
||||
|
||||
Based on `Lid-Functionality.md` specifications:
|
||||
|
||||
- ✅ **Lid closed + external monitors** → Laptop screen turns off, external monitors stay active
|
||||
- ✅ **Lid closed + no external monitors** → System suspends to sleep
|
||||
- ✅ **Lid opens from sleep** → System resumes and restores monitors
|
||||
- ✅ **Lid opens + external monitors** → Three-monitor mode (2 external + laptop)
|
||||
- ✅ **Dock disconnected** → Automatically switches to mobile-only mode
|
||||
- ✅ **Dock connected** → Auto-detects and enables external monitors
|
||||
- ✅ **Waybar restart** → Automatically restarts on monitor configuration changes
|
||||
- ✅ **Multi-location support** → Handles different monitor configurations
|
||||
|
||||
## Architecture
|
||||
|
||||
The system consists of three components:
|
||||
|
||||
```
|
||||
ACPI Event (lid open/close)
|
||||
↓
|
||||
/etc/acpi/lid.sh (ACPI handler)
|
||||
↓
|
||||
/usr/local/bin/lid-handler.sh (Decision logic)
|
||||
↓
|
||||
├→ External monitors present → Monitor reconfiguration
|
||||
└→ No external monitors → System suspend
|
||||
↓
|
||||
/lib/elogind/system-sleep/hyprland-resume
|
||||
↓
|
||||
Monitor reconfiguration on wake
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### 1. ACPI Lid Event Handler
|
||||
|
||||
**File**: `/etc/acpi/lid.sh`
|
||||
|
||||
**Purpose**: Receives lid open/close events from ACPI daemon
|
||||
|
||||
**Function**: Minimal event handler that delegates to the comprehensive lid handler without blocking acpid
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Simply delegate to comprehensive handler
|
||||
/usr/local/bin/lid-handler.sh &
|
||||
exit 0
|
||||
```
|
||||
|
||||
**Why this design:**
|
||||
- ACPI handlers should return quickly
|
||||
- Running handler in background prevents blocking acpid
|
||||
- Keeps ACPI config simple and maintainable
|
||||
|
||||
### 2. Comprehensive Lid Handler
|
||||
|
||||
**File**: `/usr/local/bin/lid-handler.sh`
|
||||
|
||||
**Purpose**: Intelligent decision-making for lid events
|
||||
|
||||
**Logic Flow:**
|
||||
|
||||
1. **Detect lid state** from `/proc/acpi/button/lid/*/state`
|
||||
2. **Check for Hyprland** and set up environment
|
||||
3. **Count external monitors** using `hyprctl monitors`
|
||||
4. **Make decision:**
|
||||
|
||||
**If lid is CLOSED:**
|
||||
- External monitors present → Disable laptop screen only
|
||||
- No external monitors → Trigger suspend via `loginctl suspend`
|
||||
|
||||
**If lid is OPEN:**
|
||||
- Reconfigure all monitors (handled by monitor-setup.sh)
|
||||
|
||||
**Key Features:**
|
||||
- Properly sets Hyprland environment variables for `hyprctl` to work
|
||||
- Logs all actions to `/tmp/lid-handler.log`
|
||||
- Uses `loginctl suspend` (elogind) for proper suspend handling
|
||||
- Non-blocking execution
|
||||
|
||||
**Environment Setup:**
|
||||
```bash
|
||||
export HYPRLAND_INSTANCE_SIGNATURE=$(ls -t /tmp/hypr/ | head -n1)
|
||||
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
|
||||
export WAYLAND_DISPLAY="wayland-0"
|
||||
```
|
||||
|
||||
### 3. elogind Resume Hook
|
||||
|
||||
**File**: `/lib/elogind/system-sleep/hyprland-resume`
|
||||
|
||||
**Purpose**: Restores monitor configuration after waking from suspend
|
||||
|
||||
**Execution**: Automatically called by elogind with two arguments:
|
||||
- `$1 = "pre"` before suspend, `"post"` after resume
|
||||
- `$2 = "suspend"`, `"hibernate"`, or `"hybrid-sleep"`
|
||||
|
||||
**On Resume (post):**
|
||||
1. Wait 2 seconds for system to stabilize
|
||||
2. Find user running Hyprland
|
||||
3. Execute monitor-setup.sh as that user
|
||||
4. Log all actions
|
||||
|
||||
**Why this is needed:**
|
||||
- Monitors may disconnect/reconnect during suspend
|
||||
- DisplayLink dock needs re-initialization after resume
|
||||
- Waybar needs restart to update status bar for new monitor layout
|
||||
|
||||
**Logs**: `/tmp/elogind-sleep.log`
|
||||
|
||||
### 4. Monitor Setup Script
|
||||
|
||||
**File**: `/home/alexander/.config/hypr/scripts/monitor-setup.sh`
|
||||
|
||||
**Purpose**: Central script for all monitor configuration
|
||||
|
||||
**Called by:**
|
||||
- Lid handler (when lid state changes)
|
||||
- Resume hook (when waking from suspend)
|
||||
- DisplayLink hotplug (when dock connects/disconnects)
|
||||
|
||||
**Already implemented** and working correctly.
|
||||
|
||||
## Installation
|
||||
|
||||
All scripts are prepared in `/tmp/`. To install:
|
||||
|
||||
```bash
|
||||
su -
|
||||
/tmp/install-lid-automation.sh
|
||||
exit
|
||||
```
|
||||
|
||||
**What the installer does:**
|
||||
1. Copies lid handler to `/usr/local/bin/`
|
||||
2. Creates elogind sleep hook directory if needed
|
||||
3. Installs resume hook in `/lib/elogind/system-sleep/`
|
||||
4. Replaces ACPI lid handler in `/etc/acpi/lid.sh`
|
||||
5. Restarts acpid service to activate changes
|
||||
|
||||
## Testing
|
||||
|
||||
### Test 1: Lid Close with External Monitors
|
||||
|
||||
**Procedure:**
|
||||
1. Connect USB-C dock with external monitors
|
||||
2. Verify external monitors are working
|
||||
3. Close laptop lid
|
||||
|
||||
**Expected Result:**
|
||||
- Laptop screen turns off immediately
|
||||
- External monitors continue working
|
||||
- No system suspend
|
||||
|
||||
**Verify:**
|
||||
```bash
|
||||
tail -f /tmp/lid-handler.log
|
||||
```
|
||||
Should show: "External monitors detected" and "Disable laptop screen"
|
||||
|
||||
### Test 2: Lid Close without External Monitors
|
||||
|
||||
**Procedure:**
|
||||
1. Disconnect USB-C dock
|
||||
2. Verify only laptop screen is active
|
||||
3. Close laptop lid
|
||||
|
||||
**Expected Result:**
|
||||
- System suspends within 1 second
|
||||
- Power LED should blink (suspend indicator)
|
||||
|
||||
**Verify:**
|
||||
After waking, check logs:
|
||||
```bash
|
||||
tail /tmp/lid-handler.log
|
||||
```
|
||||
Should show: "No external monitors" and "suspending system"
|
||||
|
||||
### Test 3: Resume from Suspend
|
||||
|
||||
**Procedure:**
|
||||
1. With laptop suspended (from Test 2)
|
||||
2. Open laptop lid
|
||||
|
||||
**Expected Result:**
|
||||
- System wakes immediately
|
||||
- Laptop screen turns on
|
||||
- Login prompt appears
|
||||
- Monitors restore to correct configuration
|
||||
|
||||
**Verify:**
|
||||
```bash
|
||||
tail /tmp/elogind-sleep.log
|
||||
```
|
||||
Should show: "Waking from sleep" and "Monitor reconfiguration triggered"
|
||||
|
||||
### Test 4: Three-Monitor Mode
|
||||
|
||||
**Procedure:**
|
||||
1. Connect USB-C dock with external monitors
|
||||
2. Open laptop lid (if closed)
|
||||
|
||||
**Expected Result:**
|
||||
- Two external monitors: 2560x1440@60Hz side-by-side at top
|
||||
- Laptop monitor: 2880x1800@120Hz centered below
|
||||
- All three monitors active simultaneously
|
||||
|
||||
**Verify:**
|
||||
```bash
|
||||
hyprctl monitors
|
||||
```
|
||||
Should show 3 active monitors: eDP-1, DVI-I-1, DVI-I-2
|
||||
|
||||
### Test 5: Dock Hotplug
|
||||
|
||||
**Procedure:**
|
||||
1. With laptop lid open, disconnect USB-C dock
|
||||
2. Wait 2-3 seconds
|
||||
3. Reconnect USB-C dock
|
||||
|
||||
**Expected Result:**
|
||||
- On disconnect: Switches to laptop-only mode
|
||||
- On reconnect: External monitors appear and configure automatically
|
||||
- Waybar restarts on each change
|
||||
|
||||
**Verify:**
|
||||
```bash
|
||||
tail -f /tmp/displaylink-hotplug.log
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Lid close doesn't suspend
|
||||
|
||||
**Check:**
|
||||
```bash
|
||||
cat /etc/elogind/logind.conf | grep HandleLidSwitch
|
||||
```
|
||||
|
||||
Should show:
|
||||
```
|
||||
HandleLidSwitch=ignore
|
||||
HandleLidSwitchExternalPower=ignore
|
||||
HandleLidSwitchDocked=ignore
|
||||
```
|
||||
|
||||
Our script handles lid logic, not elogind. This is correct.
|
||||
|
||||
**Test suspend manually:**
|
||||
```bash
|
||||
loginctl suspend
|
||||
```
|
||||
|
||||
If this doesn't work, check:
|
||||
```bash
|
||||
cat /sys/power/state
|
||||
```
|
||||
Should include `mem` or `s2idle`.
|
||||
|
||||
### Monitors don't restore after resume
|
||||
|
||||
**Check logs:**
|
||||
```bash
|
||||
tail -20 /tmp/elogind-sleep.log
|
||||
tail -20 /tmp/hyprland-monitor-setup.log
|
||||
```
|
||||
|
||||
**Common issues:**
|
||||
- DisplayLink dock needs 2-3 seconds to re-initialize after resume
|
||||
- Increase sleep time in resume hook if needed
|
||||
|
||||
**Manual test:**
|
||||
After resume, run:
|
||||
```bash
|
||||
~/.config/hypr/scripts/monitor-setup.sh
|
||||
```
|
||||
|
||||
### ACPI lid events not triggering
|
||||
|
||||
**Check acpid is running:**
|
||||
```bash
|
||||
rc-status | grep acpid
|
||||
```
|
||||
|
||||
**Test ACPI events:**
|
||||
```bash
|
||||
# Clear log
|
||||
> /tmp/lid-handler.log
|
||||
|
||||
# Close lid, wait, open lid
|
||||
|
||||
# Check log
|
||||
cat /tmp/lid-handler.log
|
||||
```
|
||||
|
||||
If no entries, check ACPI event:
|
||||
```bash
|
||||
acpi_listen
|
||||
# Close and open lid - should see events
|
||||
```
|
||||
|
||||
## Logs
|
||||
|
||||
All components log their actions:
|
||||
|
||||
| Log File | What It Contains |
|
||||
|----------|------------------|
|
||||
| `/tmp/lid-handler.log` | Lid event decisions and actions |
|
||||
| `/tmp/elogind-sleep.log` | Suspend/resume events |
|
||||
| `/tmp/hyprland-monitor-setup.log` | Monitor configuration details |
|
||||
| `/tmp/displaylink-hotplug.log` | Dock connection/disconnection |
|
||||
|
||||
**Monitor all logs simultaneously:**
|
||||
```bash
|
||||
tail -f /tmp/lid-handler.log /tmp/elogind-sleep.log /tmp/hyprland-monitor-setup.log
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Single User System
|
||||
|
||||
The system is designed for single-user operation (alexander). The scripts automatically detect the user running Hyprland.
|
||||
|
||||
### Different Monitor Configurations
|
||||
|
||||
The monitor setup script uses `preferred` resolution and auto-positioning. To support different locations (work/home) with different monitors:
|
||||
|
||||
**Option 1: Let it auto-configure** (current approach)
|
||||
- Works for most setups
|
||||
- Monitors use their preferred resolution
|
||||
|
||||
**Option 2: Create location profiles** (future enhancement)
|
||||
- Detect location by monitor serial numbers
|
||||
- Load specific configuration per location
|
||||
- Requires extending monitor-setup.sh
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **elogind**: Session management and suspend/resume
|
||||
- **acpid**: ACPI event handling
|
||||
- **hyprland**: Window manager with hyprctl
|
||||
- **jq**: JSON parsing for monitor queries
|
||||
- **loginctl**: elogind control utility
|
||||
|
||||
All dependencies are already installed and working.
|
||||
|
||||
## Files Modified/Created
|
||||
|
||||
| File | Action | Purpose |
|
||||
|------|--------|---------|
|
||||
| `/usr/local/bin/lid-handler.sh` | Created | Main lid event logic |
|
||||
| `/lib/elogind/system-sleep/hyprland-resume` | Created | Resume hook |
|
||||
| `/etc/acpi/lid.sh` | Replaced | ACPI event entry point |
|
||||
| `/home/alexander/.config/hypr/scripts/monitor-setup.sh` | Already exists | Monitor configuration |
|
||||
|
||||
## Design Decisions
|
||||
|
||||
### Why not let elogind handle lid events?
|
||||
|
||||
**Problem**: elogind's lid handling is all-or-nothing:
|
||||
- `HandleLidSwitch=suspend` → Always suspends (even with external monitors)
|
||||
- `HandleLidSwitch=ignore` → Never suspends (manual suspend only)
|
||||
|
||||
**Solution**: Custom logic that considers external monitor state.
|
||||
|
||||
### Why use loginctl suspend instead of writing to /sys/power/state?
|
||||
|
||||
**Reasons:**
|
||||
- elogind handles pre-suspend tasks (session locking, service notifications)
|
||||
- Proper resume hook execution
|
||||
- Better integration with session management
|
||||
- Logs in journal/syslog
|
||||
|
||||
### Why run handler in background from ACPI?
|
||||
|
||||
**Reasons:**
|
||||
- ACPI handlers should return quickly (< 1 second)
|
||||
- Suspend takes time, would block acpid
|
||||
- Other ACPI events (power button, dock) need to be handled concurrently
|
||||
|
||||
### Why wait 2 seconds on resume?
|
||||
|
||||
**Reasons:**
|
||||
- DisplayLink USB devices need time to re-enumerate
|
||||
- Kernel drivers need to re-initialize
|
||||
- Too fast = monitors not detected yet
|
||||
- Too slow = user sees blank screens longer
|
||||
|
||||
**Tunable**: Adjust sleep time in `/lib/elogind/system-sleep/hyprland-resume` if needed.
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
**1. Monitor Configuration Profiles**
|
||||
- Detect location by monitor serial numbers
|
||||
- Load specific layouts per location
|
||||
- Store in `~/.config/hypr/monitor-profiles/`
|
||||
|
||||
**2. Lock Screen on Suspend**
|
||||
- Integrate with swaylock or gtklock
|
||||
- Lock before suspend, unlock on resume
|
||||
|
||||
**3. Notification on Dock Connect/Disconnect**
|
||||
- Use mako to show notifications
|
||||
- "Dock connected: 2 monitors"
|
||||
- "Switched to mobile mode"
|
||||
|
||||
**4. Faster Resume**
|
||||
- Pre-load DisplayLink configuration
|
||||
- Reduce sleep time by detecting device readiness
|
||||
|
||||
**5. Hibernation Support**
|
||||
- Similar to suspend but saves to disk
|
||||
- Requires swap configuration
|
||||
- Useful for extended battery life
|
||||
|
||||
## References
|
||||
|
||||
- elogind documentation: `/usr/share/doc/elogind-*/`
|
||||
- ACPI specification: https://www.kernel.org/doc/Documentation/acpi/
|
||||
- Original requirements: `Lid-Functionality.md`
|
||||
- Monitor configuration: `Monitor-Dock-via-DisplayLink.md`
|
||||
Reference in New Issue
Block a user