PyWinCtl icon indicating copy to clipboard operation
PyWinCtl copied to clipboard

`getActiveWindow` does not work on Linux using dwm

Open recluzegeek opened this issue 1 year ago • 1 comments

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.

recluzegeek avatar Mar 13 '24 06:03 recluzegeek

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.

  • The issue regarding XDG_CURRENT_DESKTOP is already fixed in next version (assuming empty instead of crashing, but not sure if this will work in your case. I mean, it is not filling it with 'dwm' nor any other value).
  • About the second crash, it is outside PyWinCtl module. No idea about where, to be honest. Most likely it is because of DWM not being compliat with EWMH specs.

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!

Kalmat avatar Mar 13 '24 08:03 Kalmat