# EWMH-lib
[![Type Checking](https://github.com/Kalmat/EWMHlib/actions/workflows/type-checking.yml/badge.svg)](https://github.com/Kalmat/EWMHlib/actions/workflows/type-checking.yml)
[![PyPI version](https://badge.fury.io/py/ewmhlib.svg)](https://badge.fury.io/py/ewmhlib)
Extended Window Manager Hints implementation in Python 3 and python-xlib, which allows to easily query and control
Window Managers following these standards.
It also adds some additional, useful features like managing hints and handling events.
For more information, refer to official documentation at: https://specifications.freedesktop.org/wm-spec/latest/
This module has been tested OK in Ubuntu/GNOME, Mint/Cinnamon and Manjaro/KDE. If you have issues in other EWMH-compliant environments, do not hesitate to [open an issue](https://github.com/Kalmat/EWMHlib/issues) in the [project homepage](https://github.com/Kalmat/EWMHlib)
**Warning: new Display Server used by GNOME in Ubuntu, Wayland, is not EWMH-compliant, so many features will not work**
### EwmhRoot: Root queries, changes and messages
Class to access root features.
If you need to address default root window, you can simply use `defaultRootWindow` object, which will give you
instant access to all root-related features (it is equivalent to: `myRoot = EwmhRoot()`)
To get a EwmhRoot object it is necessary to pass the target root id. This can be achieved in several ways:
- You already have a root, so pass root.id param
- You have some criteria to select a root, so use the convenience function `getAllDisplaysInfo()`, to look for all roots and select the desired one
- You have a target window, so use the convenience function getDisplayFromWindow(window.id), so you will retrieve the associated display connection and root window
- Instantiate this class with no param (None), so it will retrieve the default display and root
Note that, even though a regular (application) window has the same type than a root window,
these methods will not work with it, so avoid passing it to instantiate this class.
Apart from given methods, you can access these other values to be used with python-xlib:
- display: XDisplay connection
- screen: screen Struct
- root: root X Window object
- id: root window id
#### WM Protocols
WM_PROTOCOLS messages (PING/SYNC) are accessible using wmProtocols subclass (EwmhRoot.wmProtocols.Ping/Sync)
### EwmhWindow: Window queries, changes and messages
Class to access application window features.
To instantiate this class only a window id is required. It is possible to retrieve this value in several ways:
- Target a specific window using an external module (e.g. `pywinctl.getAllWindowsWithTitle(title)` or `pywinctl.getActiveWindow()`)
- Retrieve it from your own application (e.g. PyQt's `winId()` or TKinter's `frame()`)
Note that, although a root is also a window, most of these methods will not likely work with it.
Apart from given methods, there are some values you can use with python-xlib:
- display: XDisplay connection
- screen: screen Struct
- root: root X Window object
- rootWindow: object to access EwmhRoot methods
- xWindow: X Window object associated to current window
- id: current window id
Additional, non-EWMH features, related to low-level window properties like hints, protocols and events are
available using extensions subclass (EwmhWindow.extensions.*), see below.
#### Extensions: Geometry, Hints, Protocols and Events
Additional, non-EWMH features, related to low-level window properties like geometry, hints, protocols and events.
Events loop example:
import time
import Xlib.protocol
import Xlib.X
from ewmhlib import EwmhRoot, EwmhWindow
root = EwmhRoot()
w = root.getActiveWindow()
if w:
win = EwmhWindow(w)
def callback(event: Xlib.protocol.rq.Event):
print("EVENT RECEIVED", event)
win.extensions.checkEvents.start([Xlib.X.ConfigureNotify, Xlib.X.ConfigureRequest, Xlib.X.ClientMessage],
Xlib.X.StructureNotifyMask | Xlib.X.SubstructureNotifyMask,
callback)
print("MOVE AND RESIZE ACTIVE WINDOW")
print("Press Ctl-C to exit")
while True:
try:
time.sleep(0.1)
except KeyboardInterrupt:
break
win.extensions.checkEvents.stop()
### General variables
As their names suggest, these general variables will give access to the default display, screen
and root objects, allowing to perform all Xlib-related functions.
| Objects |
|:--------------:|
| defaultDisplay |
| defaultScreen |
| defaultRoot |
### Display functions
These functions will allow to manage/find proper display and screen, in a multi-display or multi-screen environment
(not the usual scenario, so the default objects above will be enough in most cases).
| Display functions |
|:--------------------:|
| getAllDisplays |
| getDisplayFromRoot |
| getDisplayFromWindow |
### Properties and Messages functions
This set of functions will allow to directly query and control application or root windows, without the
need of instantiating their corresponding classes described above.
These are very similar to their Xlib equivalent functions (more complex to use), and therefore will allow
custom, more advanced, perhaps more specific and/or non fully EWMH standard features; but they add some
useful help in order to simplify handling replies, values, atoms and so on.
| Property functions |
|:--------------------:|
| getProperty |
| getPropertyValue |
| changeProperty |
| sendMessage |
### Properties, atoms and hints values
These values are accessible through `Props` class (ewmhlib.Props.*).
They include all properties, atoms and hints values recognized by EWMH specs, so makes it easier
to find, enumerate or use them.
They have been organized in different subclasses, according to their type or when they should be used.
### Data Structs
Aimed to facilitate understanding and handling complex reply data structures and fields.
| Data Structs |
|:-------------:|
| DisplaysInfo |
| ScreensInfo |
| WmHints |
| WmNormalHints |
## INSTALL <a name="install"></a>
To install this module on your system, you can use pip:
pip3 install ewmhlib
or
python3 -m pip install ewmhlib
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):
pip install EWMHlib-x.xx-py3-none-any.whl
You may want to add `--force-reinstall` option to be sure you are installing the right dependencies version.
Then, you can use it on your own projects just importing it:
import ewmhlib
## SUPPORT <a name="support"></a>
In case you have a problem, comments or suggestions, do not hesitate to [open issues](https://github.com/Kalmat/EWMHlib/issues) on the [project homepage](https://github.com/Kalmat/EWMHlib)
## USING THIS CODE <a name="using"></a>
If you want to use this code or contribute, you can either:
* Create a fork of the [repository](https://github.com/Kalmat/EWMHlib), or
* [Download the repository](https://github.com/Kalmat/EWMHlib/archive/refs/heads/master.zip), uncompress, and open it on your IDE of choice (e.g. PyCharm)
Be sure you install all dependencies described on "docs/requirements.txt" by using pip
## TEST <a name="test"></a>
To test this module on your own system, cd to "tests" folder and run:
python3 test_ewmhlib.py
## List of window managers that support Extended Window Manager Hints
An (likely) incomplete list of EWMH-compliant window managers is (via Wikipedia, [here](https://en.wikipedia.org/wiki/Extended_Window_Manager_Hints) and [here](https://en.wikipedia.org/wiki/Comparison_of_X_window_managers#General_information)):
| Name | Comments |
|:--------------------:|:-----------:|
| aewm | |
| awesome | |
| Blackbox | (1) |
| bspwm | Partial |
| CTWM | (2) |
| Compiz | |
| echinus | |
| edewm | |
| Enlightenment | |
| evilwm | Partial (3) |
| EXWM | Partial |
| Fluxbox | |
| FVWM | |
| goomwwm | |
| herbstluftwm | |
| i3 | |
| IceWM | |
| interfacewm | |
| JWM | |
| KWin (KDE) | |
| LeftWM | |
| Marco | |
| Matchbox | |
| Metacity (GNOME) | |
| Mutter (GNOME/MeeGo) | |
| Notion | |
| Openbox | |
| PekWM | Partial |
| PlayWM | |
| Qtile | |
| Sawfish | Partial |
| spectrwm | |
| subtle | |
| Window Maker | Partial |
| Wingo | |
| WMFS | |
| wmii | |
| Xfwm (Xfce) | |
| xmonad | (4) |
(1) Through 0.65 / from 0.70
(2) As of 4.0.0
(3) Releases following and including version 1.1.0 follow the EWMH standard
(4) Must activate EWMH (XMonad.Hooks.EwmhDesktops)
Raw data
{
"_id": null,
"home_page": "https://github.com/Kalmat/EWMHlib",
"name": "EWMHlib",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "ewmh Extended-Window-manager-hints window-manager window manager hints",
"author": "Kalmat",
"author_email": "palookjones@gmail.com",
"download_url": null,
"platform": null,
"description": "# EWMH-lib\r\n[![Type Checking](https://github.com/Kalmat/EWMHlib/actions/workflows/type-checking.yml/badge.svg)](https://github.com/Kalmat/EWMHlib/actions/workflows/type-checking.yml)\r\n[![PyPI version](https://badge.fury.io/py/ewmhlib.svg)](https://badge.fury.io/py/ewmhlib)\r\n\r\nExtended Window Manager Hints implementation in Python 3 and python-xlib, which allows to easily query and control \r\nWindow Managers following these standards.\r\n\r\nIt also adds some additional, useful features like managing hints and handling events.\r\n\r\nFor more information, refer to official documentation at: https://specifications.freedesktop.org/wm-spec/latest/\r\n\r\nThis module has been tested OK in Ubuntu/GNOME, Mint/Cinnamon and Manjaro/KDE. If you have issues in other EWMH-compliant environments, do not hesitate to [open an issue](https://github.com/Kalmat/EWMHlib/issues) in the [project homepage](https://github.com/Kalmat/EWMHlib)\r\n\r\n**Warning: new Display Server used by GNOME in Ubuntu, Wayland, is not EWMH-compliant, so many features will not work**\r\n\r\n\r\n### EwmhRoot: Root queries, changes and messages\r\n\r\nClass to access root features.\r\n\r\nIf you need to address default root window, you can simply use `defaultRootWindow` object, which will give you\r\ninstant access to all root-related features (it is equivalent to: `myRoot = EwmhRoot()`)\r\n\r\nTo get a EwmhRoot object it is necessary to pass the target root id. This can be achieved in several ways:\r\n\r\n- You already have a root, so pass root.id param\r\n- You have some criteria to select a root, so use the convenience function `getAllDisplaysInfo()`, to look for all roots and select the desired one\r\n- You have a target window, so use the convenience function getDisplayFromWindow(window.id), so you will retrieve the associated display connection and root window\r\n- Instantiate this class with no param (None), so it will retrieve the default display and root\r\n\r\nNote that, even though a regular (application) window has the same type than a root window, \r\nthese methods will not work with it, so avoid passing it to instantiate this class.\r\n\r\nApart from given methods, you can access these other values to be used with python-xlib:\r\n\r\n- display: XDisplay connection\r\n- screen: screen Struct\r\n- root: root X Window object\r\n- id: root window id\r\n\r\n\r\n#### WM Protocols\r\n\r\nWM_PROTOCOLS messages (PING/SYNC) are accessible using wmProtocols subclass (EwmhRoot.wmProtocols.Ping/Sync)\r\n\r\n\r\n### EwmhWindow: Window queries, changes and messages\r\n\r\nClass to access application window features.\r\n\r\nTo instantiate this class only a window id is required. It is possible to retrieve this value in several ways:\r\n\r\n- Target a specific window using an external module (e.g. `pywinctl.getAllWindowsWithTitle(title)` or `pywinctl.getActiveWindow()`)\r\n- Retrieve it from your own application (e.g. PyQt's `winId()` or TKinter's `frame()`)\r\n\r\nNote that, although a root is also a window, most of these methods will not likely work with it.\r\n\r\nApart from given methods, there are some values you can use with python-xlib:\r\n\r\n- display: XDisplay connection\r\n- screen: screen Struct\r\n- root: root X Window object\r\n- rootWindow: object to access EwmhRoot methods\r\n- xWindow: X Window object associated to current window\r\n- id: current window id\r\n\r\nAdditional, non-EWMH features, related to low-level window properties like hints, protocols and events are\r\navailable using extensions subclass (EwmhWindow.extensions.*), see below.\r\n\r\n\r\n#### Extensions: Geometry, Hints, Protocols and Events\r\n\r\nAdditional, non-EWMH features, related to low-level window properties like geometry, hints, protocols and events.\r\n\r\nEvents loop example:\r\n\r\n import time\r\n \r\n import Xlib.protocol\r\n import Xlib.X\r\n \r\n from ewmhlib import EwmhRoot, EwmhWindow\r\n \r\n root = EwmhRoot()\r\n w = root.getActiveWindow()\r\n if w:\r\n win = EwmhWindow(w)\r\n\r\n def callback(event: Xlib.protocol.rq.Event):\r\n print(\"EVENT RECEIVED\", event)\r\n\r\n win.extensions.checkEvents.start([Xlib.X.ConfigureNotify, Xlib.X.ConfigureRequest, Xlib.X.ClientMessage],\r\n Xlib.X.StructureNotifyMask | Xlib.X.SubstructureNotifyMask,\r\n callback)\r\n\r\n print(\"MOVE AND RESIZE ACTIVE WINDOW\")\r\n print(\"Press Ctl-C to exit\")\r\n while True:\r\n try:\r\n time.sleep(0.1)\r\n except KeyboardInterrupt:\r\n break\r\n win.extensions.checkEvents.stop()\r\n\r\n\r\n### General variables\r\n\r\nAs their names suggest, these general variables will give access to the default display, screen\r\nand root objects, allowing to perform all Xlib-related functions.\r\n\r\n| Objects |\r\n|:--------------:|\r\n| defaultDisplay |\r\n| defaultScreen |\r\n| defaultRoot |\r\n\r\n\r\n### Display functions\r\n\r\nThese functions will allow to manage/find proper display and screen, in a multi-display or multi-screen environment\r\n(not the usual scenario, so the default objects above will be enough in most cases).\r\n \r\n| Display functions |\r\n|:--------------------:|\r\n| getAllDisplays |\r\n| getDisplayFromRoot |\r\n| getDisplayFromWindow |\r\n\r\n\r\n### Properties and Messages functions \r\n\r\nThis set of functions will allow to directly query and control application or root windows, without the\r\nneed of instantiating their corresponding classes described above. \r\n\r\nThese are very similar to their Xlib equivalent functions (more complex to use), and therefore will allow \r\ncustom, more advanced, perhaps more specific and/or non fully EWMH standard features; but they add some \r\nuseful help in order to simplify handling replies, values, atoms and so on.\r\n\r\n| Property functions |\r\n|:--------------------:|\r\n| getProperty |\r\n| getPropertyValue |\r\n| changeProperty |\r\n| sendMessage |\r\n\r\n\r\n### Properties, atoms and hints values\r\n\r\nThese values are accessible through `Props` class (ewmhlib.Props.*). \r\nThey include all properties, atoms and hints values recognized by EWMH specs, so makes it easier \r\nto find, enumerate or use them.\r\n\r\nThey have been organized in different subclasses, according to their type or when they should be used.\r\n\r\n### Data Structs\r\n\r\nAimed to facilitate understanding and handling complex reply data structures and fields.\r\n\r\n| Data Structs |\r\n|:-------------:|\r\n| DisplaysInfo |\r\n| ScreensInfo |\r\n| WmHints |\r\n| WmNormalHints |\r\n\r\n\r\n## INSTALL <a name=\"install\"></a>\r\n\r\nTo install this module on your system, you can use pip: \r\n\r\n pip3 install ewmhlib\r\n\r\nor\r\n\r\n python3 -m pip install ewmhlib\r\n\r\nAlternatively, 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):\r\n\r\n pip install EWMHlib-x.xx-py3-none-any.whl\r\n\r\nYou may want to add `--force-reinstall` option to be sure you are installing the right dependencies version.\r\n\r\nThen, you can use it on your own projects just importing it:\r\n\r\n import ewmhlib\r\n\r\n## SUPPORT <a name=\"support\"></a>\r\n\r\nIn case you have a problem, comments or suggestions, do not hesitate to [open issues](https://github.com/Kalmat/EWMHlib/issues) on the [project homepage](https://github.com/Kalmat/EWMHlib)\r\n\r\n## USING THIS CODE <a name=\"using\"></a>\r\n\r\nIf you want to use this code or contribute, you can either:\r\n\r\n* Create a fork of the [repository](https://github.com/Kalmat/EWMHlib), or \r\n* [Download the repository](https://github.com/Kalmat/EWMHlib/archive/refs/heads/master.zip), uncompress, and open it on your IDE of choice (e.g. PyCharm)\r\n\r\nBe sure you install all dependencies described on \"docs/requirements.txt\" by using pip\r\n\r\n## TEST <a name=\"test\"></a>\r\n\r\nTo test this module on your own system, cd to \"tests\" folder and run:\r\n\r\n python3 test_ewmhlib.py\r\n \r\n\r\n## List of window managers that support Extended Window Manager Hints\r\n\r\nAn (likely) incomplete list of EWMH-compliant window managers is (via Wikipedia, [here](https://en.wikipedia.org/wiki/Extended_Window_Manager_Hints) and [here](https://en.wikipedia.org/wiki/Comparison_of_X_window_managers#General_information)):\r\n\r\n| Name | Comments |\r\n|:--------------------:|:-----------:|\r\n| aewm | |\r\n| awesome | |\r\n| Blackbox | (1) |\r\n| bspwm | Partial |\r\n| CTWM | (2) |\r\n| Compiz | |\r\n| echinus | |\r\n| edewm | |\r\n| Enlightenment | |\r\n| evilwm | Partial (3) |\r\n| EXWM | Partial |\r\n| Fluxbox | |\r\n| FVWM | |\r\n| goomwwm | |\r\n| herbstluftwm | |\r\n| i3 | |\r\n| IceWM | |\r\n| interfacewm | |\r\n| JWM | |\r\n| KWin (KDE) | |\r\n| LeftWM | |\r\n| Marco | |\r\n| Matchbox | |\r\n| Metacity (GNOME) | |\r\n| Mutter (GNOME/MeeGo) | |\r\n| Notion | |\r\n| Openbox | |\r\n| PekWM | Partial |\r\n| PlayWM | |\r\n| Qtile | |\r\n| Sawfish | Partial |\r\n| spectrwm | |\r\n| subtle | |\r\n| Window Maker | Partial |\r\n| Wingo | |\r\n| WMFS | |\r\n| wmii | |\r\n| Xfwm (Xfce) | |\r\n| xmonad | (4) |\r\n\r\n(1) Through 0.65 / from 0.70\r\n\r\n(2) As of 4.0.0\r\n\r\n(3) Releases following and including version 1.1.0 follow the EWMH standard\r\n\r\n(4) Must activate EWMH (XMonad.Hooks.EwmhDesktops)\r\n",
"bugtrack_url": null,
"license": "BSD 3",
"summary": "Extended Window Manager Hints implementation in Python 3",
"version": "0.2",
"project_urls": {
"Homepage": "https://github.com/Kalmat/EWMHlib"
},
"split_keywords": [
"ewmh",
"extended-window-manager-hints",
"window-manager",
"window",
"manager",
"hints"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2f3a46ca34abf0725a754bc44ef474ad34aedcc3ea23b052d97b18b76715a6a9",
"md5": "7929125fff1fb853e8396b441938dd7e",
"sha256": "f5b07d8cfd4c7734462ee744c32d490f2f3233fa7ab354240069344208d2f6f5"
},
"downloads": -1,
"filename": "EWMHlib-0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7929125fff1fb853e8396b441938dd7e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 46657,
"upload_time": "2024-04-17T08:15:56",
"upload_time_iso_8601": "2024-04-17T08:15:56.338552Z",
"url": "https://files.pythonhosted.org/packages/2f/3a/46ca34abf0725a754bc44ef474ad34aedcc3ea23b052d97b18b76715a6a9/EWMHlib-0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-17 08:15:56",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Kalmat",
"github_project": "EWMHlib",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "ewmhlib"
}