wmctrl
The Python `wmctrl` library (version 0.5) provides a wrapper around the `wmctrl` command-line utility, enabling programmatic control of windows within the X Window System. It allows Python scripts to query window information, activate windows, and perform actions like resizing or moving. The library follows a stable release cadence, with updates typically occurring years apart, reflecting its role as an interface to a mature external tool.
Common errors
-
Cannot open display.
cause The script is running in an environment (e.g., cron, SSH session without X forwarding, as root) where the `DISPLAY` and `XAUTHORITY` environment variables are not correctly set, preventing interaction with the X server.fixSet the `DISPLAY` and `XAUTHORITY` environment variables explicitly before running the script. Example: `export DISPLAY=:0 && export XAUTHORITY=/home/youruser/.Xauthority && python your_script.py`. You might also need `xhost local:root` if running as root. -
subprocess.CalledProcessError: Command 'wmctrl -l' returned non-zero exit status 1.
cause This often indicates that the `wmctrl` command-line utility itself failed. Common reasons include 'Cannot open display.' (see above), or `wmctrl` not being installed, or syntax errors in the command string passed to `subprocess`.fixFirst, check `DISPLAY` and `XAUTHORITY` as described above. Second, ensure the `wmctrl` command-line utility is installed. Third, verify the exact `wmctrl` command works from a regular terminal before embedding it in Python. -
Window not found or not responding to commands (e.g., move, resize, activate) after launching an application.
cause A common race condition where the `wmctrl` command executes before the newly launched application's window is fully created, mapped, and has its properties (like title and ID) available to `wmctrl`.fixIntroduce a small delay (`time.sleep(X)`) after launching the application, or implement a loop that repeatedly calls `get_windows()` (or `wmctrl -lp`) until the target window is detected before attempting further actions.
Warnings
- breaking The Python `wmctrl` library is a wrapper. It requires the separate `wmctrl` command-line utility to be installed on your system (e.g., `sudo apt-get install wmctrl` on Debian/Ubuntu). Without the underlying utility, the Python library will not function.
- gotcha When launching new applications and immediately attempting to manipulate their windows (e.g., move, resize, activate), you may encounter timing issues where `wmctrl` acts before the window is fully initialized or its title is set. This can lead to commands failing or targeting the wrong window.
- gotcha `wmctrl` operations might fail with 'Cannot open display.' errors when run from non-interactive environments like cron jobs or as root. This occurs because the `DISPLAY` and `XAUTHORITY` environment variables, necessary for X11 interaction, are not set or are incorrect in these contexts.
- gotcha `wmctrl` may not reliably bring windows on top of applications running in fullscreen mode, especially if those applications hide window borders and decorations.
Install
-
pip install wmctrl -
sudo apt-get install wmctrl # For Debian/Ubuntu sudo dnf install wmctrl # For Fedora
Imports
- Window
from wmctrl import Window, get_windows, get_active_window
Quickstart
import os
from wmctrl import get_windows, get_active_window
# Ensure wmctrl command-line utility is installed
if os.system('which wmctrl > /dev/null') != 0:
print("Error: 'wmctrl' command-line utility not found. Please install it.")
print("e.g., sudo apt-get install wmctrl (Debian/Ubuntu)")
exit(1)
print("--- Active Window ---")
active_window = get_active_window()
if active_window:
print(f"ID: {active_window.id}, Name: {active_window.wm_name}, Class: {active_window.wm_class}")
else:
print("No active window found.")
print("\n--- All Windows ---")
windows = get_windows()
if windows:
for w in windows:
print(f"ID: {w.id}, Desktop: {w.desktop}, Name: {w.wm_name[:40]}...")
else:
print("No windows found.")
# Example of activating a specific window by its name (if it exists)
# Note: This is an example, ensure a window with 'Firefox' in its name is open.
firefox_window = next((w for w in windows if 'Firefox' in w.wm_name), None)
if firefox_window:
print(f"\nActivating Firefox window: {firefox_window.wm_name}")
firefox_window.activate()
else:
print("\nFirefox window not found to activate.")
# Example of moving/resizing a window using wmctrl command directly via subprocess
# Requires the window ID (e.g., from an active window or a search)
import subprocess
if active_window:
print(f"\nAttempting to move active window {active_window.id} to 100,100 with size 800x600...")
# Gravity 0, X=100, Y=100, Width=800, Height=600. -1 means keep current.
try:
subprocess.run(['wmctrl', '-ir', active_window.id, '-e', '0,100,100,800,600'], check=True)
print("Window moved/resized (check your desktop).")
except subprocess.CalledProcessError as e:
print(f"Failed to move/resize window: {e}")