I would like to get the size of the current window from a shell script…
Really not much else to say… I would prefer to use wmctrl.
command linewindow
I would like to get the size of the current window from a shell script…
Really not much else to say… I would prefer to use wmctrl.
Use the xttitle
program from the xttitle
package. Note the TWO "t"s in xttitle. Well, actually, there are 3 "t"s... but I've only had trouble mistyping the first two.
Here's an example from my ~/.bashrc
, in which I override the cd
builtin, and use xttitle
to put the current directory in my window title:
# from the "xttitle(1)" man page - put info in window title
update_title()
{
[[ $TERM = xterm ]] || [[ $TERM = xterm-color ]] && xttitle "[$$] ${USER}@${HOSTNAME}:$PWD"
}
cd()
{
[[ -z "$*" ]] && builtin cd $HOME
[[ -n "$*" ]] && builtin cd "$*"
update_title
}
From your own answer, I understand you are looking for a convenient GUI tool, so:
As explained further below in "Explanation", both wmctrl
and xdotool
return a slightly incorrect windowsize.
The script (indicator) below will show both the "real" size and the net size of a window in the panel.
#!/usr/bin/env python3
import signal
import gi
gi.require_version('AppIndicator3', '0.1')
gi.require_version('Gtk', '3.0')
import subprocess
from gi.repository import Gtk, AppIndicator3, GObject
import time
from threading import Thread
def get(cmd):
try:
return subprocess.check_output(cmd).decode("utf-8").strip()
except subprocess.CalledProcessError:
pass
# ---
# uncomment either one of two the lines below; the first one will let the user
# pick a window *after* the indicator started, the second one will pick the
# currently active window
# ---
window = get(["xdotool", "selectwindow"])
# window = get(["xdotool", "getactivewindow"])
class Indicator():
def __init__(self):
self.app = 'test123'
iconpath = "unity-display-panel"
self.indicator = AppIndicator3.Indicator.new(
self.app, iconpath,
AppIndicator3.IndicatorCategory.OTHER)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
self.indicator.set_menu(self.create_menu())
self.indicator.set_label(" ...Starting up", self.app)
# the thread:
self.update = Thread(target=self.show_seconds)
# daemonize the thread to make the indicator stopable
self.update.setDaemon(True)
self.update.start()
def create_menu(self):
menu = Gtk.Menu()
# separator
menu_sep = Gtk.SeparatorMenuItem()
menu.append(menu_sep)
# quit
item_quit = Gtk.MenuItem('Quit')
item_quit.connect('activate', self.stop)
menu.append(item_quit)
menu.show_all()
return menu
def show_seconds(self):
sizes1 = None
while True:
time.sleep(1)
sizes2 = self.getsize(window)
if sizes2 != sizes1:
GObject.idle_add(
self.indicator.set_label,
sizes2, self.app,
priority=GObject.PRIORITY_DEFAULT
)
sizes1 = sizes2
def getsize(self, window):
try:
nettsize = [int(n) for n in get([
"xdotool", "getwindowgeometry", window
]).splitlines()[-1].split()[-1].split("x")]
except AttributeError:
subprocess.Popen(["notify-send", "Missing data", "window "+window+\
" does not exist\n(terminating)"])
self.stop()
else:
add = [l for l in get(["xprop", "-id", window]).splitlines() if "FRAME" in l][0].split()
add = [int(n.replace(",", "")) for n in add[-4:]]
xadd = add[0]+add[1]; yadd = add[2]+add[3]
totalsize = [str(s) for s in [nettsize[0]+add[0]+add[1], nettsize[1]+add[2]+add[3]]]
displ_sizes = ["x".join(geo) for geo in [[str(s) for s in nettsize], totalsize]]
string = " "+displ_sizes[0]+" / "+displ_sizes[1]
return string+((25-len(string))*" ")
def stop(self, *args):
Gtk.main_quit()
Indicator()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
The script needs xdotool to be installed:
sudo apt-get install xdotool
Copy the script into an empty file, save it as getwindowsize.py
Test- run the script from a terminal window by the command:
python3 /path/to/getwindowsize.py
The script picks the focussed window to dynamically show the net windowsize (as in the output of both wmctrl
and xdotool
) and the real window size, including decorators etc.
If you close the targeted window, the indicator shows a message:
If all works fine, add it to a shortcut key: choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:
python3 /path/to/getwindowsize.py
...is slightly incorrect
You mention:
Ideally, that tool would deduct the size of the Ubuntu's menu bar
The complete story is that both wmctrl -lG
and xdotool getwindowgeometry
return the size of the window without menu bar, or, as it is explained in this answer:
What's happening is that wmctrl is returning the geometry of the window inside the decorations (i.e. not including the title bar and borders)
To get the information correctly, we can run
xprop -id <window_id> | grep FRAME
This will output like:
_NET_FRAME_EXTENTS(CARDINAL) = 0, 0, 28, 0
Here we get the values we need to add to the window's size, as output from wmctrl
and xdotool
, to the left, right, top and bottom of the window.
In other words, in this case, if a wmctrl
shows a size of 200x100, the real size is 200x128.
As suggested by OP, the user can also pick a window after the indicator was started, by replacing:
window = get(["xdotool", "getactivewindow"])
by:
window = get(["xdotool", "selectwindow"])
In the script, either one of these lines can be uncommented.
Best Answer
Will give you something like:
With this you can
grep
andcut
down on these so you are left with the geometry values (columns 3-6).To quote the man page so you understand exactly what the columns are: