X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=utils%2Fgrabscreen.c;h=6bf8cc8b848bdd8e6edd5ce57025a8642a6b44bb;hp=1dba4328d509e4b7a4539d8b037381028b480ae2;hb=481b95e2617b69e6fd4444432747d7e1e0c3dc85;hpb=f3e0240915ed9f9b3a61781f5c7002d587563fe0 diff --git a/utils/grabscreen.c b/utils/grabscreen.c index 1dba4328..6bf8cc8b 100644 --- a/utils/grabscreen.c +++ b/utils/grabscreen.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1997 +/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1997, 1998 * Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its @@ -18,6 +18,7 @@ */ #include "utils.h" +#include "yarandom.h" #include #include @@ -33,6 +34,9 @@ #include "usleep.h" #include "colors.h" #include "grabscreen.h" +#include "sgivideo.h" +#include "visual.h" +#include "resources.h" #include "vroot.h" #undef RootWindowOfScreen @@ -41,7 +45,6 @@ #ifdef HAVE_READ_DISPLAY_EXTENSION -# include "visual.h" # include static Bool read_display (Screen *, Window, Pixmap, Bool); #endif /* HAVE_READ_DISPLAY_EXTENSION */ @@ -49,6 +52,10 @@ static void copy_default_colormap_contents (Screen *, Colormap, Visual *); +#if defined(HAVE_READ_DISPLAY_EXTENSION) || defined(HAVE_SGI_VIDEO) +static void make_cubic_colormap (Screen *, Window, Visual *); +#endif + static Bool MapNotify_event_p (Display *dpy, XEvent *event, XPointer window) @@ -131,6 +138,25 @@ BadWindow_ehandler (Display *dpy, XErrorEvent *error) } +/* XCopyArea seems not to work right on SGI O2s if you draw in SubwindowMode + on a window whose depth is not the maximal depth of the screen? Or + something. Anyway, things don't work unless we: use SubwindowMode for + the real root window (or a legitimate virtual root window); but do not + use SubwindowMode for the xscreensaver window. I make no attempt to + explain. + */ +Bool +use_subwindow_mode_p(Screen *screen, Window window) +{ + if (window != VirtualRootWindowOfScreen(screen)) + return False; + else if (xscreensaver_window_p(DisplayOfScreen(screen), window)) + return False; + else + return True; +} + + /* Install the colormaps of all visible windows, deepest first. This should leave the colormaps of the topmost windows installed (if only N colormaps can be installed at a time, then only the @@ -174,8 +200,8 @@ install_screen_colormaps (Screen *screen) } -void -grab_screen_image (Screen *screen, Window window) +static void +grab_screen_image_1 (Screen *screen, Window window) { Display *dpy = DisplayOfScreen (screen); XWindowAttributes xgwa; @@ -196,10 +222,18 @@ grab_screen_image (Screen *screen, Window window) if (!root_p) { + double unmap = 0; if (saver_p) - unmap_time = 2500000; /* 2 1/2 seconds */ + { + unmap = get_float_resource("grabRootDelay", "Seconds"); + if (unmap <= 0.00001 || unmap > 20) unmap = 2.5; + } else - unmap_time = 660000; /* 2/3rd second */ + { + unmap = get_float_resource("grabWindowDelay", "Seconds"); + if (unmap <= 0.00001 || unmap > 20) unmap = 0.66; + } + unmap_time = unmap * 100000; } #ifdef DEBUG @@ -211,7 +245,8 @@ grab_screen_image (Screen *screen, Window window) XWindowAttributes xgwa2; XGetWindowAttributes (dpy, window, &xgwa2); fprintf(stderr, "%s: ", progname); - describe_visual(stderr, screen, xgwa2.visual); + describe_visual(stderr, screen, xgwa2.visual, ####); + fprintf (stderr, "\n"); } #endif /* DEBUG */ @@ -293,6 +328,42 @@ grab_screen_image (Screen *screen, Window window) XSync (dpy, True); } +void +grab_screen_image (Screen *screen, Window window) +{ +#ifdef HAVE_SGI_VIDEO + char c, *s = get_string_resource("grabVideoProbability", "Float"); + double prob = -1; + if (!s || + (1 != sscanf (s, " %lf %c", &prob, &c)) || + prob < 0 || + prob > 1) + prob = 0.5; + + if ((random() % 100) < ((int) (100 * prob))) + { + XWindowAttributes xgwa; + Display *dpy = DisplayOfScreen (screen); + XGetWindowAttributes (dpy, window, &xgwa); +# ifdef DEBUG + fprintf(stderr, "%s: trying to grab from video...\n", progname); +# endif /* DEBUG */ + if (grab_video_frame (screen, xgwa.visual, window)) + { + if (xgwa.depth < 24) + { + int class = visual_class (screen, xgwa.visual); + if (class == PseudoColor || class == DirectColor) + make_cubic_colormap (screen, window, xgwa.visual); + } + return; + } + } +#endif /* HAVE_SGI_VIDEO */ + + grab_screen_image_1 (screen, window); +} + /* When we are grabbing and manipulating a screen image, it's important that we use the same colormap it originally had. So, if the screensaver was @@ -345,7 +416,35 @@ copy_default_colormap_contents (Screen *screen, got_cells = max_cells; allocate_writable_colors (dpy, to_cmap, pixels, &got_cells); - XStoreColors (dpy, to_cmap, old_colors, got_cells); + +#ifdef DEBUG + if (got_cells != max_cells) + fprintf(stderr, "%s: got only %d of %d cells\n", progname, + got_cells, max_cells); +#endif /* DEBUG */ + + if (got_cells <= 0) /* we're screwed */ + ; + else if (got_cells == max_cells && /* we're golden */ + from_cells == to_cells) + XStoreColors (dpy, to_cmap, old_colors, got_cells); + else /* try to cope... */ + { + for (i = 0; i < got_cells; i++) + { + XColor *c = old_colors + i; + int j; + for (j = 0; j < got_cells; j++) + if (pixels[j] == c->pixel) + { + /* only store this color value if this is one of the pixels + we were able to allocate. */ + XStoreColors (dpy, to_cmap, c, 1); + break; + } + } + } + #ifdef DEBUG fprintf(stderr, "%s: installing copy of default colormap\n", progname); @@ -368,8 +467,6 @@ copy_default_colormap_contents (Screen *screen, #ifdef HAVE_READ_DISPLAY_EXTENSION -static void make_cubic_colormap (Screen *, Window, Visual *); - static Bool read_display (Screen *screen, Window window, Pixmap into_pixmap, Bool dont_wait) @@ -426,13 +523,23 @@ read_display (Screen *screen, Window window, Pixmap into_pixmap, return False; } - /* Uh, this can't be right, can it? But it's necessary. X sucks. - If the visual is of depth 24, but the image came back as depth 32, - hack it to be 24 lest we get a BadMatch from XPutImage. (I presume - I'm expected to look at the server's pixmap formats or some such - nonsense... but fuck it. + /* XReadDisplay tends to LIE about the depth of the image it read. + It is returning an XImage which has `depth' and `bits_per_pixel' + confused! + + That is, on a 24-bit display, where all visuals claim depth 24, and + where XGetImage would return an XImage with depth 24, and where + XPutImage will get a BadMatch with images that are not depth 24, + XReadDisplay is returning images with depth 32! Fuckwits! + + So if the visual is of depth 24, but the image came back as depth 32, + hack it to be 24 lest we get a BadMatch from XPutImage. + + I wonder what happens on an 8-bit SGI... Probably it still returns + an image claiming depth 32? Certainly it can't be 8. So, let's just + smash it to 32... */ - if (xgwa.depth == 24 && image->depth == 32) + if (image->depth == 32 /* && xgwa.depth == 24 */ ) image->depth = 24; /* If the visual of the window/pixmap into which we're going to draw is @@ -532,7 +639,14 @@ read_display (Screen *screen, Window window, Pixmap into_pixmap, return True; } +#endif /* HAVE_READ_DISPLAY_EXTENSION */ + + +#if defined(HAVE_READ_DISPLAY_EXTENSION) || defined(HAVE_SGI_VIDEO) +/* Makes and installs a colormap that makes a PseudoColor or DirectColor + visual behave like a TrueColor visual of the same depth. + */ static void make_cubic_colormap (Screen *screen, Window window, Visual *visual) { @@ -606,5 +720,4 @@ make_cubic_colormap (Screen *screen, Window window, Visual *visual) XInstallColormap (dpy, cmap); } - -#endif /* HAVE_READ_DISPLAY_EXTENSION */ +#endif /* HAVE_READ_DISPLAY_EXTENSION || HAVE_SGI_VIDEO */