Try this code. Save as xgeometry.c
and compile with gcc -o xgeometry xgeometry.c -lX11 -lXt
. The program takes one or more window IDs (in decimal, hexadecimal, or octal) as arguments, and outputs, space separated, the window ID (in hexadecimal), X position, Y position, width, height and border width (usually zero – this is not what the window manager puts on the window). The X, Y, width and height include the window manager's decorations, at least in the case where wmctrl
is using these numbers for positioning.
Interestingly, wmctrl -e
, at least when used with xfwm, requires the X and Y positions from this program, and the width and height returned by wmctrl -l -G
, in order for wmctrl -e
not to move the window. I have not tested other window managers, so results may vary.
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
int
main(int argc, char *argv)
{
XtAppContext app;
Display display;
int status = 0;
app = XtCreateApplicationContext();
display = XtOpenDisplay(app, 0, argv[0], "xgeometry", 0, 0, &argc, argv);
if (display)
{
while (--argc)
{
char const *idstring = *++argv;
char *endptr = 0;
unsigned long id;
if (idstring[0] != '0')
id = strtoul(idstring, &endptr, 10);
else if (idstring[1] == 'x' || idstring[1] == 'X')
id = strtoul(idstring + 2, &endptr, 16);
else
id = strtoul(idstring + 1, &endptr, 8);
if (*endptr)
{
fprintf(stderr, "Invalid window id: %s\n", idstring);
status = 1;
}
else
{
Window win = (Window) id;
while (1)
{
Window parent;
Window root;
Window *children;
int nchildren;
if (!XQueryTree(display, win, &root, &parent, &children, &nchildren))
{
fprintf(stderr, "Error finding top level window for %08lx", id);
status = 1;
break;
}
XFree(children);
if (parent == root)
{
int x, y;
unsigned w, h;
unsigned border;
unsigned depth;
if (XGetGeometry(display, win, &root, &x, &y, &w, &h, &border, &depth))
{
printf("0x%08lx %d %d %u %u %u\n", id, x, y, w, h, border);
}
else
{
fprintf(stderr, "Could not get location of window 0x%08lx\n", id);
status = 1;
}
break;
}
win = parent;
}
}
}
XtCloseDisplay(display);
}
else
{
fprintf(stderr, "Cannot open display\n");
status = 1;
}
XtDestroyApplicationContext(app);
return status;
}