1 /* xset.c --- interacting with server extensions and the builtin screensaver.
2 * xscreensaver, Copyright (c) 1991-2002 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
19 #include <X11/Xutil.h>
20 #include <X11/Xatom.h>
23 /* This file doesn't need the Xt headers, so stub these types out... */
25 #define XtAppContext void*
26 #define XrmDatabase void*
27 #define XtIntervalId void*
28 #define XtPointer void*
31 #include "xscreensaver.h"
34 ERROR! You must not include vroot.h in this file.
38 /* MIT SCREEN-SAVER server extension hackery.
41 #ifdef HAVE_MIT_SAVER_EXTENSION
43 # include <X11/extensions/scrnsaver.h>
46 query_mit_saver_extension (saver_info *si)
48 return XScreenSaverQueryExtension (si->dpy,
49 &si->mit_saver_ext_event_number,
50 &si->mit_saver_ext_error_number);
54 ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
60 init_mit_saver_extension (saver_info *si)
63 Pixmap *blank_pix = (Pixmap *) calloc (sizeof(Pixmap), si->nscreens);
65 for (i = 0; i < si->nscreens; i++)
67 saver_screen_info *ssi = &si->screens[i];
70 Window root = RootWindowOfScreen (ssi->screen);
71 blank_pix[i] = XCreatePixmap (si->dpy, root, 1, 1, 1);
73 /* Kill off the old MIT-SCREEN-SAVER client if there is one.
74 This tends to generate X errors, though (possibly due to a bug
75 in the server extension itself?) so just ignore errors here. */
76 if (XScreenSaverGetRegistered (si->dpy,
77 XScreenNumberOfScreen (ssi->screen),
79 && kill_id != blank_pix[i])
81 XErrorHandler old_handler =
82 XSetErrorHandler (ignore_all_errors_ehandler);
83 XKillClient (si->dpy, kill_id);
84 XSync (si->dpy, False);
85 XSetErrorHandler (old_handler);
87 XScreenSaverSelectInput (si->dpy, root, ScreenSaverNotifyMask);
88 XScreenSaverRegister (si->dpy,
89 XScreenNumberOfScreen (ssi->screen),
90 (XID) blank_pix[i], XA_PIXMAP);
94 #endif /* HAVE_MIT_SAVER_EXTENSION */
97 /* SGI SCREEN_SAVER server extension hackery.
100 #ifdef HAVE_SGI_SAVER_EXTENSION
102 # include <X11/extensions/XScreenSaver.h>
105 query_sgi_saver_extension (saver_info *si)
107 return XScreenSaverQueryExtension (si->dpy,
108 &si->sgi_saver_ext_event_number,
109 &si->sgi_saver_ext_error_number);
113 init_sgi_saver_extension (saver_info *si)
115 saver_preferences *p = &si->prefs;
117 if (si->screen_blanked_p)
118 /* If you mess with this while the server thinks it's active,
119 the server crashes. */
122 for (i = 0; i < si->nscreens; i++)
124 saver_screen_info *ssi = &si->screens[i];
125 XScreenSaverDisable (si->dpy, XScreenNumberOfScreen(ssi->screen));
126 if (! XScreenSaverEnable (si->dpy, XScreenNumberOfScreen(ssi->screen)))
129 "%s: SGI SCREEN_SAVER extension exists, but can't be initialized;\n\
130 perhaps some other screensaver program is already running?\n",
132 si->using_sgi_saver_extension = False;
138 #endif /* HAVE_SGI_SAVER_EXTENSION */
141 /* XIDLE server extension hackery.
144 #ifdef HAVE_XIDLE_EXTENSION
146 # include <X11/extensions/xidle.h>
149 query_xidle_extension (saver_info *si)
153 return XidleQueryExtension (si->dpy, &event_number, &error_number);
156 #endif /* HAVE_XIDLE_EXTENSION */
160 /* Figuring out what the appropriate XSetScreenSaver() parameters are
161 (one wouldn't expect this to be rocket science.)
165 disable_builtin_screensaver (saver_info *si, Bool unblank_screen_p)
167 saver_preferences *p = &si->prefs;
168 int current_server_timeout, current_server_interval;
169 int current_prefer_blank, current_allow_exp;
170 int desired_server_timeout, desired_server_interval;
171 int desired_prefer_blank, desired_allow_exp;
173 XGetScreenSaver (si->dpy, ¤t_server_timeout, ¤t_server_interval,
174 ¤t_prefer_blank, ¤t_allow_exp);
176 desired_server_timeout = current_server_timeout;
177 desired_server_interval = current_server_interval;
178 desired_prefer_blank = current_prefer_blank;
179 desired_allow_exp = current_allow_exp;
181 /* On SGIs, if interval is non-zero, it is the number of seconds after
182 screen saving starts at which the monitor should be powered down.
183 Obviously I don't want that, so set it to 0 (meaning "never".)
185 Power saving is disabled if DontPreferBlanking, but in that case,
186 we don't get extension events either. So we can't turn it off that way.
188 Note: if you're running Irix 6.3 (O2), you may find that your monitor is
189 powering down anyway, regardless of the xset settings. This is fixed by
190 installing SGI patches 2447 and 2537.
192 desired_server_interval = 0;
194 /* I suspect (but am not sure) that DontAllowExposures might have
195 something to do with powering off the monitor as well, at least
196 on some systems that don't support XDPMS? Who know... */
197 desired_allow_exp = AllowExposures;
199 if (si->using_mit_saver_extension || si->using_sgi_saver_extension)
201 desired_server_timeout = (p->timeout / 1000);
203 /* The SGI extension won't give us events unless blanking is on.
204 I think (unsure right now) that the MIT extension is the opposite. */
205 if (si->using_sgi_saver_extension)
206 desired_prefer_blank = PreferBlanking;
208 desired_prefer_blank = DontPreferBlanking;
212 /* When we're not using an extension, set the server-side timeout to 0,
213 so that the server never gets involved with screen blanking, and we
214 do it all ourselves. (However, when we *are* using an extension,
215 we tell the server when to notify us, and rather than blanking the
216 screen, the server will send us an X event telling us to blank.)
218 desired_server_timeout = 0;
221 if (desired_server_timeout != current_server_timeout ||
222 desired_server_interval != current_server_interval ||
223 desired_prefer_blank != current_prefer_blank ||
224 desired_allow_exp != current_allow_exp)
228 "%s: disabling server builtin screensaver:\n"
229 "%s: (xset s %d %d; xset s %s; xset s %s)\n",
231 desired_server_timeout, desired_server_interval,
232 (desired_prefer_blank ? "blank" : "noblank"),
233 (desired_allow_exp ? "expose" : "noexpose"));
235 XSetScreenSaver (si->dpy,
236 desired_server_timeout, desired_server_interval,
237 desired_prefer_blank, desired_allow_exp);
238 XSync(si->dpy, False);
242 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
244 static Bool extension_initted = False;
245 if (!extension_initted)
247 extension_initted = True;
248 # ifdef HAVE_MIT_SAVER_EXTENSION
249 if (si->using_mit_saver_extension) init_mit_saver_extension(si);
251 # ifdef HAVE_SGI_SAVER_EXTENSION
252 if (si->using_sgi_saver_extension) init_sgi_saver_extension(si);
256 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
258 if (unblank_screen_p)
259 /* Turn off the server builtin saver if it is now running. */
260 XForceScreenSaver (si->dpy, ScreenSaverReset);
264 /* Display Power Management System (DPMS.)
266 On XFree86 systems, "man xset" reports:
268 -dpms The -dpms option disables DPMS (Energy Star) features.
269 +dpms The +dpms option enables DPMS (Energy Star) features.
272 The dpms option allows the DPMS (Energy Star)
273 parameters to be set. The option can take up to three
274 numerical values, or the `force' flag followed by a
275 DPMS state. The `force' flags forces the server to
276 immediately switch to the DPMS state specified. The
277 DPMS state can be one of `standby', `suspend', or
278 `off'. When numerical values are given, they set the
279 inactivity period before the three modes are activated.
280 The first value given is for the `standby' mode, the
281 second is for the `suspend' mode, and the third is for
282 the `off' mode. Setting these values implicitly
283 enables the DPMS features. A value of zero disables a
286 However, note that the implementation is more than a little bogus,
287 in that there is code in /usr/X11R6/lib/libXdpms.a to implement all
288 the usual server-extension-querying utilities -- but there are no
289 prototypes in any header file! Thus, the prototypes here. (The
290 stuff in X11/extensions/dpms.h and X11/extensions/dpmsstr.h define
291 the raw X protcol, they don't define the API to libXdpms.a.)
294 Library: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMSLib.ms
295 Protocol: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMS.ms
298 #ifdef HAVE_DPMS_EXTENSION
300 #include <X11/Xproto.h> /* for CARD16 */
301 #include <X11/extensions/dpms.h>
302 #include <X11/extensions/dpmsstr.h>
304 extern Bool DPMSQueryExtension (Display *dpy, int *event_ret, int *error_ret);
305 extern Bool DPMSCapable (Display *dpy);
306 extern Status DPMSForceLevel (Display *dpy, CARD16 level);
307 extern Status DPMSInfo (Display *dpy, CARD16 *power_level, BOOL *state);
309 #if 0 /* others we don't use */
310 extern Status DPMSGetVersion (Display *dpy, int *major_ret, int *minor_ret);
311 extern Status DPMSSetTimeouts (Display *dpy,
312 CARD16 standby, CARD16 suspend, CARD16 off);
313 extern Bool DPMSGetTimeouts (Display *dpy,
314 CARD16 *standby, CARD16 *suspend, CARD16 *off);
315 extern Status DPMSEnable (Display *dpy);
316 extern Status DPMSDisable (Display *dpy);
321 monitor_powered_on_p (saver_info *si)
324 int event_number, error_number;
328 if (!DPMSQueryExtension(si->dpy, &event_number, &error_number))
329 /* Server doesn't know -- assume the monitor is on. */
332 else if (!DPMSCapable(si->dpy))
333 /* Server says the monitor doesn't do power management -- so it's on. */
338 DPMSInfo(si->dpy, &state, &onoff);
340 /* Server says DPMS is disabled -- so the monitor is on. */
344 case DPMSModeOn: result = True; break; /* really on */
345 case DPMSModeStandby: result = False; break; /* kinda off */
346 case DPMSModeSuspend: result = False; break; /* pretty off */
347 case DPMSModeOff: result = False; break; /* really off */
348 default: result = True; break; /* protocol error? */
356 monitor_power_on (saver_info *si)
358 if (!monitor_powered_on_p (si))
360 DPMSForceLevel(si->dpy, DPMSModeOn);
361 XSync(si->dpy, False);
362 if (!monitor_powered_on_p (si))
364 "%s: DPMSForceLevel(dpy, DPMSModeOn) did not power the monitor on?\n",
369 #else /* !HAVE_DPMS_EXTENSION */
372 monitor_powered_on_p (saver_info *si)
378 monitor_power_on (saver_info *si)
383 #endif /* !HAVE_DPMS_EXTENSION */