1 /* xset.c --- interacting with server extensions and the builtin screensaver.
2 * xscreensaver, Copyright (c) 1991-1998 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)
226 if (p->verbose_p && unblank_screen_p)
227 /* Used to print this all the time, but really, nobody cares.
228 Now only print it when verbose. */
230 "%s disabling server builtin screensaver.\n"
231 "%s: you can re-enable it with \"xset s on\".\n",
235 fprintf (stderr, "%s: (xset s %d %d; xset s %s; xset s %s)\n", blurb(),
236 desired_server_timeout, desired_server_interval,
237 (desired_prefer_blank ? "blank" : "noblank"),
238 (desired_allow_exp ? "expose" : "noexpose"));
240 XSetScreenSaver (si->dpy,
241 desired_server_timeout, desired_server_interval,
242 desired_prefer_blank, desired_allow_exp);
243 XSync(si->dpy, False);
247 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
249 static Bool extension_initted = False;
250 if (!extension_initted)
252 extension_initted = True;
253 # ifdef HAVE_MIT_SAVER_EXTENSION
254 if (si->using_mit_saver_extension) init_mit_saver_extension(si);
256 # ifdef HAVE_SGI_SAVER_EXTENSION
257 if (si->using_sgi_saver_extension) init_sgi_saver_extension(si);
261 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
263 if (unblank_screen_p)
264 /* Turn off the server builtin saver if it is now running. */
265 XForceScreenSaver (si->dpy, ScreenSaverReset);
269 /* Display Power Management System (DPMS.)
271 On XFree86 systems, "man xset" reports:
273 -dpms The -dpms option disables DPMS (Energy Star) features.
274 +dpms The +dpms option enables DPMS (Energy Star) features.
277 The dpms option allows the DPMS (Energy Star)
278 parameters to be set. The option can take up to three
279 numerical values, or the `force' flag followed by a
280 DPMS state. The `force' flags forces the server to
281 immediately switch to the DPMS state specified. The
282 DPMS state can be one of `standby', `suspend', or
283 `off'. When numerical values are given, they set the
284 inactivity period before the three modes are activated.
285 The first value given is for the `standby' mode, the
286 second is for the `suspend' mode, and the third is for
287 the `off' mode. Setting these values implicitly
288 enables the DPMS features. A value of zero disables a
291 However, note that the implementation is more than a little bogus,
292 in that there is code in /usr/X11R6/lib/libXdpms.a to implement all
293 the usual server-extension-querying utilities -- but there are no
294 prototypes in any header file! Thus, the prototypes here. (The
295 stuff in X11/extensions/dpms.h and X11/extensions/dpmsstr.h define
296 the raw X protcol, they don't define the API to libXdpms.a.)
299 Library: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMSLib.ms
300 Protocol: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMS.ms
303 #ifdef HAVE_DPMS_EXTENSION
305 #include <X11/Xproto.h> /* for CARD16 */
306 #include <X11/extensions/dpms.h>
307 #include <X11/extensions/dpmsstr.h>
309 extern Bool DPMSQueryExtension (Display *dpy, int *event_ret, int *error_ret);
310 extern Bool DPMSCapable (Display *dpy);
311 extern Status DPMSForceLevel (Display *dpy, CARD16 level);
312 extern Status DPMSInfo (Display *dpy, CARD16 *power_level, BOOL *state);
314 #if 0 /* others we don't use */
315 extern Status DPMSGetVersion (Display *dpy, int *major_ret, int *minor_ret);
316 extern Status DPMSSetTimeouts (Display *dpy,
317 CARD16 standby, CARD16 suspend, CARD16 off);
318 extern Bool DPMSGetTimeouts (Display *dpy,
319 CARD16 *standby, CARD16 *suspend, CARD16 *off);
320 extern Status DPMSEnable (Display *dpy);
321 extern Status DPMSDisable (Display *dpy);
326 monitor_powered_on_p (saver_info *si)
329 int event_number, error_number;
333 if (!DPMSQueryExtension(si->dpy, &event_number, &error_number))
334 /* Server doesn't know -- assume the monitor is on. */
337 else if (!DPMSCapable(si->dpy))
338 /* Server says the monitor doesn't do power management -- so it's on. */
343 DPMSInfo(si->dpy, &state, &onoff);
345 /* Server says DPMS is disabled -- so the monitor is on. */
349 case DPMSModeOn: result = True; break; /* really on */
350 case DPMSModeStandby: result = False; break; /* kinda off */
351 case DPMSModeSuspend: result = False; break; /* pretty off */
352 case DPMSModeOff: result = False; break; /* really off */
353 default: result = True; break; /* protocol error? */
361 monitor_power_on (saver_info *si)
363 if (!monitor_powered_on_p (si))
365 DPMSForceLevel(si->dpy, DPMSModeOn);
366 XSync(si->dpy, False);
367 if (!monitor_powered_on_p (si))
369 "%s: DPMSForceLevel(dpy, DPMSModeOn) did not power the monitor on?\n",
374 #else /* !HAVE_DPMS_EXTENSION */
377 monitor_powered_on_p (saver_info *si)
383 monitor_power_on (saver_info *si)
388 #endif /* !HAVE_DPMS_EXTENSION */