I’ve been trying to figure out the size of a window for use in a small script. My current technique is using wmctrl -lG to find out the dimensions. However, the problem is this:
The x and y figures it gives are for the top left of the window decorations, while the height and width are for just the content area. This means that if the window decorations add 20px of height and 2px of width, wmctrl will report a window as being 640×480, even if it takes up 660×482 on screen. This is a problem because my script’s next step would be to use that area to tell ffmpeg to record the screen. I would like to avoid hardcoding in the size of the window decorations from my current setup.
What would suit is either a method to get the size of the window decorations so I can use them to figure out the position of the 640×480 content area, or a way to get the position of the content area directly, not that of the window decorations.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The following script will give you the top-left screen co-ords and size of the window (without any decoration). . . . xwininfo -id $(xdotool getactivewindow) contains enough information for you.
#!/bin/bash
# Get the coordinates of the active window's
# top-left corner, and the window's size.
# This excludes the window decoration.
unset x y w h
eval $(xwininfo -id $(xdotool getactivewindow) |
sed -n -e "s/^ +Absolute upper-left X: +([0-9]+).*/x=1/p"
-e "s/^ +Absolute upper-left Y: +([0-9]+).*/y=1/p"
-e "s/^ +Width: +([0-9]+).*/w=1/p"
-e "s/^ +Height: +([0-9]+).*/h=1/p" )
echo -n "$x $y $w $h"
#
Method 2
Much simpler way to get current window size and position:
xdotool getwindowfocus getwindowgeometry
and to get selected window size and position:
xdotool selectwindow getwindowgeometry
Method 3
The accepted answer can be extended to get the entire window:
entire=false
x=0
y=0
w=0
h=0
b=0 # b for border
t=0 # t for title (or top)
# ... find out what user wants then
eval $(xwininfo -id $(xdotool getactivewindow) |
sed -n -e "s/^ +Absolute upper-left X: +([0-9]+).*/x=1/p"
-e "s/^ +Absolute upper-left Y: +([0-9]+).*/y=1/p"
-e "s/^ +Width: +([0-9]+).*/w=1/p"
-e "s/^ +Height: +([0-9]+).*/h=1/p"
-e "s/^ +Relative upper-left X: +([0-9]+).*/b=1/p"
-e "s/^ +Relative upper-left Y: +([0-9]+).*/t=1/p" )
if [ "$entire" = true ]
then # if user wanted entire window, adjust x,y,w and h
let x=$x-$b
let y=$y-$t
let w=$w+2*$b
let h=$h+$t+$b
fi
echo "$w"x"$h" $x,$y
Although easy, it turns out not to work on Unity in Ubuntu 14.04 because the Relative info is all 0. I asked Get the full window dimensions (including decorations) in Unity and got a good answer. Here is how I used that answer:
aw=$(xdotool getactivewindow)
eval $(xwininfo -id "$aw" |
sed -n -e "s/^ +Absolute upper-left X: +([0-9]+).*/x=1/p"
-e "s/^ +Absolute upper-left Y: +([0-9]+).*/y=1/p"
-e "s/^ +Width: +([0-9]+).*/w=1/p"
-e "s/^ +Height: +([0-9]+).*/h=1/p" )
if [ "$entire" = true ]
then
extents=$(xprop _NET_FRAME_EXTENTS -id "$aw" | grep "NET_FRAME_EXTENTS" | cut -d '=' -f 2 | tr -d ' ')
bl=$(echo $extents | cut -d ',' -f 1) # width of left border
br=$(echo $extents | cut -d ',' -f 2) # width of right border
t=$(echo $extents | cut -d ',' -f 3) # height of title bar
bb=$(echo $extents | cut -d ',' -f 4) # height of bottom border
let x=$x-$bl
let y=$y-$t
let w=$w+$bl+$br
let h=$h+$t+$bb
fi
This second method works in both Unity and Xfce, and should work in Gnome too.
Method 4
Using xdotool:
- First you need to get window id:
sleep 3s && xdotool getactivewindow, you have 3 sec to open your window
- Then you need to use :
- to get info in output use this:
xdotool getwindowgeometry $WINDOW_ID - or if you want shell parameter use this:
xdotool getwindowgeometry -shell $WINDOW_ID
- to get info in output use this:
Method 5
The accepted answer explicitly does not include window decoration. For those still looking for how to get the geometry including all decorations, as per this question’s title, you can use wmiface as per this other question https://superuser.com/questions/164047/how-to-get-accurate-window-information-dimensions-etc-in-linux-x. Example:
wmiface frameGeometry `wmiface activeWindow`
This returns geometry and position relative to top left like so:
650x437+0+1003
wmiface does not seem to come with all linux distros (I didn’t find a package providing it on Mint or Ubuntu) but I was able to install it from the packages here: http://kde-apps.org/content/show.php?content=40425
And it comes with no docs nor even --help, but the README is here:
https://gitorious.org/wmiface/wmiface/source/ea941eeb2076124734f6a3d3079326c826b462d7:README
Method 6
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: %sn", 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 %un", id, x, y, w, h, border);
}
else
{
fprintf(stderr, "Could not get location of window 0x%08lxn", id);
status = 1;
}
break;
}
win = parent;
}
}
}
XtCloseDisplay(display);
}
else
{
fprintf(stderr, "Cannot open displayn");
status = 1;
}
XtDestroyApplicationContext(app);
return status;
}
Method 7
If you’d like to pick the window with the mouse, just run
$ xwininfo
And click the window you’d like. It gives a lot of info, and geometry that includes the decorations in a format which can just be copy-pasted to other programs such as xterm. eg.
xwininfo: Please select the window about which you
would like information by clicking the
mouse in that window.
xwininfo: Window id: 0x160000d "watch"
Absolute upper-left X: 1184
Absolute upper-left Y: 215
Relative upper-left X: 0
Relative upper-left Y: 0
Width: 484
Height: 615
Depth: 24
Visual: 0x21
Visual Class: TrueColor
Border width: 0
Class: InputOutput
Colormap: 0x20 (installed)
Bit Gravity State: NorthWestGravity
Window Gravity State: NorthWestGravity
Backing Store State: NotUseful
Save Under State: no
Map State: IsViewable
Override Redirect State: no
Corners: +1184+215 -2812+215 -2812-1150 +1184-1150
-geometry 80x47+1178+188
Then you can put the following in your .xinitrc or equivalent:
xterm -geometry 80x47+1178+188 -bg black -fg white -T sensors -e watch -n10 -d "sensors;"
The -geometry option is interpreted by almost every X application.
If you’re not getting accurate geometry it’s because the window in question is drawing its own decorations that the windowing system doesn’t know about, so you’ll have to check the settings for the app in question, and adjust accordingly.
On Debian this is from:
$ dpkg -S xwininfo x11-utils: /usr/bin/xwininfo x11-utils: /usr/share/man/man1/xwininfo.1.gz
So just
$ apt install x11-utils
If you don’t have it.
Method 8
Combining answers on this page I used this:
$ sleep 3 && xdotool getwindowfocus getwindowgeometry Window 88080400 Position: 4565,2345 (screen: 0) Geometry: 1186x885
Run the one-liner and then within 3 seconds click on the window you want the position and geometry for.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0