X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=driver%2Fwindows.c;h=9dbb5004cfbe5428dabe4486803e038d64c49629;hp=7ee76045134b9cf0967b73821c2582aa9ec545fa;hb=6b1c86cf395f59389e4ece4ea8f4bea2c332745b;hpb=9c9d475ff889ed8be02e8ce8c17da28b93278fca diff --git a/driver/windows.c b/driver/windows.c index 7ee76045..9dbb5004 100644 --- a/driver/windows.c +++ b/driver/windows.c @@ -1,5 +1,5 @@ /* windows.c --- turning the screen black; dealing with visuals, virtual roots. - * xscreensaver, Copyright (c) 1991-2004 Jamie Zawinski + * xscreensaver, Copyright (c) 1991-2008 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -30,7 +30,7 @@ #endif /* HAVE_UNAME */ #include -#include /* for CARD32 */ +/* #include / * for CARD32 */ #include #include /* for XSetClassHint() */ #include @@ -39,6 +39,13 @@ #include #include +/* You might think that to store an array of 32-bit quantities onto a + server-side property, you would pass an array of 32-bit data quantities + into XChangeProperty(). You would be wrong. You have to use an array + of longs, even if long is 64 bits (using 32 of each 64.) + */ +typedef long PROP32; + #ifdef HAVE_MIT_SAVER_EXTENSION # include #endif /* HAVE_MIT_SAVER_EXTENSION */ @@ -269,8 +276,24 @@ grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor, fprintf (stderr, "%s: couldn't grab pointer! (%s)\n", blurb(), grab_string(mstatus)); - return (kstatus == GrabSuccess || - mstatus == GrabSuccess); + + /* When should we allow blanking to proceed? The current theory + is that a keyboard grab is manditory; a mouse grab is optional. + + - If we don't have a keyboard grab, then we won't be able to + read a password to unlock, so the kbd grab is manditory. + (We can't conditionalize this on locked_p, because someone + might run "xscreensaver-command -lock" at any time.) + + - If we don't have a mouse grab, then we might not see mouse + clicks as a signal to unblank -- but we will still see kbd + activity, so that's not a disaster. + */ + + if (kstatus != GrabSuccess) /* Do not blank without a kbd grab. */ + return False; + + return True; /* Grab is good, go ahead and blank. */ } static void @@ -348,25 +371,26 @@ ensure_no_screensaver_running (Display *dpy, Screen *screen) Atom type; int format; unsigned long nitems, bytesafter; - char *version; + unsigned char *version; if (XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_VERSION, 0, 1, False, XA_STRING, &type, &format, &nitems, - &bytesafter, (unsigned char **) &version) + &bytesafter, &version) == Success && type != None) { - char *id; + unsigned char *id; if (!XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_ID, 0, 512, False, XA_STRING, &type, &format, &nitems, - &bytesafter, (unsigned char **) &id) + &bytesafter, &id) == Success || type == None) - id = "???"; + id = (unsigned char *) "???"; fprintf (stderr, "%s: already running on display %s (window 0x%x)\n from process %s.\n", - blurb(), DisplayString (dpy), (int) kids [i], id); + blurb(), DisplayString (dpy), (int) kids [i], + (char *) id); status = True; } } @@ -434,7 +458,7 @@ kill_xsetroot_data_1 (Display *dpy, Window window, Atom type; int format; unsigned long nitems, bytesafter; - Pixmap *dataP = 0; + unsigned char *dataP = 0; /* If the user has been using xv or xsetroot as a screensaver (to display an image on the screensaver window, as a kind of slideshow) then the @@ -454,17 +478,18 @@ kill_xsetroot_data_1 (Display *dpy, Window window, */ if (XGetWindowProperty (dpy, window, prop, 0, 1, True, AnyPropertyType, &type, &format, &nitems, - &bytesafter, (unsigned char **) &dataP) + &bytesafter, &dataP) == Success && type != None) { - if (dataP && *dataP && type == XA_PIXMAP && format == 32 && + Pixmap *pixP = (Pixmap *) dataP; + if (pixP && *pixP && type == XA_PIXMAP && format == 32 && nitems == 1 && bytesafter == 0) { if (verbose_p) fprintf (stderr, "%s: destroying %s data (0x%lX).\n", - blurb(), atom_name, *dataP); - safe_XKillClient (dpy, *dataP); + blurb(), atom_name, *pixP); + safe_XKillClient (dpy, *pixP); } else fprintf (stderr, @@ -472,7 +497,7 @@ kill_xsetroot_data_1 (Display *dpy, Window window, "\t%lu, %lu; type: %lu, format: %d, " "nitems: %lu, bytesafter %ld\n", blurb(), atom_name, - (unsigned long) dataP, (dataP ? *dataP : 0), type, + (unsigned long) pixP, (pixP ? *pixP : 0), type, format, nitems, bytesafter); } } @@ -522,7 +547,8 @@ save_real_vroot (saver_screen_info *ssi) Atom type; int format; unsigned long nitems, bytesafter; - Window *vrootP = 0; + unsigned char *dataP = 0; + Window *vrootP; int j; /* Skip this window if it is the xscreensaver window of any other @@ -537,11 +563,13 @@ save_real_vroot (saver_screen_info *ssi) if (XGetWindowProperty (dpy, kids[i], XA_VROOT, 0, 1, False, XA_WINDOW, &type, &format, &nitems, &bytesafter, - (unsigned char **) &vrootP) + &dataP) != Success) continue; - if (! vrootP) + if (! dataP) continue; + + vrootP = (Window *) dataP; if (ssi->real_vroot) { if (*vrootP == ssi->screensaver_window) abort (); @@ -781,9 +809,14 @@ saver_sighup_handler (int sig) fprintf (stderr, "%s: %s received: restarting...\n", blurb(), signal_name(sig)); - unblank_screen (si); - kill_screenhack (si); - XSync (si->dpy, False); + + if (si->screen_blanked_p) + { + unblank_screen (si); + kill_screenhack (si); + XSync (si->dpy, False); + } + restart_process (si); /* Does not return */ abort (); } @@ -940,16 +973,16 @@ store_saver_id (saver_screen_info *ssi) void store_saver_status (saver_info *si) { - CARD32 *status; + PROP32 *status; int size = si->nscreens + 2; int i; - status = (CARD32 *) calloc (size, sizeof(CARD32)); + status = (PROP32 *) calloc (size, sizeof(PROP32)); - status[0] = (CARD32) (si->screen_blanked_p + status[0] = (PROP32) (si->screen_blanked_p ? (si->locked_p ? XA_LOCK : XA_BLANK) : 0); - status[1] = (CARD32) si->blank_time; + status[1] = (PROP32) si->blank_time; for (i = 0; i < si->nscreens; i++) { @@ -1011,12 +1044,14 @@ get_screen_viewport (saver_screen_info *ssi, { target_x = ssi->x; target_y = ssi->y; + which = ssi->number; } /* Find the Xinerama rectangle that contains the mouse position. */ for (i = 0; i < si->nscreens; i++) { - if (target_x >= si->screens[i].x && + if (which == -1 && + target_x >= si->screens[i].x && target_y >= si->screens[i].y && target_x < si->screens[i].x + si->screens[i].width && target_y < si->screens[i].y + si->screens[i].height) @@ -1386,7 +1421,12 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) attrs.backing_pixel = ssi->black_pixel; attrs.border_pixel = ssi->black_pixel; - if (p->debug_p && !p->quad_p) width = width / 2; + if (p->debug_p +# ifdef QUAD_MODE + && !p->quad_p +# endif + ) + width = width / 2; if (!p->verbose_p || printed_visual_info) ; @@ -1564,9 +1604,21 @@ resize_screensaver_window (saver_info *si) */ int nscreens; XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens); - if (nscreens != si->nscreens) abort(); + + if (nscreens != si->nscreens) { + /* Apparently some Xinerama implementations let you use a hot-key + to change the number of screens in use! This is, of course, + documented nowhere. Let's try to do something marginally less + bad than crashing. + */ + fprintf (stderr, "%s: bad craziness: xinerama screen count changed " + "from %d to %d!\n", blurb(), si->nscreens, nscreens); + if (nscreens > si->nscreens) + nscreens = si->nscreens; + } + if (!xsi) abort(); - for (i = 0; i < si->nscreens; i++) + for (i = 0; i < nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; if (p->verbose_p && @@ -1644,7 +1696,12 @@ resize_screensaver_window (saver_info *si) changes.height = height; changes.border_width = 0; - if (p->debug_p && !p->quad_p) changes.width = changes.width / 2; + if (p->debug_p +# ifdef QUAD_MODE + && !p->quad_p +# endif + ) + changes.width = changes.width / 2; if (p->verbose_p) fprintf (stderr, @@ -1829,12 +1886,17 @@ blank_screen (saver_info *si) mscreen); +# if 0 if (si->using_mit_saver_extension || si->using_sgi_saver_extension) /* If we're using a server extension, then failure to get a grab is not a big deal -- even without the grab, we will still be able to un-blank when there is user activity, since the server will tell us. */ + /* #### No, that's not true: if we don't have a keyboard grab, + then we can't read passwords to unlock. + */ ok = True; +# endif /* 0 */ if (!ok) return False; @@ -1947,7 +2009,7 @@ unblank_screen (saver_info *si) /* If the focus window does has a non-default colormap, then install that colormap as well. (On SGIs, this will cause both the root map - and the focus map to be installed simultaniously. It'd be nice to + and the focus map to be installed simultaneously. It'd be nice to pick up the other colormaps that had been installed, too; perhaps XListInstalledColormaps could be used for that?) */ @@ -2043,6 +2105,13 @@ select_visual (saver_screen_info *ssi, const char *visual_name) Visual *new_v = 0; Bool got_it; + /* On some systems (most recently, MacOS X) OpenGL programs get confused + when you kill one and re-start another on the same window. So maybe + it's best to just always destroy and recreate the xscreensaver window + when changing hacks, instead of trying to reuse the old one? + */ + Bool always_recreate_window_p = True; + if (visual_name && *visual_name) { if (!strcmp(visual_name, "default-i") || @@ -2086,7 +2155,8 @@ select_visual (saver_screen_info *ssi, const char *visual_name) ssi->install_cmap_p = install_cmap_p; if (new_v && - ((ssi->current_visual != new_v) || + (always_recreate_window_p || + (ssi->current_visual != new_v) || (install_cmap_p != was_installed_p))) { Colormap old_c = ssi->cmap;