7

I have a game running in the background, but I would like to take screenshots of the window which is not visible. Seems like all the screenshot utilities for X11 need the window to be visible. Is there a way to do this?

  • This should be possible with a compositing window manager, but you might have to cobble together some pieces to make it happen. – Caleb Apr 3 '14 at 10:16
  • 2
    If using a different window manager is an option, see Screenshot of non active window – Gilles Apr 3 '14 at 23:44
6

It's probably the fault of the game, not the fault of the screenshot utility. X11 sends applications a VisibilityNotify event to tell them that their window is fully visible, partially obscured or totally obscured. When the window is totally obscured, most applications don't bother updating their display, which saves resources. In other words, if nobody is there to see it, the tree doesn't fall.

I think that if you send the game window a VisibilityNotify event to pretend that it's visible, then you'll get your screenshot. You'll need to send the event after the window becomes obscured, since X11 itself will send its normal event at that time. Here's an untested script that sends a VisibilityNotify event, call it with the argument VisibilityPartiallyObscured or VisibilityUnobscured. I follow with a MapNotify event, I don't know if it's useful. You need Python and Python-xlib.

#! /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))
    window.send_event(Xlib.protocol.event.MapNotify(window=window,
                                                    event=window,
                                                    override=False))
    display.sync()

if __name__ == "__main__":
    display = Xlib.display.Display()
    send_event(display, parse_window(display, sys.argv[1]), parse_action(sys.argv[2]))
  • 1
    I called it like this: ./visibility_notify.py 0x1e00087 VisibilityUnobscured, running the screenshot command afterwards had a negative result. I donno how to send a "MapNotify" after the other event. – marinara Apr 4 '14 at 7:31
  • @marinara I've added code to send MapNotify. Does it help? What screenshot program(s) have you tried? – Gilles Apr 4 '14 at 8:45
  • @Gilles is it possible to send this event without involving any custom made scripting? Perhaps using some utility program? – AnonymousLurker Apr 29 '18 at 8:22
3

If you don't have xwd and xwud already installed on your system I would be very surprised if you could not easily install them via package manager in a few seconds at most.

% man xwd

NAME
       xwd - dump an image of an X window

SYNOPSIS
       xwd  [-debug] [-help] [-nobdrs] [-out file] [-xy] [-frame] [-add value]
       [-root | -id id | -name name ] [-icmap] [-screen]  [-silent]  [-display
       display]

DESCRIPTION
       Xwd  is  an X Window System window dumping utility.  Xwd allows X users
       to store window images in a specially formatted dump file.   This  file
       can  then be read by various other X utilities for redisplay, printing,
       editing, formatting, archiving, image processing, etc.  The target win‐
       dow  is  selected  by  clicking the pointer in the desired window.  The
       keyboard bell is rung once at the beginning of the dump and twice  when
       the dump is completed.

Understand this is a sort of a desktop session recording software - built into the X-server - it does enable you take screenshots, and much more. But you'll want to read the documentation a little before diving in - just to get familiar with it, I think.

Note - the target window does not need to be selected via mouse-cursor as mentioned above - that's just the default behavior when it's invoked without arguments. The entire interface is completely scriptable.

Just scroll a little more and...

   -root   This option indicates that the root window should  be  selected
           for  the  window  dump,  without requiring the user to select a
           window with the pointer.

   -id id  This option  indicates  that  the  window  with  the  specified
           resource  id  should  be  selected for the window dump, without
           requiring the user to select a window with the pointer.

If you'll take my advice you'll also look pretty closely at xdotool, though, admittedly it has limited relevance here. It scripts the mouse mostly, though it does offer some direct command-line interface to the X backend api - as @Gilles references. And it's pretty simple to use.

All that said, the primary issue is that your display is currently occupied. If your window must remain invisible it is possible to handle it in a few ways - though you'll have to try at them a little, I think, before you get them down. The way I would recommend is merely to configure your screen to be twice the size of your screen. That way you can just drag the window off of the screen and it will continue to update the display - but off screen. I can do this with nvidia's tools, and most can do this with xrandr, but, especially in Linux it seems, at least in my experience, display issues are often personal issues just because there are so many possible ways to configure them.

Another way this might be done is with a virtual X-server - such as xnest or xephyr. These servers nest an entire X-server within a window which can be backgrounded, or completely nonexistent if you prefer. Last I checked, which was some time ago unfortunately, these were using the xdummy-driver - and would therefore not be good choices for a video game that required video acceleration. Still, I'm sure your man pages could tell you more, and I can only hope I helped.

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.