X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fwindows.c;h=4daa0607ea902bac5e35fd1d2ffa640a10e95e29;hb=ce3185de9d9705e259f2b60dd4b5509007fa17d4;hp=5dcc3d355b4fb7303934c5450b33ee793b8b2c4c;hpb=186b0b9f1638444c650c9273df38085e0db71e4a;p=xscreensaver diff --git a/driver/windows.c b/driver/windows.c index 5dcc3d35..4daa0607 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-1997 Jamie Zawinski + * xscreensaver, Copyright (c) 1991-1998 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 @@ -65,7 +65,7 @@ extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ Atom XA_VROOT, XA_XSETROOT_ID; -Atom XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID; +Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID; Atom XA_SCREENSAVER_TIME; @@ -80,50 +80,134 @@ static void store_activate_time (saver_info *si, Bool use_last_p); Button1MotionMask | Button2MotionMask | Button3MotionMask | \ Button4MotionMask | Button5MotionMask | ButtonMotionMask) -/* I don't really understand Sync vs Async, but these seem to work... */ -#define grab_kbd(dpy,win) \ - XGrabKeyboard ((dpy), (win), True, GrabModeSync, GrabModeAsync, CurrentTime) -#define grab_mouse(dpy,win,cursor) \ - XGrabPointer ((dpy), (win), True, ALL_POINTER_EVENTS, \ - GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime) + +static int +grab_kbd(saver_info *si, Window w) +{ + saver_preferences *p = &si->prefs; + int status = XGrabKeyboard (si->dpy, w, True, + /* I don't really understand Sync vs Async, + but these seem to work... */ + GrabModeSync, GrabModeAsync, + CurrentTime); + if (status == GrabSuccess) + si->keyboard_grab_window = w; + + if (p->verbose_p) + fprintf(stderr, "%s: grabbing keyboard on 0x%x... %s.\n", + blurb(), (unsigned long) w, + (status == GrabSuccess ? "GrabSuccess" : + status == AlreadyGrabbed ? "AlreadyGrabbed" : + status == GrabInvalidTime ? "GrabInvalidTime" : + status == GrabNotViewable ? "GrabNotViewable" : + status == GrabFrozen ? "GrabFrozen" : + "???")); + + return status; +} + +static const char * +grab_string(int status) +{ + switch (status) + { + case GrabSuccess: return "GrabSuccess"; break; + case AlreadyGrabbed: return "AlreadyGrabbed"; break; + case GrabInvalidTime: return "GrabInvalidTime"; break; + case GrabNotViewable: return "GrabNotViewable"; break; + case GrabFrozen: return "GrabFrozen"; break; + default: + { + static char foo[255]; + sprintf(foo, "unknown status: %d", status); + return foo; + } + } +} + + +static int +grab_mouse (saver_info *si, Window w, Cursor cursor) +{ + saver_preferences *p = &si->prefs; + int status = XGrabPointer (si->dpy, w, True, ALL_POINTER_EVENTS, + GrabModeAsync, GrabModeAsync, None, + cursor, CurrentTime); + if (status == GrabSuccess) + si->mouse_grab_window = w; + + if (p->verbose_p) + fprintf(stderr, "%s: grabbing mouse on 0x%x... %s.\n", + blurb(), (unsigned long) w, grab_string(status)); + return status; +} + + +static void +ungrab_kbd(saver_info *si) +{ + saver_preferences *p = &si->prefs; + XUngrabKeyboard(si->dpy, CurrentTime); + if (p->verbose_p) + fprintf(stderr, "%s: ungrabbing keyboard (was 0x%x).\n", blurb(), + (unsigned long) si->keyboard_grab_window); + si->keyboard_grab_window = 0; +} + + +static void +ungrab_mouse(saver_info *si) +{ + saver_preferences *p = &si->prefs; + XUngrabPointer(si->dpy, CurrentTime); + if (p->verbose_p) + fprintf(stderr, "%s: ungrabbing mouse (was 0x%x).\n", blurb(), + (unsigned long) si->mouse_grab_window); + si->mouse_grab_window = 0; +} + void -grab_keyboard_and_mouse (Display *dpy, Window window, Cursor cursor) +grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor) { Status status; - XSync (dpy, False); + XSync (si->dpy, False); - status = grab_kbd (dpy, window); + status = grab_kbd (si, window); if (status != GrabSuccess) { /* try again in a second */ sleep (1); - status = grab_kbd (dpy, window); + status = grab_kbd (si, window); if (status != GrabSuccess) - fprintf (stderr, "%s: couldn't grab keyboard! (%d)\n", - progname, status); + fprintf (stderr, "%s: couldn't grab keyboard! (%s)\n", + blurb(), grab_string(status)); } - status = grab_mouse (dpy, window, cursor); + + status = grab_mouse (si, window, cursor); if (status != GrabSuccess) { /* try again in a second */ sleep (1); - status = grab_mouse (dpy, window, cursor); + status = grab_mouse (si, window, cursor); if (status != GrabSuccess) - fprintf (stderr, "%s: couldn't grab pointer! (%d)\n", - progname, status); + fprintf (stderr, "%s: couldn't grab pointer! (%s)\n", + blurb(), grab_string(status)); } } void -ungrab_keyboard_and_mouse (Display *dpy) +ungrab_keyboard_and_mouse (saver_info *si) { - XUngrabPointer (dpy, CurrentTime); - XUngrabKeyboard (dpy, CurrentTime); + ungrab_mouse (si); + ungrab_kbd (si); } -void +/* Prints an error message to stderr and returns True if there is another + xscreensaver running already. Silently returns False otherwise. */ +Bool ensure_no_screensaver_running (Display *dpy, Screen *screen) { + Bool status = 0; int i; Window root = RootWindowOfScreen (screen); Window root2, parent, *kids; @@ -159,14 +243,15 @@ ensure_no_screensaver_running (Display *dpy, Screen *screen) fprintf (stderr, "%s: already running on display %s (window 0x%x)\n from process %s.\n", - progname, DisplayString (dpy), (int) kids [i], id); - exit (1); + blurb(), DisplayString (dpy), (int) kids [i], id); + status = True; } } if (kids) XFree ((char *) kids); XSync (dpy, False); XSetErrorHandler (old_handler); + return status; } @@ -183,7 +268,7 @@ store_vroot_property (Display *dpy, Window win, Window value) #if 0 if (p->verbose_p) fprintf (stderr, - "%s: storing XA_VROOT = 0x%x (%s) = 0x%x (%s)\n", progname, + "%s: storing XA_VROOT = 0x%x (%s) = 0x%x (%s)\n", blurb(), win, (win == screensaver_window ? "ScreenSaver" : (win == real_vroot ? "VRoot" : @@ -202,7 +287,7 @@ remove_vroot_property (Display *dpy, Window win) { #if 0 if (p->verbose_p) - fprintf (stderr, "%s: removing XA_VROOT from 0x%x (%s)\n", progname, win, + fprintf (stderr, "%s: removing XA_VROOT from 0x%x (%s)\n", blurb(), win, (win == screensaver_window ? "ScreenSaver" : (win == real_vroot ? "VRoot" : (win == real_vroot_value ? "Vroot_value" : "???")))); @@ -241,14 +326,14 @@ kill_xsetroot_data (Display *dpy, Window window, Bool verbose_p) nitems == 1 && bytesafter == 0) { if (verbose_p) - printf ("%s: destroying xsetroot data (0x%lX).\n", - progname, *dataP); + fprintf (stderr, "%s: destroying xsetroot data (0x%lX).\n", + blurb(), *dataP); XKillClient (dpy, *dataP); } else fprintf (stderr, "%s: deleted unrecognised _XSETROOT_ID property: \n\ %lu, %lu; type: %lu, format: %d, nitems: %lu, bytesafter %ld\n", - progname, (unsigned long) dataP, (dataP ? *dataP : 0), type, + blurb(), (unsigned long) dataP, (dataP ? *dataP : 0), type, format, nitems, bytesafter); } } @@ -294,7 +379,7 @@ save_real_vroot (saver_screen_info *ssi) if (*vrootP == ssi->screensaver_window) abort (); fprintf (stderr, "%s: more than one virtual root window found (0x%x and 0x%x).\n", - progname, (int) ssi->real_vroot, (int) kids [i]); + blurb(), (int) ssi->real_vroot, (int) kids [i]); exit (1); } ssi->real_vroot = kids [i]; @@ -318,8 +403,9 @@ restore_real_vroot_2 (saver_screen_info *ssi) saver_info *si = ssi->global; saver_preferences *p = &si->prefs; if (p->verbose_p && ssi->real_vroot) - printf ("%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n", - progname, (unsigned long) ssi->real_vroot); + fprintf (stderr, + "%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n", + blurb(), (unsigned long) ssi->real_vroot); remove_vroot_property (si->dpy, ssi->screensaver_window); if (ssi->real_vroot) { @@ -444,7 +530,7 @@ restore_real_vroot_handler (int sig) signal (sig, SIG_DFL); if (restore_real_vroot_1 (si)) fprintf (real_stderr, "\n%s: %s intercepted, vroot restored.\n", - progname, signal_name(sig)); + blurb(), signal_name(sig)); kill (getpid (), sig); } @@ -458,9 +544,9 @@ catch_signal (saver_info *si, int sig, Bool on_p) if (((long) signal (sig, restore_real_vroot_handler)) == -1L) { char buf [255]; - sprintf (buf, "%s: couldn't catch %s", progname, signal_name(sig)); + sprintf (buf, "%s: couldn't catch %s", blurb(), signal_name(sig)); perror (buf); - saver_exit (si, 1); + saver_exit (si, 1, 0); } } } @@ -469,8 +555,8 @@ static void handle_signals (saver_info *si, Bool on_p) { #if 0 - if (on_p) printf ("handling signals\n"); - else printf ("unhandling signals\n"); + if (on_p) fprintf (stderr, "handling signals\n"); + else fprintf (stderr, "unhandling signals\n"); #endif catch_signal (si, SIGHUP, on_p); @@ -502,7 +588,7 @@ handle_signals (saver_info *si, Bool on_p) } void -saver_exit (saver_info *si, int status) +saver_exit (saver_info *si, int status, const char *dump_core_reason) { saver_preferences *p = &si->prefs; static Bool exiting = False; @@ -517,9 +603,9 @@ saver_exit (saver_info *si, int status) emergency_kill_subproc (si); if (vrs && (p->verbose_p || status != 0)) - fprintf (real_stderr, "%s: vroot restored, exiting.\n", progname); + fprintf (real_stderr, "%s: vroot restored, exiting.\n", blurb()); else if (p->verbose_p) - fprintf (real_stderr, "%s: no vroot to restore; exiting.\n", progname); + fprintf (real_stderr, "%s: no vroot to restore; exiting.\n", blurb()); fflush(real_stdout); @@ -528,11 +614,50 @@ saver_exit (saver_info *si, int status) else if (status == 1) status = -1; #endif -#ifdef DEBUG - if (si->prefs.debug_p) - /* Do this to drop a core file, so that we can get a stack trace. */ - abort(); + if (si->prefs.debug_p && !dump_core_reason) + dump_core_reason = "because of -debug"; + + if (dump_core_reason) + { +#if 0 + if (si->locking_disabled_p && + si->nolock_reason && + *si->nolock_reason) + { + /* If locking is disabled, it's because xscreensaver was launched + by root, and has relinquished its user id (most likely we are + now running as "nobody".) This means we won't be able to dump + core, since "nobody" can't write files; so don't even try. + */ + fprintf(real_stderr, "%s: NOT dumping core (%s)\n", blurb(), + si->nolock_reason); + } + else #endif + { + /* Note that the Linux man page for setuid() says If uid is + different from the old effective uid, the process will be + forbidden from leaving core dumps. + */ + + char cwd[4096]; /* should really be PATH_MAX, but who cares. */ + fprintf(real_stderr, "%s: dumping core (%s)\n", blurb(), + dump_core_reason); + +# if defined(HAVE_GETCWD) + getcwd (cwd, sizeof(cwd)); +# elif defined(HAVE_GETWD) + getwd (cwd); +# else + strcpy(cwd, "unknown."); +# endif + fprintf (real_stderr, "%s: current directory is %s\n", blurb(), cwd); + describe_uids (si, real_stderr); + + /* Do this to drop a core file, so that we can get a stack trace. */ + abort(); + } + } exit (status); } @@ -558,6 +683,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) { saver_info *si = ssi->global; saver_preferences *p = &si->prefs; + Bool install_cmap_p = (ssi->install_cmap_p || p->install_cmap_p); /* This resets the screensaver window as fully as possible, since there's no way of knowing what some random client may have done to us in the @@ -578,8 +704,10 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) if (ssi->cmap == DefaultColormapOfScreen (ssi->screen)) ssi->cmap = 0; - if (p->install_cmap_p || - ssi->current_visual != DefaultVisualOfScreen (ssi->screen)) + if (ssi->current_visual != DefaultVisualOfScreen (ssi->screen)) + install_cmap_p = True; + + if (install_cmap_p) { if (! ssi->cmap) { @@ -591,31 +719,18 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) } else { + Colormap def_cmap = DefaultColormapOfScreen (ssi->screen); if (ssi->cmap) { XFreeColors (si->dpy, ssi->cmap, &ssi->black_pixel, 1, 0); - if (ssi->cmap != ssi->demo_cmap) + if (ssi->cmap != ssi->demo_cmap && + ssi->cmap != def_cmap) XFreeColormap (si->dpy, ssi->cmap); } - ssi->cmap = DefaultColormapOfScreen (ssi->screen); + ssi->cmap = def_cmap; ssi->black_pixel = BlackPixelOfScreen (ssi->screen); } -#if 0 - if (cmap2) - { - XFreeColormap (si->dpy, cmap2); - cmap2 = 0; - } - - if (p->fade_p) - { - cmap2 = copy_colormap (si->screen, ssi->current_visual, ssi->cmap, 0); - if (! cmap2) - p->fade_p = p->unfade_p = 0; - } -#endif - attrmask = (CWOverrideRedirect | CWEventMask | CWBackingStore | CWColormap | CWBackPixel | CWBackingPixel | CWBorderPixel); attrs.override_redirect = True; @@ -634,24 +749,25 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) attrs.backing_pixel = ssi->black_pixel; attrs.border_pixel = ssi->black_pixel; -#ifdef DEBUG if (p->debug_p) width = width / 2; -#endif /* DEBUG */ if (!p->verbose_p || printed_visual_info) ; else if (ssi->current_visual == DefaultVisualOfScreen (ssi->screen)) { - fprintf (stderr, "%s: using default visual ", progname); - describe_visual (stderr, ssi->screen, ssi->current_visual); + fprintf (stderr, "%s: using default visual ", blurb()); + describe_visual (stderr, ssi->screen, ssi->current_visual, + install_cmap_p); } else { - fprintf (stderr, "%s: using visual: ", progname); - describe_visual (stderr, ssi->screen, ssi->current_visual); - fprintf (stderr, "%s: default visual: ", progname); + fprintf (stderr, "%s: using visual: ", blurb()); + describe_visual (stderr, ssi->screen, ssi->current_visual, + install_cmap_p); + fprintf (stderr, "%s: default visual: ", blurb()); describe_visual (stderr, ssi->screen, - DefaultVisualOfScreen (ssi->screen)); + DefaultVisualOfScreen (ssi->screen), + ssi->install_cmap_p); } printed_visual_info = True; @@ -731,7 +847,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) store_activate_time(si, True); if (p->verbose_p) fprintf (stderr, "%s: saver window is 0x%lx.\n", - progname, (unsigned long) ssi->screensaver_window); + blurb(), (unsigned long) ssi->screensaver_window); } #ifdef HAVE_MIT_SAVER_EXTENSION @@ -819,65 +935,64 @@ raise_window (saver_info *si, if (p->fade_p && !inhibit_fade && !si->demo_mode_p) { - int grabbed = -1; + Window *current_windows = (Window *) + calloc(sizeof(Window), si->nscreens); Colormap *current_maps = (Colormap *) calloc(sizeof(Colormap), si->nscreens); for (i = 0; i < si->nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; + current_windows[i] = ssi->screensaver_window; current_maps[i] = (between_hacks_p ? ssi->cmap : DefaultColormapOfScreen (ssi->screen)); + /* Ensure that the default background of the window is really black, + not a pixmap or something. (This does not clear the window.) */ + XSetWindowBackground (si->dpy, ssi->screensaver_window, + ssi->black_pixel); } - if (p->verbose_p) fprintf (stderr, "%s: fading... ", progname); + if (p->verbose_p) fprintf (stderr, "%s: fading...\n", blurb()); - XGrabServer (si->dpy); - - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; + XGrabServer (si->dpy); /* ############ DANGER! */ - /* grab and blacken mouse on the root window (saver not mapped yet) - */ - if (grabbed != GrabSuccess) - grabbed = grab_mouse (si->dpy, ssi->screensaver_window, - (si->demo_mode_p ? 0 : ssi->cursor)); + /* Clear the stderr layer on each screen. + */ + if (!dont_clear) + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->stderr_overlay_window) + /* Do this before the fade, since the stderr cmap won't fade + even if we uninstall it (beats me...) */ + clear_stderr (ssi); + } - if (!dont_clear || ssi->stderr_overlay_window) - /* Do this before the fade, since the stderr cmap won't fade - even if we uninstall it (beats me...) */ - clear_stderr (ssi); - } + /* Note! The server is grabbed, and this will take several seconds + to complete! */ + fade_screens (si->dpy, current_maps, current_windows, + p->fade_seconds, p->fade_ticks, True, !dont_clear); - fade_screens (si->dpy, current_maps, p->fade_seconds, p->fade_ticks, - True); + free(current_maps); + free(current_windows); + current_maps = 0; + current_windows = 0; - if (p->verbose_p) fprintf (stderr, "fading done.\n"); + if (p->verbose_p) fprintf (stderr, "%s: fading done.\n", blurb()); +#ifdef HAVE_MIT_SAVER_EXTENSION for (i = 0; i < si->nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; - if (!dont_clear) - XClearWindow (si->dpy, ssi->screensaver_window); - XMapRaised (si->dpy, ssi->screensaver_window); - -#ifdef HAVE_MIT_SAVER_EXTENSION if (ssi->server_mit_saver_window && window_exists_p (si->dpy, ssi->server_mit_saver_window)) XUnmapWindow (si->dpy, ssi->server_mit_saver_window); -#endif /* HAVE_MIT_SAVER_EXTENSION */ - - /* Once the saver window is up, restore the colormap. - (The "black" pixels of the two colormaps are compatible.) */ - if (ssi->cmap) - XInstallColormap (si->dpy, ssi->cmap); } +#endif /* HAVE_MIT_SAVER_EXTENSION */ - if (grabbed == GrabSuccess) - XUngrabPointer (si->dpy, CurrentTime); XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ } else { @@ -909,6 +1024,16 @@ void blank_screen (saver_info *si) { int i; + + /* Note: we do our grabs on the root window, not on the screensaver window. + If we grabbed on the saver window, then the demo mode and lock dialog + boxes wouldn't get any events. + */ + grab_keyboard_and_mouse (si, + /*si->screens[0].screensaver_window,*/ + RootWindowOfScreen(si->screens[0].screen), + (si->demo_mode_p ? 0 : si->screens[0].cursor)); + for (i = 0; i < si->nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; @@ -920,9 +1045,7 @@ blank_screen (saver_info *si) } store_activate_time (si, si->screen_blanked_p); raise_window (si, False, False, False); - /* #### */ - grab_keyboard_and_mouse (si->dpy, si->screens[0].screensaver_window, - (si->demo_mode_p ? 0 : si->screens[0].cursor)); + #ifdef HAVE_XHPDISABLERESET if (si->locked_p && !hp_locked_p) { @@ -938,57 +1061,55 @@ void unblank_screen (saver_info *si) { saver_preferences *p = &si->prefs; - int i, j; + int i; + + monitor_power_on (si); store_activate_time (si, True); reset_watchdog_timer (si, False); if (p->unfade_p && !si->demo_mode_p) { - int grabbed = -1; - int extra_cmaps = 4; - int ncmaps = si->nscreens * (extra_cmaps + 1); - Colormap *cmaps = (Colormap *) calloc(sizeof(Colormap), ncmaps); + Window *current_windows = (Window *) + calloc(sizeof(Window), si->nscreens); + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + current_windows[i] = ssi->screensaver_window; + /* Ensure that the default background of the window is really black, + not a pixmap or something. (This does not clear the window.) */ + XSetWindowBackground (si->dpy, ssi->screensaver_window, + ssi->black_pixel); + } - if (p->verbose_p) fprintf (stderr, "%s: unfading... ", progname); + if (p->verbose_p) fprintf (stderr, "%s: unfading...\n", blurb()); - /* Fake out SGI's multi-colormap hardware; see utils/fade.c - for an explanation. */ - for (i = 0; i < ncmaps; i += (extra_cmaps + 1)) - for (j = 0; j < (extra_cmaps + 1); j++) - { - cmaps[i+j] = XCreateColormap (si->dpy, - RootWindow (si->dpy, i), - DefaultVisual(si->dpy, i), - AllocAll); - if (cmaps[i+j]) - { - blacken_colormap (ScreenOfDisplay(si->dpy, i), cmaps[i+j]); - XInstallColormap (si->dpy, cmaps[i+j]); - } - } - XGrabServer (si->dpy); + XSync (si->dpy, False); + XGrabServer (si->dpy); /* ############ DANGER! */ + XSync (si->dpy, False); + + /* Clear the stderr layer on each screen. + */ for (i = 0; i < si->nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; - if (grabbed != GrabSuccess) - grabbed = grab_mouse (si->dpy, RootWindowOfScreen (ssi->screen), - 0); - XUnmapWindow (si->dpy, ssi->screensaver_window); clear_stderr (ssi); } + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ - fade_screens (si->dpy, 0, p->fade_seconds, p->fade_ticks, False); - for (i = 0; i < ncmaps; i++) - if (cmaps[i]) XFreeColormap (si->dpy, cmaps[i]); - free (cmaps); + fade_screens (si->dpy, 0, current_windows, + p->fade_seconds, p->fade_ticks, + False, False); - if (p->verbose_p) fprintf (stderr, "unfading done.\n"); - if (grabbed == GrabSuccess) - XUngrabPointer (si->dpy, CurrentTime); + free(current_windows); + current_windows = 0; + + if (p->verbose_p) fprintf (stderr, "%s: unfading done.\n", blurb()); } else { @@ -1037,7 +1158,7 @@ unblank_screen (saver_info *si) store_activate_time(si, False); /* store unblank time */ - ungrab_keyboard_and_mouse (si->dpy); + ungrab_keyboard_and_mouse (si); restore_real_vroot (si); #ifdef HAVE_XHPDISABLERESET @@ -1048,6 +1169,13 @@ unblank_screen (saver_info *si) } #endif + /* Unmap the windows a second time, dammit -- just to avoid a race + with the screen-grabbing hacks. (I'm not sure if this is really + necessary; I'm stabbing in the dark now.) + */ + for (i = 0; i < si->nscreens; i++) + XUnmapWindow (si->dpy, si->screens[i].screensaver_window); + si->screen_blanked_p = False; } @@ -1077,31 +1205,52 @@ select_visual (saver_screen_info *ssi, const char *visual_name) { saver_info *si = ssi->global; saver_preferences *p = &si->prefs; + Bool install_cmap_p = p->install_cmap_p; + Bool was_installed_p = (ssi->cmap != DefaultColormapOfScreen(ssi->screen)); Visual *new_v; Bool got_it; if (visual_name && *visual_name) - new_v = get_visual (ssi->screen, visual_name, True, False); + { + if (!strcmp(visual_name, "default-i")) + { + visual_name = "default"; + install_cmap_p = True; + } + else if (!strcmp(visual_name, "default-n")) + { + visual_name = "default"; + install_cmap_p = False; + } + new_v = get_visual (ssi->screen, visual_name, True, False); + } else - new_v = ssi->default_visual; + { + new_v = ssi->default_visual; + } got_it = !!new_v; - if (new_v && ssi->current_visual != new_v) + if (new_v && new_v != DefaultVisualOfScreen(ssi->screen)) + install_cmap_p = True; + + ssi->install_cmap_p = install_cmap_p; + + if (new_v && + ((ssi->current_visual != new_v) || + (install_cmap_p != was_installed_p))) { Colormap old_c = ssi->cmap; Window old_w = ssi->screensaver_window; if (p->verbose_p) { + fprintf (stderr, "%s: switching to visual ", blurb()); + describe_visual (stderr, ssi->screen, new_v, install_cmap_p); #if 0 - fprintf (stderr, "%s: switching visuals\tfrom: ", progname); - describe_visual (stderr, ssi->screen, ssi->current_visual); - fprintf (stderr, "\t\t\t\tto: "); - describe_visual (stderr, ssi->screen, new_v); -#else - fprintf (stderr, "%s: switching to visual ", progname); - describe_visual (stderr, ssi->screen, new_v); + fprintf (stderr, "%s: from ", blurb()); + describe_visual (stderr, ssi->screen, ssi->current_visual, + was_installed_p); #endif } @@ -1112,12 +1261,62 @@ select_visual (saver_screen_info *ssi, const char *visual_name) ssi->screensaver_window = 0; initialize_screensaver_window_1 (ssi); + + /* stderr_overlay_window is a child of screensaver_window, so we need + to destroy that as well (actually, we just need to invalidate and + drop our pointers to it, but this will destroy it, which is ok so + long as it happens before old_w itself is destroyed.) */ + reset_stderr (ssi); + raise_window (si, True, True, False); store_vroot_property (si->dpy, ssi->screensaver_window, ssi->screensaver_window); store_activate_time (si, True); + + + /* Transfer the grabs from the old window to the new. + Actually I think none of this is necessary, since we always + hold our grabs on the root window, but I wrote this before + re-discovering that... + */ + + + /* If we're destroying the window that holds our mouse grab, + transfer the grab to the new window. (Grab the server while + so doing, to avoid a race condition.) + */ + if (old_w == si->mouse_grab_window) + { + XGrabServer (si->dpy); /* ############ DANGER! */ + ungrab_mouse(si); + grab_mouse(si, ssi->screensaver_window, + (si->demo_mode_p ? 0 : ssi->cursor)); + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + } + + /* If we're destroying the window that holds our keyboard grab, + transfer the grab to the new window. (Grab the server while + so doing, to avoid a race condition.) + */ + if (old_w == si->keyboard_grab_window) + { + XGrabServer (si->dpy); /* ############ DANGER! */ + ungrab_kbd(si); + grab_kbd(si, ssi->screensaver_window); + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + } + + /* Now we can destroy this window without horking our grabs. */ + XDestroyWindow (si->dpy, old_w); + + if (p->verbose_p) + fprintf (stderr, "%s: destroyed old saver window 0x%lx.\n", + blurb(), (unsigned long) old_w); + if (old_c && old_c != DefaultColormapOfScreen (ssi->screen) && old_c != ssi->demo_cmap)