-/* xscreensaver, Copyright (c) 1991-2013 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2015 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* 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
}
}
+ /* 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;
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);
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,
"%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;
}
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);
}
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);
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,
}
else if (type == XA_DEACTIVATE)
{
- if (! until_idle_p)
- {
- if (si->throttled_p && p->verbose_p)
- fprintf (stderr, "%s: unthrottled.\n", blurb());
- si->throttled_p = False;
+# if 0
+ /* When -deactivate is received while locked, pop up the dialog box
+ instead of just ignoring it. Some people depend on this behavior
+ to be able to unlock by using e.g. a fingerprint reader without
+ also having to click the mouse first.
+ */
+ if (si->locked_p)
+ {
+ clientmessage_response(si, window, False,
+ "DEACTIVATE ClientMessage received while locked: ignored.",
+ "screen is locked.");
+ }
+ else
+# endif /* 0 */
+ {
+ if (! until_idle_p)
+ {
+ if (si->throttled_p && p->verbose_p)
+ fprintf (stderr, "%s: unthrottled.\n", blurb());
+ si->throttled_p = False;
- clientmessage_response(si, window, False,
- "DEACTIVATE ClientMessage received.",
- "deactivating.");
- if (si->using_mit_saver_extension || si->using_sgi_saver_extension)
- {
- XForceScreenSaver (si->dpy, ScreenSaverReset);
- return False;
- }
- else
- {
- return True;
- }
- }
- clientmessage_response(si, window, False,
- "ClientMessage DEACTIVATE received while inactive: resetting idle timer.",
- "not active: idle timer reset.");
- reset_timers (si);
+ clientmessage_response(si, window, False,
+ "DEACTIVATE ClientMessage received.",
+ "deactivating.");
+ if (si->using_mit_saver_extension ||
+ si->using_sgi_saver_extension)
+ {
+ XForceScreenSaver (si->dpy, ScreenSaverReset);
+ return False;
+ }
+ else
+ {
+ return True;
+ }
+ }
+ clientmessage_response(si, window, False,
+ "ClientMessage DEACTIVATE received while inactive: "
+ "resetting idle timer.",
+ "not active: idle timer reset.");
+ reset_timers (si);
+ }
}
else if (type == XA_CYCLE)
{
: "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;
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)