8
votes

I need to find window position and size, but I cannot figure out how. For example if I try:

id.get_geometry()    # "id" is Xlib.display.Window

I get something like this:

data = {'height': 2540,
'width': 1440,
'depth': 24,
'y': 0, 'x': 0,
'border_width': 0
'root': <Xlib.display.Window 0x0000026a>
'sequence_number': 63}

I need to find window position and size, so my problem is: "y", "x" and "border_width" are always 0; even worse, "height" and "width" are returned without window frame.

In this case on my X screen (its dimensions are 4400x2560) I expected x=1280, y=0, width=1440, height=2560.

In other words I'm looking for python equivalent for:

#!/bin/bash
id=$1
wmiface framePosition $id
wmiface frameSize $id

If you think Xlib is not what I want, feel free to offer non-Xlib solution in python if it can take window id as argument (like the bash script above). Obvious workaround to use output of the bash script in python code does not feel right.

3
Thanks to answer by Andrey Sidorov I solved my problem. Here is very simple script which demonstrates the solution: print_frame_geometry_of_all_windows.py. - Lissanro Rayen

3 Answers

3
votes

You are probably using reparenting window manager, and because of this id window has zero x and y. Check coordinates of parent window (which is window manager frame)

2
votes

Liss posted the following solution as a comment:

from ewmh import EWMH
ewmh = EWMH()

def frame(client):
    frame = client
    while frame.query_tree().parent != ewmh.root:
        frame = frame.query_tree().parent
    return frame

for client in ewmh.getClientList():
    print frame(client).get_geometry()

I'm copying it here because answers should contain the actual answer, and to prevent link rot.

0
votes

Here's what I came up with that seems to work well:

from collections import namedtuple

import Xlib.display


disp = Xlib.display.Display()
root = disp.screen().root

MyGeom = namedtuple('MyGeom', 'x y height width')


def get_absolute_geometry(win):
    """
    Returns the (x, y, height, width) of a window relative to the top-left
    of the screen.
    """
    geom = win.get_geometry()
    (x, y) = (geom.x, geom.y)
    while True:
        parent = win.query_tree().parent
        pgeom = parent.get_geometry()
        x += pgeom.x
        y += pgeom.y
        if parent.id == root.id:
            break
        win = parent
    return MyGeom(x, y, geom.height, geom.width)

Full example here.