Skip to content

Latest commit

 

History

History
373 lines (276 loc) · 16.5 KB

README.md

File metadata and controls

373 lines (276 loc) · 16.5 KB

EWMH-lib

Type Checking PyPI version Documentation Status

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 in the project homepage

Warning: new Display Server used by GNOME in Ubuntu, Wayland, is not EWMH-compliant, so many features will not work

General functions and variables

These functions and variables are module-level, so they do not need to previously instantiate any class or object.

General objects

As their names suggest, these general variables will give access to the default display, screen and root objects, allowing to use them in Xlib-related functions.

Objects
defaultDisplay
defaultScreen
defaultRoot

General functions

These functions will allow to manage/find displays, screens and roots, 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
getDisplaysInfo
getDisplayFromRoot
getDisplayFromWindow
getRoots

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 getDisplaysInfo(), 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.

EwmhRoot methods
getSupportedHints
getClientList
getClientListStacking
getNumberOfDesktops
setNumberOfDesktops
getDesktopGeometry
setDesktopGeometry
getDesktopViewport
setDesktopViewport
getCurrentDesktop
setCurrentDesktop
getDesktopNames
getActiveWindow
getWorkArea
getSupportingWMCheck
getVirtualRoots
setDesktopLayout
getShowingDesktop
setShowingDesktop
setClosed
setMoveResize
setWmMoveResize
setWmStacking
requestFrameExtents

WM_PROTOCOLS messages are accessible using wmProtocols subclass (EwmhRoot.wmProtocols.Ping/Sync)

EwmhRoot WMProtocols methods
ping
sync

Apart from given methods, you can access these other variables (EwmhRoot.*) to be used with python-xlib. In most cases these values will match default general variables described above.

EwmhRoot variables Description
display XDisplay connection the root belongs to
screen screen the root belongs to as Struct
root root as X-Window object
id root window id

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.

EwmhRoot methods
getName
setName
getVisibleName
setVisibleName
getIconName
setIconName
getVisibleIconName
setVisibleIconName
getDesktop
setDesktop
getWmWindowType
setWmWindowType
getWmState
changeWmState
setMaximized
setMinimized
getAllowedActions
getStrut
setStrut
getStrutPartial
getIconGeometry
getPid
getHandledIcons
getUserTime
getFrameExtents
getOpaqueRegion
getBypassCompositor
setActive
setClosed
changeStacking
setMoveResize
setMoveWmResize
setWmStacking
requestFrameExtents

Apart from given methods, there are some values you can use with python-xlib:

EwmhWindow variables Description
display XDisplay connection the window belongs to
screen screen the window belongs to as Struct
root root the window belongs to as X-Window object
rootWindow root the window belongs to as EwmhRoot object
XWindow X-Window object associated to current window
id window id

EwmhWindow Extensions: Geometry, Hints, Protocols and Events

Additional, non-EWMH features, related to low-level window properties like hints, protocols and events are available using extensions subclass (EwmhWindow.extensions.*).

Extensions methods
getWmHints
setWmHints
getWmNormalHints
setWmNormalHints
getWmProtocols
addWmProtocols
delWmProtocols
CheckEvents
Extensions.CheckEvents Methods
start
pause
stop

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("MANUALLY 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()

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 than the methods provided by EwmhRoot and EwmhWindow classes), 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:

Properties, atoms and hints
Root
DesktopLayout
Window
WindowType
State
StateAction
MoveResize
DataFormat
Mode
StackMode
HintAction

Data Structs

Aimed to facilitate understanding and handling complex reply data structures and fields.

Data Structs
DisplaysInfo
ScreensInfo
WmHints
WmNormalHints

Install

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 and the dist folder, 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

In case you have a problem, comments or suggestions, do not hesitate to open issues on the project homepage

Using this code

If you want to use this code or contribute, you can either:

Be sure you install all dependencies described on "docs/requirements.txt" by using pip

Test

To test this module on your own system, cd to "tests" folder and run:

python3 test_ewmhlib.py

List of EWMH-compliant window managers

A (likely) incomplete list of EWMH-compliant window managers is (via Wikipedia, here and here):

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)