-/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1997, 1998
+/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1997, 1998, 2003, 2004
* Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
Atom type;
int format;
unsigned long nitems, bytesafter;
- char *version;
+ unsigned char *version;
if (XGetWindowProperty (dpy, window,
XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
0, 1, False, XA_STRING,
&type, &format, &nitems, &bytesafter,
- (unsigned char **) &version)
+ &version)
== Success
&& type != None)
return True;
+/* Whether the given window is:
+ - the real root window;
+ - a direct child of the root window;
+ - a direct child of the window manager's decorations.
+ */
+Bool
+top_level_window_p (Screen *screen, Window window)
+{
+ Display *dpy = DisplayOfScreen (screen);
+ Window root, parent, *kids;
+ unsigned int nkids;
+
+ if (!XQueryTree (dpy, window, &root, &parent, &kids, &nkids))
+ return False;
+
+ if (window == root)
+ return True;
+
+ /* If our direct parent is the real root window, then yes. */
+ if (parent == root)
+ return True;
+ else
+ {
+ Atom type = None;
+ int format;
+ unsigned long nitems, bytesafter;
+ unsigned char *data;
+
+ /* If our direct parent has the WM_STATE property, then it is a
+ window manager decoration -- yes.
+ */
+ if (XGetWindowProperty (dpy, window,
+ XInternAtom (dpy, "WM_STATE", True),
+ 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &bytesafter,
+ (unsigned char **) &data)
+ == Success
+ && type != None)
+ return True;
+ }
+
+ /* Else, no. We're deep in a tree somewhere.
+ */
+ return False;
+}
+
+
+static Bool error_handler_hit_p = False;
static XErrorHandler old_ehandler = 0;
static int
BadWindow_ehandler (Display *dpy, XErrorEvent *error)
{
+ error_handler_hit_p = True;
if (error->error_code == BadWindow || error->error_code == BadDrawable)
return 0;
else if (!old_ehandler)
static void
install_screen_colormaps (Screen *screen)
{
- int i;
+ unsigned int i;
Display *dpy = DisplayOfScreen (screen);
- Window vroot, real_root;
+ Window real_root;
Window parent, *kids = 0;
unsigned int nkids = 0;
XSync (dpy, False);
old_ehandler = XSetErrorHandler (BadWindow_ehandler);
+ error_handler_hit_p = False;
- vroot = VirtualRootWindowOfScreen (screen);
- if (XQueryTree (dpy, vroot, &real_root, &parent, &kids, &nkids))
+ real_root = XRootWindowOfScreen (screen); /* not vroot */
+ if (XQueryTree (dpy, real_root, &real_root, &parent, &kids, &nkids))
for (i = 0; i < nkids; i++)
{
XWindowAttributes xgwa;
void
-grab_screen_image (Screen *screen, Window window)
+grab_screen_image_internal (Screen *screen, Window window)
{
Display *dpy = DisplayOfScreen (screen);
XWindowAttributes xgwa;
- Window real_root = XRootWindowOfScreen (screen); /* not vroot */
- Bool root_p = (window == real_root);
- Bool saver_p = xscreensaver_window_p (dpy, window);
+ Window real_root;
+ Bool root_p;
+ Bool saver_p;
Bool grab_mouse_p = False;
int unmap_time = 0;
+ real_root = XRootWindowOfScreen (screen); /* not vroot */
+ root_p = (window == real_root);
+ saver_p = xscreensaver_window_p (dpy, window);
+
+ XGetWindowAttributes (dpy, window, &xgwa);
+ screen = xgwa.screen;
+
if (saver_p)
/* I think this is redundant, but just to be safe... */
root_p = False;
if (grab_verbose_p)
{
- XWindowAttributes xgwa2;
fprintf(stderr,
"\n%s: window 0x%08lX root: %d saver: %d grab: %d wait: %.1f\n",
progname, (unsigned long) window,
root_p, saver_p, grab_mouse_p, ((double)unmap_time)/1000000.0);
- XGetWindowAttributes (dpy, window, &xgwa2);
fprintf(stderr, "%s: ", progname);
- describe_visual(stderr, screen, xgwa2.visual, False);
+ describe_visual(stderr, screen, xgwa.visual, False);
fprintf (stderr, "\n");
}
+
+ if (!root_p && !top_level_window_p (screen, window))
+ {
+ if (grab_verbose_p)
+ fprintf (stderr, "%s: not a top-level window: 0x%08lX: not grabbing\n",
+ progname, (unsigned long) window);
+ return;
+ }
+
+
if (!root_p)
XSetWindowBackgroundPixmap (dpy, window, None);
usleep(unmap_time); /* wait for everyone to swap in and handle exposes */
}
- XGetWindowAttributes (dpy, window, &xgwa);
-
if (!root_p)
{
#ifdef HAVE_READ_DISPLAY_EXTENSION
else /* root_p */
{
Pixmap pixmap;
- XWindowAttributes xgwa;
- XGetWindowAttributes(dpy, window, &xgwa);
pixmap = XCreatePixmap(dpy, window, xgwa.width, xgwa.height, xgwa.depth);
#ifdef HAVE_READ_DISPLAY_EXTENSION
if (! read_display(screen, window, pixmap, True))
#endif
{
- Window real_root = XRootWindowOfScreen (xgwa.screen); /* not vroot */
+ Window real_root = XRootWindowOfScreen (screen); /* not vroot */
XGCValues gcv;
GC gc;
/* Check to see if the server supports the extension, and bug out if not.
*/
if (! XReadDisplayQueryExtension (dpy, &rd_event_base, &rd_error_base))
- return False;
+ {
+ if (grab_verbose_p)
+ fprintf(stderr, "%s: no XReadDisplay extension\n", progname);
+ return False;
+ }
/* If this isn't a visual we know how to handle, bug out. We handle:
- = TrueColor in depths 8, 12, 16, and 32;
+ = TrueColor in depths 8, 12, 15, 16, and 32;
= PseudoColor and DirectColor in depths 8 and 12.
*/
XGetWindowAttributes(dpy, window, &xgwa);
class = visual_class (screen, xgwa.visual);
if (class == TrueColor)
{
- if (xgwa.depth != 8 && xgwa.depth != 12 && xgwa.depth != 16 &&
- xgwa.depth != 24 && xgwa.depth != 32)
- return False;
+ if (xgwa.depth != 8 && xgwa.depth != 12 && xgwa.depth != 15 &&
+ xgwa.depth != 16 && xgwa.depth != 24 && xgwa.depth != 32)
+ {
+ if (grab_verbose_p)
+ fprintf(stderr, "%s: TrueColor depth %d unsupported\n",
+ progname, xgwa.depth);
+ return False;
+ }
}
else if (class == PseudoColor || class == DirectColor)
{
if (xgwa.depth != 8 && xgwa.depth != 12)
- return False;
+ {
+ if (grab_verbose_p)
+ fprintf(stderr, "%s: Pseudo/DirectColor depth %d unsupported\n",
+ progname, xgwa.depth);
+ return False;
+ }
else
/* Allocate a TrueColor-like spread of colors for the image. */
remap_p = True;
image = XReadDisplay (dpy, window, xgwa.x, xgwa.y, xgwa.width, xgwa.height,
hints, &hints);
if (!image)
- return False;
+ {
+ if (grab_verbose_p)
+ fprintf(stderr, "%s: XReadDisplay() failed\n", progname);
+ return False;
+ }
if (!image->data)
{
+ if (grab_verbose_p)
+ fprintf(stderr, "%s: XReadDisplay() returned no data\n", progname);
XDestroyImage(image);
return False;
}
xgwa.width, xgwa.height,
8, 0);
if (!image2)
- return False;
+ {
+ if (grab_verbose_p)
+ fprintf(stderr, "%s: out of memory?\n", progname);
+ return False;
+ }
if (grab_verbose_p)
fprintf(stderr, "%s: converting from depth %d to depth %d\n",
pixel = ((r >> 5) | ((g >> 5) << 3) | ((b >> 6) << 6));
else if (xgwa.depth == 12)
pixel = ((r >> 4) | ((g >> 4) << 4) | ((b >> 4) << 8));
- else if (xgwa.depth == 16)
- pixel = ((r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10));
+ else if (xgwa.depth == 16 || xgwa.depth == 15)
+ /* Gah! I don't understand why these are in the other order. */
+ pixel = (((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3)));
else
abort();