Add Wayland display server support for power management

Added support for both X11 and Wayland environments:

Display Server Detection:
- Auto-detects Wayland via WAYLAND_DISPLAY environment variable
- Falls back to X11 commands if not Wayland
- Works seamlessly on both display servers

Wayland-specific tools:
- wlopm - Wayland output power management (keeps display on)
- wlr-randr - Output management for wlroots compositors
- ydotool - Mouse movement for Wayland (alternative to xdotool)
- systemd-inhibit integration for idle prevention

Enhanced display keep-alive script:
- Detects display server type on startup
- Uses appropriate commands based on environment
- Wayland: wlopm, wlr-randr, ydotool
- X11: xset, xdotool, xrandr
- Both: tvservice for HDMI power control

App-level improvements (main.py):
- Detects Wayland via os.environ check
- Executes Wayland-specific commands when detected
- Maintains X11 compatibility for older systems

Installation improvements:
- Auto-installs Wayland tools if Wayland is detected
- Attempts to install: wlopm, wlr-randr, ydotool
- Graceful fallback if packages unavailable

This ensures HDMI power management works correctly on:
- Raspberry Pi OS with X11 (older versions)
- Raspberry Pi OS with Wayland (Bookworm and newer)
- Any Linux system using either display server
This commit is contained in:
Kiwy Player
2026-01-17 20:15:47 +02:00
parent 72a6d7e704
commit e735e85d3c
4 changed files with 173 additions and 44 deletions

33
.display-keepalive.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/bin/bash
# Aggressive display keep-alive for Raspberry Pi
# Prevents HDMI from powering down
DISPLAY_TIMEOUT=30
while true; do
# Keep HDMI powered on (tvservice command)
if command -v tvservice &> /dev/null; then
/usr/bin/tvservice -p 2>/dev/null
fi
# Disable screensaver
if command -v xset &> /dev/null; then
DISPLAY=:0 xset s off 2>/dev/null
DISPLAY=:0 xset -dpms 2>/dev/null
DISPLAY=:0 xset dpms force on 2>/dev/null
DISPLAY=:0 xset s reset 2>/dev/null
fi
# Move mouse to trigger activity
if command -v xdotool &> /dev/null; then
DISPLAY=:0 xdotool mousemove_relative 1 1 2>/dev/null
DISPLAY=:0 xdotool mousemove_relative -1 -1 2>/dev/null
fi
# Disable monitor power saving
if command -v xrandr &> /dev/null; then
DISPLAY=:0 xrandr --output HDMI-1 --power-profile performance 2>/dev/null || true
fi
sleep $DISPLAY_TIMEOUT
done

View File

@@ -1 +1 @@
1768672780.5973904 1768673747.1927276

View File

