X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fxscreensaver.c;h=76969f23d2454bc0e01628af46abbb8e5018ff67;hb=aa75c7476aeaa84cf3abc192b376a8b03c325213;hp=aa9d964bf42bda1ae69955ac754d8b4fa1cc7c4b;hpb=2762a7d7cf8d83e68b8f635941f6609119d630ae;p=xscreensaver diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c index aa9d964b..76969f23 100644 --- a/driver/xscreensaver.c +++ b/driver/xscreensaver.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1991-2013 Jamie Zawinski +/* xscreensaver, Copyright (c) 1991-2016 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 @@ -93,6 +93,14 @@ * subwindows. It is an incredible misdesign that one client can make * another client malfunction in this way. * + * But here's a new kink that started showing up in late 2014: GNOME programs + * don't actually select for or receive KeyPress events! They do it behind + * the scenes through some kind of Input Method magic, even when running in + * an en_US locale. However, in that case, those applications *do* seem to + * update the _NET_WM_USER_TIME on their own windows every time they have + * received a secret KeyPress, so we *also* monitor that property on every + * window, and treat changes to it as identical to KeyPress. + * * To detect mouse motion, we periodically wake up and poll the mouse * position and button/modifier state, and notice when something has * changed. We make this check every five seconds by default, and since the @@ -297,7 +305,7 @@ xscreensaver %s, copyright (c) 1991-%s by Jamie Zawinski \n\ \n\ For updates, online manual, and FAQ, please see the web page:\n\ \n\ - http://www.jwz.org/xscreensaver/\n\ + https://www.jwz.org/xscreensaver/\n\ \n"); fflush (stdout); @@ -309,7 +317,7 @@ xscreensaver %s, copyright (c) 1991-%s by Jamie Zawinski \n\ Bool in_signal_handler_p = 0; /* I hate C so much... */ char * -timestring (void) +timestring (time_t when) { if (in_signal_handler_p) { @@ -322,9 +330,10 @@ timestring (void) } else { - time_t now = time ((time_t *) 0); - char *str = (char *) ctime (&now); - char *nl = (char *) strchr (str, '\n'); + char *str, *nl; + if (! when) when = time ((time_t *) 0); + str = (char *) ctime (&when); + nl = (char *) strchr (str, '\n'); if (nl) *nl = 0; /* take off that dang newline */ return str; } @@ -340,7 +349,7 @@ blurb (void) else { static char buf[255]; - char *ct = timestring(); + char *ct = timestring(0); int n = strlen(progname); if (n > 100) n = 99; strncpy(buf, progname, n); @@ -416,7 +425,7 @@ saver_ehandler (Display *dpy, XErrorEvent *error) " won't work. A \"log.txt\" file will also be written. Please *do*\n" " include the complete \"log.txt\" file with your bug report.\n" "\n" - " http://www.jwz.org/xscreensaver/bugs.html explains how to create\n" + " https://www.jwz.org/xscreensaver/bugs.html explains how to create\n" " the most useful bug reports, and how to examine core files.\n" "\n" " The more information you can provide, the better. But please\n" @@ -486,8 +495,8 @@ startup_ehandler (String name, String type, String class, } fprintf (stderr, "\n" - " http://www.jwz.org/xscreensaver/faq.html\n" - " http://www.jwz.org/xscreensaver/man.html\n" + " https://www.jwz.org/xscreensaver/faq.html\n" + " https://www.jwz.org/xscreensaver/man.html\n" "\n"); fflush (stderr); @@ -600,6 +609,16 @@ lock_initialization (saver_info *si, int *argc, char **argv) } } + /* Like MacOS, locking under Wayland's embedded X11 server does not work. + (X11 grabs don't work because the Wayland window manager lives at a + higher level than the X11 emulation layer.) + */ + if (!si->locking_disabled_p && getenv ("WAYLAND_DISPLAY")) + { + si->locking_disabled_p = True; + si->nolock_reason = "Cannot lock securely under Wayland"; + } + if (si->prefs.debug_p) /* But allow locking anyway in debug mode. */ si->locking_disabled_p = False; @@ -659,6 +678,7 @@ connect_to_server (saver_info *si, int *argc, char **argv) XA_XSETROOT_ID = XInternAtom (si->dpy, "_XSETROOT_ID", False); XA_ESETROOT_PMAP_ID = XInternAtom (si->dpy, "ESETROOT_PMAP_ID", False); XA_XROOTPMAP_ID = XInternAtom (si->dpy, "_XROOTPMAP_ID", False); + XA_NET_WM_USER_TIME = XInternAtom (si->dpy, "_NET_WM_USER_TIME", False); XA_ACTIVATE = XInternAtom (si->dpy, "ACTIVATE", False); XA_DEACTIVATE = XInternAtom (si->dpy, "DEACTIVATE", False); XA_RESTART = XInternAtom (si->dpy, "RESTART", False); @@ -730,7 +750,7 @@ process_command_line (saver_info *si, int *argc, char **argv) You control a running xscreensaver process by sending it messages\n\ with `xscreensaver-demo' or `xscreensaver-command'.\n\ . See the man pages for details, or check the web page:\n\ - http://www.jwz.org/xscreensaver/\n\n"); + https://www.jwz.org/xscreensaver/\n\n"); } exit (1); @@ -784,12 +804,12 @@ print_banner (saver_info *si) "\n", blurb()); - if (p->verbose_p && senescent_p ()) + if (p->verbose_p && decrepit_p ()) fprintf (stderr, "\n" "*************************************" "**************************************\n" "%s: Warning: this version of xscreensaver is VERY OLD!\n" - "%s: Please upgrade! http://www.jwz.org/xscreensaver/\n" + "%s: Please upgrade! https://www.jwz.org/xscreensaver/\n" "*************************************" "**************************************\n" "\n", @@ -1138,6 +1158,7 @@ maybe_reload_init_file (saver_info *si) sync_server_dpms_settings (si->dpy, (p->dpms_enabled_p && p->mode != DONT_BLANK), + p->dpms_quickoff_p, p->dpms_standby / 1000, p->dpms_suspend / 1000, p->dpms_off / 1000, @@ -1177,10 +1198,10 @@ main_loop (saver_info *si) { if (si->demoing_p) fprintf (stderr, "%s: demoing %d at %s.\n", blurb(), - si->selection_mode, timestring()); + si->selection_mode, timestring(0)); else fprintf (stderr, "%s: blanking screen at %s.\n", blurb(), - timestring()); + timestring(0)); } maybe_reload_init_file (si); @@ -1189,7 +1210,7 @@ main_loop (saver_info *si) { if (p->verbose_p) fprintf (stderr, "%s: idle with blanking disabled at %s.\n", - blurb(), timestring()); + blurb(), timestring(0)); /* Go around the loop and wait for the next bout of idleness, or for the init file to change, or for a remote command to @@ -1255,6 +1276,12 @@ main_loop (saver_info *si) "%s: unable to grab keyboard or mouse! Blanking aborted.\n", blurb()); + /* Since we were unable to blank, clearly we're not locked, + but we might have been prematurely marked as locked by + the LOCK ClientMessage. */ + if (si->locked_p) + set_locked_p (si, False); + schedule_wakeup_event (si, retry, p->debug_p); continue; } @@ -1270,19 +1297,16 @@ main_loop (saver_info *si) for (i = 0; i < si->nscreens; i++) spawn_screenhack (&si->screens[i]); - /* If we are blanking only, optionally power down monitor right now. - To do this, we might need to temporarily re-enable DPMS first. - */ + /* If we are blanking only, optionally power down monitor right now. */ if (p->mode == BLANK_ONLY && p->dpms_enabled_p && p->dpms_quickoff_p) { sync_server_dpms_settings (si->dpy, True, + p->dpms_quickoff_p, p->dpms_standby / 1000, p->dpms_suspend / 1000, - (p->dpms_off - ? (p->dpms_off / 1000) - : 0xFFFF), + p->dpms_off / 1000, False); monitor_power_on (si, False); } @@ -1388,7 +1412,7 @@ main_loop (saver_info *si) if (p->verbose_p) fprintf (stderr, "%s: unblanking screen at %s.\n", - blurb(), timestring ()); + blurb(), timestring (0)); /* Kill before unblanking, to stop drawing as soon as possible. */ for (i = 0; i < si->nscreens; i++) @@ -1528,7 +1552,7 @@ main (int argc, char **argv) if (p->verbose_p) analyze_display (si); initialize_server_extensions (si); - si->blank_time = time ((time_t) 0); /* must be before ..._window */ + si->blank_time = time ((time_t *) 0); /* must be before ..._window */ initialize_screensaver_window (si); select_events (si); @@ -1538,6 +1562,7 @@ main (int argc, char **argv) sync_server_dpms_settings (si->dpy, (p->dpms_enabled_p && p->mode != DONT_BLANK), + p->dpms_quickoff_p, p->dpms_standby / 1000, p->dpms_suspend / 1000, p->dpms_off / 1000, @@ -2045,7 +2070,16 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p) : "locking."); sprintf (buf, "LOCK ClientMessage received; %s", response); clientmessage_response (si, window, False, buf, response); + + /* Note that this leaves things in a slightly inconsistent state: + we are blanked but not locked. And blanking might actually + fail if we can't get the grab. */ set_locked_p (si, True); + + /* Have to set the time or xscreensaver-command doesn't + report the LOCK state change. */ + si->blank_time = time ((time_t *) 0); + si->selection_mode = 0; si->demoing_p = False; @@ -2331,11 +2365,13 @@ analyze_display (saver_info *si) vi_in.screen = ssi->real_screen_number; vi_out = XGetVisualInfo (si->dpy, VisualScreenMask, &vi_in, &out_count); if (!vi_out) continue; - for (j = 0; j < out_count; j++) + for (j = 0; j < out_count; j++) { + if (vi_out[j].depth >= 32) continue; if (vi_out[j].class == PseudoColor) colormapped_depths |= (1 << vi_out[j].depth); else non_mapped_depths |= (1 << vi_out[j].depth); + } XFree ((char *) vi_out); if (colormapped_depths)