Skip to content

Commit 591b2a7

Browse files
committed
Do not mess with DPMS/blanking
This is the job of the DPMS setting. We only stop children when Xss blanks the screen or when DPMS blanks the screen. The last part is a bit inefficient as there is no event associated.
1 parent a1478bc commit 591b2a7

File tree

2 files changed

+29
-138
lines changed

2 files changed

+29
-138
lines changed

README.md

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,15 +234,6 @@ Options to XSecureLock can be passed by environment variables:
234234
the screen saver.
235235
* `XSECURELOCK_AUTH_WARNING_COLOR`: specifies the X11 color (see manpage of
236236
XParseColor) for the warning text of the auth dialog.
237-
* `XSECURELOCK_BLANK_TIMEOUT`: specifies the time (in seconds) before telling
238-
X11 to fully blank the screen; a negative value disables X11 blanking. The
239-
time is measured since the closing of the auth window or xsecurelock
240-
startup. Setting this to 0 is rather nonsensical, as key-release events
241-
(e.g. from the keystroke to launch xsecurelock or from pressing escape to
242-
close the auth dialog) always wake up the screen.
243-
* `XSECURELOCK_BLANK_DPMS_STATE`: specifies which DPMS state to put the screen
244-
in when blanking (one of standby, suspend, off and on, where "on" means to
245-
not invoke DPMS at all).
246237
* `XSECURELOCK_BURNIN_MITIGATION`: specifies the number of pixels the prompt
247238
of `auth_x11` may be moved at startup to mitigate possible burn-in
248239
effects due to the auth dialog being displayed all the time (e.g. when

main.c

Lines changed: 29 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ limitations under the License.
4545
#endif
4646
#ifdef HAVE_XCOMPOSITE_EXT
4747
#include <X11/extensions/Xcomposite.h> // for XCompositeGetOverlayWindow
48-
4948
#include "incompatible_compositor.xbm" // for incompatible_compositor_bits
5049
#endif
5150
#ifdef HAVE_XSCREENSAVER_EXT
@@ -75,7 +74,7 @@ limitations under the License.
7574
*
7675
* This defines the minimum frequency to call WatchChildren().
7776
*/
78-
#define WATCH_CHILDREN_HZ 10
77+
#define WATCH_CHILDREN_HZ 1
7978

8079
/*! \brief Try to reinstate grabs in regular intervals.
8180
*
@@ -143,115 +142,12 @@ int have_switch_user_command = 0;
143142
int force_grab = 0;
144143
//! If set, print window info about any "conflicting" windows to stderr.
145144
int debug_window_info = 0;
146-
//! If nonnegative, the time in seconds till we blank the screen explicitly.
147-
int blank_timeout = -1;
148-
//! The DPMS state to switch the screen to when blanking.
149-
const char *blank_dpms_state = "off";
150145
//! Whether to reset the saver module when auth closes.
151146
int saver_reset_on_auth_close = 0;
152147

153148
//! The PID of a currently running notify command, or 0 if none is running.
154149
pid_t notify_command_pid = 0;
155150

156-
//! The time when we will blank the screen.
157-
struct timeval time_to_blank;
158-
159-
//! Whether the screen is currently blanked by us.
160-
int blanked = 0;
161-
162-
#ifdef HAVE_DPMS_EXT
163-
//! Whether DPMS needs to be disabled when unblanking. Set when blanking.
164-
int must_disable_dpms = 0;
165-
#endif
166-
167-
void ResetBlankScreenTimer(void) {
168-
if (blank_timeout < 0) {
169-
return;
170-
}
171-
gettimeofday(&time_to_blank, NULL);
172-
time_to_blank.tv_sec += blank_timeout;
173-
}
174-
175-
void InitBlankScreen(void) {
176-
if (blank_timeout < 0) {
177-
return;
178-
}
179-
blanked = 0;
180-
ResetBlankScreenTimer();
181-
}
182-
183-
void MaybeBlankScreen(Display *display) {
184-
if (blank_timeout < 0 || blanked) {
185-
return;
186-
}
187-
struct timeval now;
188-
gettimeofday(&now, NULL);
189-
if (now.tv_sec < time_to_blank.tv_sec ||
190-
(now.tv_sec == time_to_blank.tv_sec &&
191-
now.tv_usec < time_to_blank.tv_usec)) {
192-
return;
193-
}
194-
// Blank timer expired - blank the screen.
195-
blanked = 1;
196-
XForceScreenSaver(display, ScreenSaverActive);
197-
if (!strcmp(blank_dpms_state, "on")) {
198-
// Just X11 blanking.
199-
goto done;
200-
}
201-
#ifdef HAVE_DPMS_EXT
202-
// If we get here, we want to do DPMS blanking.
203-
int dummy;
204-
if (!DPMSQueryExtension(display, &dummy, &dummy)) {
205-
Log("DPMS is unavailable and XSECURELOCK_BLANK_DPMS_STATE not on");
206-
goto done;
207-
}
208-
CARD16 state;
209-
BOOL onoff;
210-
DPMSInfo(display, &state, &onoff);
211-
if (!onoff) {
212-
// DPMS not active by user - so we gotta force it.
213-
must_disable_dpms = 1;
214-
DPMSEnable(display);
215-
}
216-
if (!strcmp(blank_dpms_state, "standby")) {
217-
DPMSForceLevel(display, DPMSModeStandby);
218-
} else if (!strcmp(blank_dpms_state, "suspend")) {
219-
DPMSForceLevel(display, DPMSModeSuspend);
220-
} else if (!strcmp(blank_dpms_state, "off")) {
221-
DPMSForceLevel(display, DPMSModeOff);
222-
} else {
223-
Log("XSECURELOCK_BLANK_DPMS_STATE not in standby/suspend/off/on");
224-
}
225-
#else
226-
Log("DPMS is not compiled in and XSECURELOCK_BLANK_DPMS_STATE not on");
227-
#endif
228-
done:
229-
// Flush the output buffer so we turn off the display now and not a few ms
230-
// later.
231-
XFlush(display);
232-
}
233-
234-
void ScreenNoLongerBlanked(Display *display) {
235-
#ifdef HAVE_DPMS_EXT
236-
if (must_disable_dpms) {
237-
DPMSDisable(display);
238-
must_disable_dpms = 0;
239-
// Flush the output buffer so we turn on the display now and not a
240-
// few ms later. Makes our and X11's idle timer more consistent.
241-
XFlush(display);
242-
}
243-
#endif
244-
blanked = 0;
245-
}
246-
247-
void UnblankScreen(Display *display) {
248-
if (blanked) {
249-
XForceScreenSaver(display, ScreenSaverReset);
250-
ScreenNoLongerBlanked(display);
251-
}
252-
ResetBlankScreenTimer();
253-
}
254-
255151
static void HandleSIGTERM(int signo) {
256152
KillAllSaverChildrenSigHandler(signo); // Dirty, but quick.
257153
KillAuthChildSigHandler(signo); // More dirty.
@@ -319,18 +215,34 @@ int WatchChildren(Display *dpy, Window auth_win, Window saver_win,
319215
WatchSaverChild(dpy, saver_win, 0, saver_executable,
320216
state != WATCH_CHILDREN_SAVER_DISABLED);
321217

322-
if (auth_running) {
323-
// While auth is running, we never blank.
324-
UnblankScreen(dpy);
325-
} else {
326-
// If no auth is running, permit blanking as per timer.
327-
MaybeBlankScreen(dpy);
328-
}
329-
330218
// Do not terminate the screen lock.
331219
return 0;
332220
}
333221

222+
/*! \brief Check if screen is blanked by DPMS.
223+
*
224+
* \return If true, the screen is blanked by DPMS.
225+
*/
226+
int IsBlankedByDPMS(Display *dpy) {
227+
#if HAVE_DPMS_EXT
228+
static Bool DPMSExtensionAvailable = -1;
229+
if (DPMSExtensionAvailable == -1) {
230+
int dummy;
231+
DPMSExtensionAvailable = (DPMSQueryExtension(dpy, &dummy, &dummy) != 0);
232+
}
233+
if (!DPMSExtensionAvailable) {
234+
return 0;
235+
}
236+
/* There is no DPMSSelectInput, so we need to poll */
237+
CARD16 dpms_state;
238+
BOOL dpms_enabled;
239+
if (DPMSInfo(dpy, &dpms_state, &dpms_enabled)) {
240+
return (dpms_enabled && dpms_state != DPMSModeOn);
241+
}
242+
#endif
243+
return 0;
244+
}
245+
334246
/*! \brief Wake up the screen saver in response to a keyboard or mouse event.
335247
*
336248
* \return If true, authentication was successful, and the program should exit.
@@ -425,8 +337,6 @@ void LoadDefaults() {
425337
*GetStringSetting("XSECURELOCK_SWITCH_USER_COMMAND", "");
426338
force_grab = GetIntSetting("XSECURELOCK_FORCE_GRAB", 0);
427339
debug_window_info = GetIntSetting("XSECURELOCK_DEBUG_WINDOW_INFO", 0);
428-
blank_timeout = GetIntSetting("XSECURELOCK_BLANK_TIMEOUT", 600);
429-
blank_dpms_state = GetStringSetting("XSECURELOCK_BLANK_DPMS_STATE", "off");
430340
saver_reset_on_auth_close =
431341
GetIntSetting("XSECURELOCK_SAVER_RESET_ON_AUTH_CLOSE", 0);
432342
}
@@ -1091,13 +1001,12 @@ int main(int argc, char **argv) {
10911001
// Need to flush the display so savers sure can access the window.
10921002
XFlush(display);
10931003

1094-
// Figure out the initial Xss saver state. This gets updated by event.
10951004
enum WatchChildrenState xss_requested_saver_state = WATCH_CHILDREN_NORMAL;
10961005
#ifdef HAVE_XSCREENSAVER_EXT
10971006
if (scrnsaver_event_base != 0) {
10981007
XScreenSaverInfo *info = XScreenSaverAllocInfo();
10991008
XScreenSaverQueryInfo(display, root_window, info);
1100-
if (info->state == ScreenSaverOn) {
1009+
if (info->state == ScreenSaverOn && info->kind == ScreenSaverBlanked) {
11011010
xss_requested_saver_state = WATCH_CHILDREN_SAVER_DISABLED;
11021011
}
11031012
XFree(info);
@@ -1112,8 +1021,6 @@ int main(int argc, char **argv) {
11121021
xss_sleep_lock_fd = -1;
11131022
}
11141023

1115-
InitBlankScreen();
1116-
11171024
int background_window_mapped = 0, background_window_visible = 0,
11181025
auth_window_mapped = 0, saver_window_mapped = 0,
11191026
need_to_reinstate_grabs = 0, xss_lock_notified = 0;
@@ -1129,8 +1036,8 @@ int main(int argc, char **argv) {
11291036
select(x11_fd + 1, &in_fds, 0, 0, &tv);
11301037

11311038
// Make sure to shut down the saver when blanked. Saves power.
1132-
enum WatchChildrenState requested_saver_state =
1133-
blanked ? WATCH_CHILDREN_SAVER_DISABLED : xss_requested_saver_state;
1039+
enum WatchChildrenState requested_saver_state = IsBlankedByDPMS(display) ?
1040+
WATCH_CHILDREN_SAVER_DISABLED : xss_requested_saver_state;
11341041

11351042
// Now check status of our children.
11361043
if (WatchChildren(display, auth_window, saver_window, requested_saver_state,
@@ -1270,14 +1177,12 @@ int main(int argc, char **argv) {
12701177
case MotionNotify:
12711178
case ButtonPress:
12721179
// Mouse events launch the auth child.
1273-
ScreenNoLongerBlanked(display);
12741180
if (WakeUp(display, auth_window, saver_window, NULL)) {
12751181
goto done;
12761182
}
12771183
break;
12781184
case KeyPress: {
12791185
// Keyboard events launch the auth child.
1280-
ScreenNoLongerBlanked(display);
12811186
Status status = XLookupNone;
12821187
int have_key = 1;
12831188
int do_wake_up = 1;
@@ -1375,9 +1280,6 @@ int main(int argc, char **argv) {
13751280
} break;
13761281
case KeyRelease:
13771282
case ButtonRelease:
1378-
// Known to wake up screen blanking.
1379-
ScreenNoLongerBlanked(display);
1380-
break;
13811283
case MappingNotify:
13821284
case EnterNotify:
13831285
case LeaveNotify:
@@ -1493,7 +1395,7 @@ int main(int argc, char **argv) {
14931395
priv.ev.type == scrnsaver_event_base + ScreenSaverNotify) {
14941396
XScreenSaverNotifyEvent *xss_ev =
14951397
(XScreenSaverNotifyEvent *)&priv.ev;
1496-
if (xss_ev->state == ScreenSaverOn) {
1398+
if (xss_ev->state == ScreenSaverOn && xss_ev->kind == ScreenSaverBlanked) {
14971399
xss_requested_saver_state = WATCH_CHILDREN_SAVER_DISABLED;
14981400
} else {
14991401
xss_requested_saver_state = WATCH_CHILDREN_NORMAL;
@@ -1513,8 +1415,6 @@ int main(int argc, char **argv) {
15131415
}
15141416

15151417
done:
1516-
// Make sure no DPMS changes persist.
1517-
UnblankScreen(display);
15181418

15191419
if (previous_focused_window != None) {
15201420
XSetErrorHandler(SilentlyIgnoreErrorsHandler);

0 commit comments

Comments
 (0)