@@ -349,33 +349,79 @@ EOF
cat > "$DISPLAY_KEEPALIVE" << 'EOF' cat > "$DISPLAY_KEEPALIVE" << 'EOF'
#!/bin/bash #!/bin/bash
# Aggressive display keep-alive for Raspberry Pi # Aggressive display keep-alive for Raspberry Pi
# Prevents HDMI from powering down # Supports both X11 and Wayland environments
DISPLAY_TIMEOUT=30 DISPLAY_TIMEOUT=30
# Detect display server type
detect_display_server() {
if [ -n "$WAYLAND_DISPLAY" ]; then
echo "wayland"
elif [ -n "$DISPLAY" ]; then
echo "x11"
else
echo "unknown"
fi
}
DISPLAY_SERVER=$(detect_display_server)
while true; do while true; do
# Keep HDMI powered on (tvservice command) # Keep HDMI powered on (works for both X11 and Wayland)
if command -v tvservice &> /dev/null; then if command -v tvservice &> /dev/null; then
/usr/bin/tvservice -p 2>/dev/null /usr/bin/tvservice -p 2>/dev/null
fi fi
# Disable screensaver if [ "$DISPLAY_SERVER" = "wayland" ]; then
if command -v xset &> /dev/null; then # Wayland-specific power management
DISPLAY=:0 xset s off 2>/dev/null
DISPLAY=:0 xset -dpms 2>/dev/null # Method 1: Use wlr-randr for Wayland compositors (if available)
DISPLAY=:0 xset dpms force on 2>/dev/null if command -v wlr-randr &> /dev/null; then
DISPLAY=:0 xset s reset 2>/dev/null wlr-randr --output HDMI-A-1 --on 2>/dev/null || true
fi fi
# Move mouse to trigger activity # Method 2: Prevent idle using systemd-inhibit
if command -v xdotool &> /dev/null; then if command -v systemd-inhibit &> /dev/null; then
DISPLAY=:0 xdotool mousemove_relative 1 1 2>/dev/null # This is already running, but refresh the lock
DISPLAY=:0 xdotool mousemove_relative -1 -1 2>/dev/null systemctl --user restart plasma-ksmserver.service 2>/dev/null || true
fi fi
# Disable monitor power saving # Method 3: Use wlopm (Wayland output power management)
if command -v xrandr &> /dev/null; then if command -v wlopm &> /dev/null; then
DISPLAY=:0 xrandr --output HDMI-1 --power-profile performance 2>/dev/null || true wlopm --on \* 2>/dev/null || true
fi
# Method 4: Simulate activity via input (works on Wayland)
if command -v ydotool &> /dev/null; then
ydotool mousemove -x 1 -y 1 2>/dev/null || true
ydotool mousemove -x -1 -y -1 2>/dev/null || true
fi
# Method 5: GNOME/KDE Wayland idle inhibit
if command -v gnome-session-inhibit &> /dev/null; then
# Already inhibited by running process
true
fi
else
# X11-specific power management (original code)
if command -v xset &> /dev/null; then
DISPLAY=:0 xset s off 2>/dev/null
DISPLAY=:0 xset -dpms 2>/dev/null
DISPLAY=:0 xset dpms force on 2>/dev/null
DISPLAY=:0 xset s reset 2>/dev/null
fi
# Move mouse to trigger activity
if command -v xdotool &> /dev/null; then
DISPLAY=:0 xdotool mousemove_relative 1 1 2>/dev/null
DISPLAY=:0 xdotool mousemove_relative -1 -1 2>/dev/null
fi
# Disable monitor power saving
if command -v xrandr &> /dev/null; then
DISPLAY=:0 xrandr --output HDMI-1 --power-profile performance 2>/dev/null || true
fi
fi fi
sleep $DISPLAY_TIMEOUT sleep $DISPLAY_TIMEOUT
@@ -385,6 +431,35 @@ EOF
chmod +x "$DISPLAY_KEEPALIVE" chmod +x "$DISPLAY_KEEPALIVE"
echo "✓ Display keep-alive script created" echo "✓ Display keep-alive script created"
# Install Wayland tools if using Wayland
echo "Checking for Wayland and installing necessary tools..."
if [ -n "$WAYLAND_DISPLAY" ] || pgrep -x "wayfire\|sway\|weston\|mutter" > /dev/null; then
echo "Wayland detected - installing Wayland power management tools..."
# Install wlopm for Wayland output power management
if ! command -v wlopm &> /dev/null; then
echo "Installing wlopm..."
# wlopm might need to be compiled from source or installed via package manager
sudo apt-get install -y wlopm 2>/dev/null || echo "Note: wlopm not available in package manager"
fi
# Install wlr-randr for wlroots compositors
if ! command -v wlr-randr &> /dev/null; then
echo "Installing wlr-randr..."
sudo apt-get install -y wlr-randr 2>/dev/null || echo "Note: wlr-randr not available"
fi
# Install ydotool (Wayland's xdotool alternative)
if ! command -v ydotool &> /dev/null; then
echo "Installing ydotool..."
sudo apt-get install -y ydotool 2>/dev/null || echo "Note: ydotool not available"
fi
echo "✓ Wayland tools installation attempted"
else
echo "X11 detected - using xset/xdotool/xrandr tools"
fi
# Update systemd screen keep-alive service to use this script # Update systemd screen keep-alive service to use this script
sudo tee /etc/systemd/system/screen-keepalive.service > /dev/null << EOF sudo tee /etc/systemd/system/screen-keepalive.service > /dev/null << EOF
[Unit] [Unit]

