Kalmat / PyWinCtl

Cross-Platform module to get info on and control windows on screen
Other
179 stars 19 forks source link

`getActiveWindow` does not work on Linux using dwm #85

Open recluzegeek opened 5 months ago

recluzegeek commented 5 months ago

The getActiveWindow function is not working as expected on Linux systems using the dwm window manager. The function is expected to return the title of the currently active window, but instead, it's throwing an error.

Here's the code that I'm trying to run:


import pywinctl as pwc
import time
def get_active_window_title():
    # Get the active window
    active_window = pwc.getActiveWindow()
    if active_window:
        # Get the title of the active window
        return active_window.title
    else:
        return "No active window found"

# Example usage
while True:
    print(get_active_window_title())
    time.sleep(3)

Here's the error message:


Traceback (most recent call last):
  File <file_path>, line 18, in <module>
    print(get_active_window_title())
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File <file_path>, line 9, in get_active_window_title
    active_window = pwc.getActiveWindow()
                    ^^^^^^^^^^^^^^^^^^^^^
  File ".../lib/python3.11/site-packages/pywinctl/_pywinctl_linux.py", line 84, in getActiveWindow
    return LinuxWindow(win_id)
           ^^^^^^^^^^^^^^^^^^^
  File ".../lib/python3.11/site-packages/pywinctl/_pywinctl_linux.py", line 317, in __init__
    super().__init__(hWnd)
  File ".../lib/python3.11/site-packages/pywinctl/_main.py", line 21, in __init__
    self._box: PyWinBox = PyWinBox(None, None, handle)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../lib/python3.11/site-packages/pywinbox/_main.py", line 86, in __init__
    self._handle = _getHandle(handle) if handle is not None else None
                   ^^^^^^^^^^^^^^^^^^
  File ".../lib/python3.11/site-packages/pywinbox/_pywinbox_linux.py", line 19, in _getHandle
    newHandle = EwmhWindow(handle)
                ^^^^^^^^^^^^^^^^^^
  File ".../lib/python3.11/site-packages/ewmhlib/_ewmhlib.py", line 1047, in __init__
    self._currDesktop = os.environ['XDG_CURRENT_DESKTOP'].lower()
                        ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen os>", line 679, in __getitem__
KeyError: 'XDG_CURRENT_DESKTOP'

I've fixed on my system by adding this code to top of my file


import os

os.environ['XDG_CURRENT_DESKTOP'] = 'dwm'

It's working for now, but exhibits strange behavior, logs No active window found for the windows where this file is being executed — pycharm in this case


Skype - Google Chrome
Skype - Google Chrome
Skype - Google Chrome
recluzegeek@alpha:~
DBeaver 24.0.0 - screenshots 
DBeaver 24.0.0 - screenshots 
DBeaver 24.0.0 - screenshots 
recluzegeek@alpha:~
recluzegeek@alpha:~
New Issue · Kalmat/PyWinCtl — LibreWolf
New Issue · Kalmat/PyWinCtl — LibreWolf
recluzegeek@alpha:~
New Issue · Kalmat/PyWinCtl — LibreWolf
No active window found
No active window found
No active window found
New Issue · Kalmat/PyWinCtl — LibreWolf
No active window found
No active window found
Traceback (most recent call last):
  File "/mnt/win/cedar/cedar-workfolio-desktop-app/src/active_window.py", line 19, in <module>
    # Example usage
        ^^^^^^^^^^^^
KeyboardInterrupt

Process finished with exit code 130 (interrupted by signal 2:SIGINT)

I'm developing an desktop app to keep track of my system usage and it'll be annoying to set up XDG_CURRENT_DESKTOP key manually for all other window managers.

Kalmat commented 5 months ago

Hi! Thank you for your feedback!

Sorry I don't know about DWM. As I could find, it is not EWMH-compliant. Since PyWinCtl heavily relies in EWMH protocol, it will not likely work or, in the best case, some issues will arise. Not sure, but I think that DWM uses a very specific and privative control protocol called dwmfifo instead.

As I could also find, there is a DWM fork called awesome which adds support for EWMH, amongst other features like XCB or Lua. Is it possible you switch to this one?

Thanks again!