X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fwindows.c;h=4945202a1f228690bb8b4abe2e6b0f6ffe0659bb;hb=551b3de3f619c04c2dd1971ee9b3f02e270c28c9;hp=4daa0607ea902bac5e35fd1d2ffa640a10e95e29;hpb=ce3185de9d9705e259f2b60dd4b5509007fa17d4;p=xscreensaver diff --git a/driver/windows.c b/driver/windows.c index 4daa0607..4945202a 100644 --- a/driver/windows.c +++ b/driver/windows.c @@ -17,14 +17,17 @@ #ifdef VMS # include /* for getpid() */ # include "vms-gtod.h" /* for gettimeofday() */ -# if !defined(HAVE_UNAME) && (__VMS_VER >= 70000000) -# define HAVE_UNAME 1 -# endif /* !HAVE_UNAME */ #endif /* VMS */ -# ifdef HAVE_UNAME -# include /* for uname() */ -# endif /* HAVE_UNAME */ +#ifndef VMS +# include /* for getpwuid() */ +#else /* VMS */ +# include "vms-pwd.h" +#endif /* VMS */ + +#ifdef HAVE_UNAME +# include /* for uname() */ +#endif /* HAVE_UNAME */ #include #include /* for CARD32 */ @@ -62,6 +65,15 @@ #include "visual.h" #include "fade.h" + +#ifdef HAVE_VT_LOCKSWITCH +# include +# include +# include + static void lock_vt (saver_info *si, Bool lock_p); +#endif /* HAVE_VT_LOCKSWITCH */ + + extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ Atom XA_VROOT, XA_XSETROOT_ID; @@ -81,6 +93,25 @@ static void store_activate_time (saver_info *si, Bool use_last_p); Button4MotionMask | Button5MotionMask | ButtonMotionMask) +static const char * +grab_string(int status) +{ + switch (status) + { + case GrabSuccess: return "GrabSuccess"; + case AlreadyGrabbed: return "AlreadyGrabbed"; + case GrabInvalidTime: return "GrabInvalidTime"; + case GrabNotViewable: return "GrabNotViewable"; + case GrabFrozen: return "GrabFrozen"; + default: + { + static char foo[255]; + sprintf(foo, "unknown status: %d", status); + return foo; + } + } +} + static int grab_kbd(saver_info *si, Window w) { @@ -95,36 +126,10 @@ grab_kbd(saver_info *si, 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" : - "???")); - + blurb(), (unsigned long) w, grab_string(status)); 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) @@ -167,34 +172,37 @@ ungrab_mouse(saver_info *si) } -void +static Bool grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor) { - Status status; + Status mstatus, kstatus; XSync (si->dpy, False); - status = grab_kbd (si, window); - if (status != GrabSuccess) + kstatus = grab_kbd (si, window); + if (kstatus != GrabSuccess) { /* try again in a second */ sleep (1); - status = grab_kbd (si, window); - if (status != GrabSuccess) + kstatus = grab_kbd (si, window); + if (kstatus != GrabSuccess) fprintf (stderr, "%s: couldn't grab keyboard! (%s)\n", - blurb(), grab_string(status)); + blurb(), grab_string(kstatus)); } - status = grab_mouse (si, window, cursor); - if (status != GrabSuccess) + mstatus = grab_mouse (si, window, cursor); + if (mstatus != GrabSuccess) { /* try again in a second */ sleep (1); - status = grab_mouse (si, window, cursor); - if (status != GrabSuccess) + mstatus = grab_mouse (si, window, cursor); + if (mstatus != GrabSuccess) fprintf (stderr, "%s: couldn't grab pointer! (%s)\n", - blurb(), grab_string(status)); + blurb(), grab_string(mstatus)); } + + return (kstatus == GrabSuccess || + mstatus == GrabSuccess); } -void +static void ungrab_keyboard_and_mouse (saver_info *si) { ungrab_mouse (si); @@ -351,6 +359,16 @@ save_real_vroot (saver_screen_info *ssi) Window root = RootWindowOfScreen (screen); Window root2, parent, *kids; unsigned int nkids; + XErrorHandler old_handler; + + /* It's possible that a window might be deleted between our call to + XQueryTree() and our call to XGetWindowProperty(). Don't die if + that happens (but just ignore that window, it's not the one we're + interested in anyway.) + */ + XSync (dpy, False); + old_handler = XSetErrorHandler (BadWindow_ehandler); + XSync (dpy, False); ssi->real_vroot = 0; ssi->real_vroot_value = 0; @@ -386,6 +404,10 @@ save_real_vroot (saver_screen_info *ssi) ssi->real_vroot_value = *vrootP; } + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + if (ssi->real_vroot) { handle_signals (si, True); @@ -592,6 +614,7 @@ saver_exit (saver_info *si, int status, const char *dump_core_reason) { saver_preferences *p = &si->prefs; static Bool exiting = False; + Bool bugp; Bool vrs; if (exiting) @@ -614,49 +637,40 @@ saver_exit (saver_info *si, int status, const char *dump_core_reason) else if (status == 1) status = -1; #endif + bugp = !!dump_core_reason; + 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); + /* 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. */ + cwd[0] = 0; + fprintf(real_stderr, "%s: dumping core (%s)\n", blurb(), + dump_core_reason); + + if (bugp) + fprintf(real_stderr, + "%s: see http://www.jwz.org/xscreensaver/bugs.html\n" + "\t\tfor bug reporting information.\n\n", + blurb()); # if defined(HAVE_GETCWD) - getcwd (cwd, sizeof(cwd)); + if (!getcwd (cwd, sizeof(cwd))) # elif defined(HAVE_GETWD) - getwd (cwd); -# else - strcpy(cwd, "unknown."); + if (!getwd (cwd)) # endif - fprintf (real_stderr, "%s: current directory is %s\n", blurb(), cwd); - describe_uids (si, real_stderr); + strcpy(cwd, "unknown."); - /* Do this to drop a core file, so that we can get a stack trace. */ - abort(); - } + 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); @@ -678,12 +692,77 @@ window_exists_p (Display *dpy, Window window) return (xgwa.screen != 0); } +static void +store_saver_id (saver_screen_info *ssi) +{ + XClassHint class_hints; + saver_info *si = ssi->global; + unsigned long pid = (unsigned long) getpid (); + char buf[20]; + struct passwd *p = getpwuid (getuid ()); + const char *name, *host; + char *id; + + /* First store the name and class on the window. + */ + class_hints.res_name = progname; + class_hints.res_class = progclass; + XSetClassHint (si->dpy, ssi->screensaver_window, &class_hints); + XStoreName (si->dpy, ssi->screensaver_window, "screensaver"); + + /* Then store the xscreensaver version number. + */ + XChangeProperty (si->dpy, ssi->screensaver_window, + XA_SCREENSAVER_VERSION, + XA_STRING, 8, PropModeReplace, + (unsigned char *) si->version, + strlen (si->version)); + + /* Now store the XSCREENSAVER_ID property, that says what user and host + xscreensaver is running as. + */ + + if (p && p->pw_name && *p->pw_name) + name = p->pw_name; + else if (p) + { + sprintf (buf, "%lu", (unsigned long) p->pw_uid); + name = buf; + } + else + name = "???"; + +# if defined(HAVE_UNAME) + { + struct utsname uts; + if (uname (&uts) < 0) + host = "???"; + else + host = uts.nodename; + } +# elif defined(VMS) + host = getenv("SYS$NODE"); +# else /* !HAVE_UNAME && !VMS */ + host = "???"; +# endif /* !HAVE_UNAME && !VMS */ + + id = (char *) malloc (strlen(name) + strlen(host) + 50); + sprintf (id, "%lu (%s@%s)", pid, name, host); + + XChangeProperty (si->dpy, ssi->screensaver_window, + XA_SCREENSAVER_ID, XA_STRING, + 8, PropModeReplace, + (unsigned char *) id, strlen (id)); + free (id); +} + + static void 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); + Bool install_cmap_p = ssi->install_cmap_p; /* not 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 @@ -691,12 +770,10 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) its own set of problems... */ XColor black; - XClassHint class_hints; XSetWindowAttributes attrs; unsigned long attrmask; int width = WidthOfScreen (ssi->screen); int height = HeightOfScreen (ssi->screen); - char id [2048]; static Bool printed_visual_info = False; /* only print the message once. */ black.red = black.green = black.blue = 0; @@ -705,13 +782,15 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) ssi->cmap = 0; if (ssi->current_visual != DefaultVisualOfScreen (ssi->screen)) + /* It's not the default visual, so we have no choice but to install. */ install_cmap_p = True; if (install_cmap_p) { if (! ssi->cmap) { - ssi->cmap = XCreateColormap (si->dpy, RootWindowOfScreen (ssi->screen), + ssi->cmap = XCreateColormap (si->dpy, + RootWindowOfScreen (ssi->screen), ssi->current_visual, AllocNone); if (! XAllocColor (si->dpy, ssi->cmap, &black)) abort (); ssi->black_pixel = black.pixel; @@ -772,7 +851,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) printed_visual_info = True; #ifdef HAVE_MIT_SAVER_EXTENSION - if (p->use_mit_saver_extension) + if (si->using_mit_saver_extension) { XScreenSaverInfo *info; Window root = RootWindowOfScreen (ssi->screen); @@ -850,68 +929,28 @@ initialize_screensaver_window_1 (saver_screen_info *ssi) blurb(), (unsigned long) ssi->screensaver_window); } -#ifdef HAVE_MIT_SAVER_EXTENSION - if (!p->use_mit_saver_extension || - window_exists_p (si->dpy, ssi->screensaver_window)) - /* When using the MIT-SCREEN-SAVER extension, the window pointed to - by screensaver_window only exists while the saver is active. - So we must be careful to only try and manipulate it while it - exists... - (#### The above comment would be true if the MIT extension actually - worked, but it's not true today -- see `server_mit_saver_window'.) - */ -#endif /* HAVE_MIT_SAVER_EXTENSION */ - { - class_hints.res_name = progname; - class_hints.res_class = progclass; - XSetClassHint (si->dpy, ssi->screensaver_window, &class_hints); - XStoreName (si->dpy, ssi->screensaver_window, "screensaver"); - XChangeProperty (si->dpy, ssi->screensaver_window, - XA_SCREENSAVER_VERSION, - XA_STRING, 8, PropModeReplace, - (unsigned char *) si->version, - strlen (si->version)); - - sprintf (id, "%lu on host ", (unsigned long) getpid ()); -# if defined(HAVE_UNAME) - { - struct utsname uts; - if (uname (&uts) < 0) - strcat (id, "???"); - else - strcat (id, uts.nodename); - } -# elif defined(VMS) - strcat (id, getenv("SYS$NODE")); -# else /* !HAVE_UNAME && !VMS */ - strcat (id, "???"); -# endif /* !HAVE_UNAME && !VMS */ + store_saver_id (ssi); - XChangeProperty (si->dpy, ssi->screensaver_window, - XA_SCREENSAVER_ID, XA_STRING, - 8, PropModeReplace, (unsigned char *) id, strlen (id)); + if (!ssi->cursor) + { + Pixmap bit; + bit = XCreatePixmapFromBitmapData (si->dpy, ssi->screensaver_window, + "\000", 1, 1, + BlackPixelOfScreen (ssi->screen), + BlackPixelOfScreen (ssi->screen), + 1); + ssi->cursor = XCreatePixmapCursor (si->dpy, bit, bit, &black, &black, + 0, 0); + XFreePixmap (si->dpy, bit); + } - if (!ssi->cursor) - { - Pixmap bit; - bit = XCreatePixmapFromBitmapData (si->dpy, ssi->screensaver_window, - "\000", 1, 1, - BlackPixelOfScreen (ssi->screen), - BlackPixelOfScreen (ssi->screen), - 1); - ssi->cursor = XCreatePixmapCursor (si->dpy, bit, bit, &black, &black, - 0, 0); - XFreePixmap (si->dpy, bit); - } + XSetWindowBackground (si->dpy, ssi->screensaver_window, ssi->black_pixel); - XSetWindowBackground (si->dpy, ssi->screensaver_window, - ssi->black_pixel); - if (si->demo_mode_p) - XUndefineCursor (si->dpy, ssi->screensaver_window); - else - XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor); - } + if (si->demoing_p) + XUndefineCursor (si->dpy, ssi->screensaver_window); + else + XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor); } void @@ -930,10 +969,13 @@ raise_window (saver_info *si, saver_preferences *p = &si->prefs; int i; + if (si->demoing_p) + inhibit_fade = True; + initialize_screensaver_window (si); reset_watchdog_timer (si, True); - if (p->fade_p && !inhibit_fade && !si->demo_mode_p) + if (p->fade_p && p->fading_possible_p && !inhibit_fade) { Window *current_windows = (Window *) calloc(sizeof(Window), si->nscreens); @@ -972,7 +1014,7 @@ raise_window (saver_info *si, /* 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); + p->fade_seconds/1000, p->fade_ticks, True, !dont_clear); free(current_maps); free(current_windows); @@ -1020,19 +1062,33 @@ raise_window (saver_info *si, } } -void +Bool blank_screen (saver_info *si) { int i; + Bool ok; /* 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)); + ok = grab_keyboard_and_mouse (si, + /*si->screens[0].screensaver_window,*/ + RootWindowOfScreen(si->screens[0].screen), + (si->demoing_p + ? 0 + : si->screens[0].cursor)); + + + 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. */ + ok = True; + + if (!ok) + return False; for (i = 0; i < si->nscreens; i++) { @@ -1054,13 +1110,21 @@ blank_screen (saver_info *si) } #endif +#ifdef HAVE_VT_LOCKSWITCH + if (si->locked_p) + lock_vt (si, True); /* turn off C-Alt-Fn */ +#endif + si->screen_blanked_p = True; + + return True; } void unblank_screen (saver_info *si) { saver_preferences *p = &si->prefs; + Bool unfade_p = (p->fading_possible_p && p->unfade_p); int i; monitor_power_on (si); @@ -1068,7 +1132,10 @@ unblank_screen (saver_info *si) store_activate_time (si, True); reset_watchdog_timer (si, False); - if (p->unfade_p && !si->demo_mode_p) + if (si->demoing_p) + unfade_p = False; + + if (unfade_p) { Window *current_windows = (Window *) calloc(sizeof(Window), si->nscreens); @@ -1103,7 +1170,7 @@ unblank_screen (saver_info *si) fade_screens (si->dpy, 0, current_windows, - p->fade_seconds, p->fade_ticks, + p->fade_seconds/1000, p->fade_ticks, False, False); free(current_windows); @@ -1169,6 +1236,10 @@ unblank_screen (saver_info *si) } #endif +#ifdef HAVE_VT_LOCKSWITCH + lock_vt (si, False); /* turn C-Alt-Fn back on */ +#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.) @@ -1232,6 +1303,7 @@ select_visual (saver_screen_info *ssi, const char *visual_name) got_it = !!new_v; if (new_v && new_v != DefaultVisualOfScreen(ssi->screen)) + /* It's not the default visual, so we have no choice but to install. */ install_cmap_p = True; ssi->install_cmap_p = install_cmap_p; @@ -1289,9 +1361,11 @@ select_visual (saver_screen_info *ssi, const char *visual_name) 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)); + ungrab_mouse (si); + grab_mouse (si, ssi->screensaver_window, + (si->demoing_p + ? 0 + : ssi->cursor)); XUngrabServer (si->dpy); XSync (si->dpy, False); /* ###### (danger over) */ } @@ -1325,3 +1399,56 @@ select_visual (saver_screen_info *ssi, const char *visual_name) return got_it; } + + +/* VT locking */ + +#ifdef HAVE_VT_LOCKSWITCH +static void +lock_vt (saver_info *si, Bool lock_p) +{ + saver_preferences *p = &si->prefs; + static Bool locked_p = False; + const char *dev_console = "/dev/console"; + int fd; + + if (lock_p == locked_p) + return; + + if (lock_p && !p->lock_vt_p) + return; + + fd = open (dev_console, O_RDWR); + if (fd < 0) + { + char buf [255]; + sprintf (buf, "%s: couldn't %s VTs: %s", blurb(), + (lock_p ? "lock" : "unlock"), + dev_console); +#if 0 /* #### doesn't work yet, so don't bother complaining */ + perror (buf); +#endif + return; + } + + if (ioctl (fd, (lock_p ? VT_LOCKSWITCH : VT_UNLOCKSWITCH)) == 0) + { + locked_p = lock_p; + + if (p->verbose_p) + fprintf (stderr, "%s: %s VTs\n", blurb(), + (lock_p ? "locked" : "unlocked")); + } + else + { + char buf [255]; + sprintf (buf, "%s: couldn't %s VTs: ioctl", blurb(), + (lock_p ? "lock" : "unlock")); +#if 0 /* #### doesn't work yet, so don't bother complaining */ + perror (buf); +#endif + } + + close (fd); +} +#endif /* HAVE_VT_LOCKSWITCH */