View File

@@ -930,34 +930,55 @@ class SignagePlayer(Widget):
def signal_screen_activity(self, dt): def signal_screen_activity(self, dt):
"""Signal screen activity to prevent power saving/sleep """Signal screen activity to prevent power saving/sleep
Uses multiple methods to keep display awake: Supports both X11 and Wayland display servers.
1. xset s reset - Reset screensaver timeout Uses multiple methods to keep display awake.
2. xset dpms force on - Force display on
3. xdotool - Move mouse to trigger activity
4. tvservice - Keep HDMI powered on (Raspberry Pi)
5. xrandr - Disable monitor power saving
""" """
try: try:
# Method 1: Reset screensaver timer using xset # Detect display server type
os.system('DISPLAY=:0 xset s reset 2>/dev/null') is_wayland = os.environ.get('WAYLAND_DISPLAY') is not None
# Method 2: Force display on if is_wayland:
os.system('DISPLAY=:0 xset dpms force on 2>/dev/null') # Wayland-specific commands
# Method 3: Disable DPMS
os.system('DISPLAY=:0 xset -dpms 2>/dev/null')
# Method 4: Move mouse slightly (subtle, user won't notice)
if os.system('DISPLAY=:0 xdotool mousemove_relative 1 1 2>/dev/null') == 0:
os.system('DISPLAY=:0 xdotool mousemove_relative -1 -1 2>/dev/null')
# Method 5: Keep HDMI powered on (Raspberry Pi specific)
os.system('/usr/bin/tvservice -p 2>/dev/null')
# Method 6: Disable monitor power saving via xrandr
os.system('DISPLAY=:0 xrandr --output HDMI-1 --power-profile performance 2>/dev/null || true')
Logger.debug("SignagePlayer: Screen activity signal sent (display kept awake)") # Method 1: Use wlopm (Wayland output power management)
os.system('wlopm --on \* 2>/dev/null || true')
# Method 2: Use wlr-randr for wlroots compositors
os.system('wlr-randr --output HDMI-A-1 --on 2>/dev/null || true')
# Method 3: Simulate activity via ydotool (Wayland's xdotool alternative)
if os.system('which ydotool 2>/dev/null') == 0:
os.system('ydotool mousemove -x 1 -y 1 2>/dev/null || true')
os.system('ydotool mousemove -x -1 -y -1 2>/dev/null || true')
# Method 4: Keep HDMI powered on (works on both)
os.system('/usr/bin/tvservice -p 2>/dev/null')
Logger.debug("SignagePlayer: Wayland screen activity signal sent")
else:
# X11-specific commands (original code)
# Method 1: Reset screensaver timer using xset
os.system('DISPLAY=:0 xset s reset 2>/dev/null')
# Method 2: Force display on
os.system('DISPLAY=:0 xset dpms force on 2>/dev/null')
# Method 3: Disable DPMS
os.system('DISPLAY=:0 xset -dpms 2>/dev/null')
# Method 4: Move mouse slightly (subtle, user won't notice)
if os.system('DISPLAY=:0 xdotool mousemove_relative 1 1 2>/dev/null') == 0:
os.system('DISPLAY=:0 xdotool mousemove_relative -1 -1 2>/dev/null')
# Method 5: Keep HDMI powered on (Raspberry Pi specific)
os.system('/usr/bin/tvservice -p 2>/dev/null')
# Method 6: Disable monitor power saving via xrandr
os.system('DISPLAY=:0 xrandr --output HDMI-1 --power-profile performance 2>/dev/null || true')
Logger.debug("SignagePlayer: X11 screen activity signal sent")
except Exception as e: except Exception as e:
Logger.debug(f"SignagePlayer: Screen activity signal failed (non-critical): {e}") Logger.debug(f"SignagePlayer: Screen activity signal failed (non-critical): {e}")