5

I have to (scriptly) take screenshots of windows, some of which may be partially or fully hidden by other windows. Of course, in such a case the screenshot is useless, and I'd rather print a warning.

Unfortunately I'm not in a situation where I can use a Window Manager which prints even hidden or minimized windows — I'm stuck with an old KDE.

I can use e.g. xwininfo -id <windowid> | grep "Map State" to determine if the window IsViewable (which basically means standard screenshot tools won't complain), but I can't seem to figure out how to determine if the window is overlapped by other windows and how much it is (then I could print the warning if, say, less than 50 % of the window are visible).

(As I'm actually trying to workaround it because I don't believe it exists, of course I won't complain if anyone points me to an easy method to e.g. "virtually redraw" windows so that the screenshot is worth it…)

  • 3
    Kluge: Raise the window. You can do this with wmctrl. – derobert Oct 1 '13 at 16:45
  • 1
    Thanks for the suggestion, it could have been a workaround under different circumstances. Unfortunately people are using the computers (that's why some windows may be hidden), and I'm afraid popping up windows in their face is not an option. – Skippy le Grand Gourou Oct 1 '13 at 17:07
3

As far as I know (but I'm no X expert), visibility is only tracked through VisibilityNotify events, it isn't a state that you can query like IsViewable. You'd need to get KDE to spit it out, I don't know if it can do that.

You may be solve your problem by sending the window a VisibilityNotify(state=VisibilityUnobscured) event. I don't know if that's enough, you may also need to send a MapNotify event. Here's some untested Python code to send a VisibilityNotify event.

#! /usr/bin/env python
import re, sys, time
import Xlib.X, Xlib.XK, Xlib.display, Xlib.protocol

def parse_action(string):
    state = {
              '0': 0,
              '1': 1,
              '2': 2,
              'unobscured': 0,
              'partiallyobscured': 1,
              'fullyobscured': 2,
              'visibilityunobscured': 0,
              'visibilitypartiallyobscured': 1,
              'visibilityfullyobscured': 2,
             }[string.lower()]
    return state

def parse_window(display, arg):
    wid = int(arg, 0)
    return display.create_resource_object('window', wid)

def send_event(display, window, state):
    window.send_event(Xlib.protocol.event.VisibilityNotify(window=window,
                                                           state=state))
    display.sync()

if __name__ == "__main__":
    display = Xlib.display.Display()
    send_event(display, parse_window(display, sys.argv[1]), parse_action(sys.argv[2]))
  • 1
    Thanks for the explanations and the piece of code. Those python libs are not available on the machine and it's not so easy to install anything on it (it runs an old SL4.8). I may test and dig your proposition later on another setup for fun and in case it helps someone else, but anyway for our simple purpose it's probably not worth the time and trouble, so I guess I just won't bother too much about it for now. – Skippy le Grand Gourou Oct 2 '13 at 18:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.