Skip to content

Commit 8c31306

Browse files
committed
Added WM_NAME as _NET_WM_NAME fallback (older apps)
Separated Props and Structs as submodules Improved performance while maintaining multi-display, multi-screen and multi-root support Added typing_extensions dependency at runtime
1 parent e320b4d commit 8c31306

2 files changed

Lines changed: 27 additions & 14 deletions

File tree

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# EWMH-lib
22
[![Type Checking](https://github.com/Kalmat/EWMHlib/actions/workflows/type-checking.yml/badge.svg)](https://github.com/Kalmat/EWMHlib/actions/workflows/type-checking.yml)
3+
[![PyPI version](https://badge.fury.io/py/ewmhlib.svg)](https://badge.fury.io/py/ewmhlib)
34

45
Extended Window Manager Hints implementation in Python 3 and python-xlib, which allows to easily query and control
56
Window Managers following these standards.
@@ -49,7 +50,7 @@ Class to access application window features.
4950

5051
To instantiate this class only a window id is required. It is possible to retrieve this value in several ways:
5152

52-
- Target a specific window using an external module (e.g. `PyWinCtl.getAllWindowsWithTitle(title)`)
53+
- Target a specific window using an external module (e.g. `pywinctl.getAllWindowsWithTitle(title)` or `pywinctl.getActiveWindow()`)
5354
- Retrieve it from your own application (e.g. PyQt's `winId()` or TKinter's `frame()`)
5455

5556
Note that, although a root is also a window, most of these methods will not likely work with it.
@@ -173,9 +174,9 @@ or
173174

174175
python3 -m pip install ewmhlib
175176

176-
Alternatively, you can download the wheel file (.whl) available in the [Download page](https://pypi.org/project/EWMHlib/#files) and the [dist folder](https://github.com/Kalmat/EWMHlib/tree/master/dist), and run this (don't forget to replace 'x.x.xx' with proper version number):
177+
Alternatively, you can download the wheel file (.whl) available in the [Download page](https://pypi.org/project/EWMHlib/#files) and the [dist folder](https://github.com/Kalmat/EWMHlib/tree/master/dist), and run this (don't forget to replace 'x.xx' with proper version number):
177178

178-
pip install EWMHlib-x.x.xx-py3-none-any.whl
179+
pip install EWMHlib-x.xx-py3-none-any.whl
179180

180181
You may want to add `--force-reinstall` option to be sure you are installing the right dependencies version.
181182

@@ -250,6 +251,9 @@ An (likely) incomplete list of EWMH-compliant window managers is (via Wikipedia,
250251
| xmonad | (4) |
251252

252253
(1) Through 0.65 / from 0.70
254+
253255
(2) As of 4.0.0
256+
254257
(3) Releases following and including version 1.1.0 follow the EWMH standard
258+
255259
(4) Must activate EWMH (XMonad.Hooks.EwmhDesktops)

src/ewmhlib/_ewmhlib.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import os
1010
import threading
1111
import time
12-
from typing import Optional, cast, Callable, Union, List, Tuple, Iterable
12+
from typing import Optional, cast, Callable, Union, List, Tuple
1313

1414
import Xlib.display
1515
import Xlib.protocol
@@ -258,28 +258,37 @@ def getPropertyValue(prop: Optional[Xlib.protocol.request.GetProperty], text: bo
258258
Extract data from retrieved window/root property
259259
260260
:param prop: Xlib.protocol.request.GetProperty struct from which extract data
261-
:param text: set to ''True'' to convert the atoms (int) to their names (str)
261+
:param text: set to ''True'' to convert the atoms (int) to their names (str), if possible
262262
:param display: display to which window belongs to (defaults to default display)
263263
:return: extracted property data (as a list of integers or strings) or None
264264
"""
265265
if prop and hasattr(prop, "value"):
266266
# Value is either str, bytes (separated by '\x00' when multiple values) or array.array of integers.
267267
# The type of array values is stored in array.typecode ('I' in this case).
268-
valueData: Union[array.array[int], bytes] = prop.value
269-
if isinstance(valueData, str) or isinstance(valueData, int):
268+
valueData: Union[str, int, bytes, array.array[int], List[str], List[int]] = prop.value
269+
if isinstance(valueData, str):
270270
return [valueData]
271-
if isinstance(valueData, bytes):
271+
elif isinstance(valueData, int):
272+
result = valueData
273+
if text and valueData != 0:
274+
try:
275+
result = display.get_atom_name(valueData)
276+
except:
277+
pass
278+
return [result]
279+
elif isinstance(valueData, bytes):
272280
resultStr: List[str] = [a for a in valueData.decode().split("\x00") if a]
273281
return resultStr
274-
elif isinstance(valueData, array.array):
282+
elif isinstance(valueData, array.array) or isinstance(valueData, list):
275283
if text:
276-
resultStr = [display.get_atom_name(a) for a in valueData if isinstance(a, int) and a != 0]
277-
return resultStr
278-
else:
284+
try:
285+
resultStr = [display.get_atom_name(a) for a in valueData if isinstance(a, int) and a != 0]
286+
return resultStr
287+
except:
288+
text = False
289+
if not text:
279290
resultInt: List[int] = [a for a in valueData if isinstance(a, int)]
280291
return resultInt
281-
# Leaving this to detect if data has an unexpected type
282-
return [a for a in valueData] if isinstance(valueData, Iterable) else [valueData]
283292
return None
284293

285294

0 commit comments

Comments
 (0)