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 (unblank_screen_p)
228 "%s disabling server builtin screensaver.\n"
229 "%s: you can re-enable it with \"xset s on\".\n",
233 fprintf (stderr, "%s: (xset s %d %d; xset s %s; xset s %s)\n", blurb(),
234 desired_server_timeout, desired_server_interval,
235 (desired_prefer_blank ? "blank" : "noblank"),
236 (desired_allow_exp ? "expose" : "noexpose"));
238 XSetScreenSaver (si->dpy,
239 desired_server_timeout, desired_server_interval,
240 desired_prefer_blank, desired_allow_exp);
241 XSync(si->dpy, False);
245 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
247 static Bool extension_initted = False;
248 if (!extension_initted)
250 extension_initted = True;
251 # ifdef HAVE_MIT_SAVER_EXTENSION
252 if (si->using_mit_saver_extension) init_mit_saver_extension(si);
254 # ifdef HAVE_SGI_SAVER_EXTENSION
255 if (si->using_sgi_saver_extension) init_sgi_saver_extension(si);
259 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
261 if (unblank_screen_p)
262 /* Turn off the server builtin saver if it is now running. */
263 XForceScreenSaver (si->dpy, ScreenSaverReset);
267 /* Display Power Management System (DPMS.)
269 On XFree86 systems, "man xset" reports:
271 -dpms The -dpms option disables DPMS (Energy Star) features.
272 +dpms The +dpms option enables DPMS (Energy Star) features.
275 The dpms option allows the DPMS (Energy Star)
276 parameters to be set. The option can take up to three
277 numerical values, or the `force' flag followed by a
278 DPMS state. The `force' flags forces the server to
279 immediately switch to the DPMS state specified. The
280 DPMS state can be one of `standby', `suspend', or
281 `off'. When numerical values are given, they set the
282 inactivity period before the three modes are activated.
283 The first value given is for the `standby' mode, the
284 second is for the `suspend' mode, and the third is for
285 the `off' mode. Setting these values implicitly
286 enables the DPMS features. A value of zero disables a
289 However, note that the implementation is more than a little bogus,
290 in that there is code in /usr/X11R6/lib/libXdpms.a to implement all
291 the usual server-extension-querying utilities -- but there are no
292 prototypes in any header file! Thus, the prototypes here. (The
293 stuff in X11/extensions/dpms.h and X11/extensions/dpmsstr.h define
294 the raw X protcol, they don't define the API to libXdpms.a.)
297 Library: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMSLib.ms
298 Protocol: ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/DPMS.ms
301 #ifdef HAVE_DPMS_EXTENSION
303 #include <X11/Xproto.h> /* for CARD16 */
304 #include <X11/extensions/dpms.h>
305 #include <X11/extensions/dpmsstr.h>
307 extern Bool DPMSQueryExtension (Display *dpy, int *event_ret, int *error_ret);
308 extern Bool DPMSCapable (Display *dpy);
309 extern Status DPMSForceLevel (Display *dpy, CARD16 level);
310 extern Status DPMSInfo (Display *dpy, CARD16 *power_level, BOOL *state);
312 #if 0 /* others we don't use */
313 extern Status DPMSGetVersion (Display *dpy, int *major_ret, int *minor_ret);
314 extern Status DPMSSetTimeouts (Display *dpy,
315 CARD16 standby, CARD16 suspend, CARD16 off);
316 extern Bool DPMSGetTimeouts (Display *dpy,
317 CARD16 *standby, CARD16 *suspend, CARD16 *off);
318 extern Status DPMSEnable (Display *dpy);
319 extern Status DPMSDisable (Display *dpy);
324 monitor_powered_on_p (saver_info *si)
327 int event_number, error_number;
331 if (!DPMSQueryExtension(si->dpy, &event_number, &error_number))
332 /* Server doesn't know -- assume the monitor is on. */
335 else if (!DPMSCapable(si->dpy))
336 /* Server says the monitor doesn't do power management -- so it's on. */
341 DPMSInfo(si->dpy, &state, &onoff);
343 /* Server says DPMS is disabled -- so the monitor is on. */
347 case DPMSModeOn: result = True; break; /* really on */
348 case DPMSModeStandby: result = False; break; /* kinda off */
349 case DPMSModeSuspend: result = False; break; /* pretty off */
350 case DPMSModeOff: result = False; break; /* really off */
351 default: result = True; break; /* protocol error? */
359 monitor_power_on (saver_info *si)
361 if (!monitor_powered_on_p (si))
363 DPMSForceLevel(si->dpy, DPMSModeOn);
364 XSync(si->dpy, False);
365 if (!monitor_powered_on_p (si))
367 "%s: DPMSForceLevel(dpy, DPMSModeOn) did not power the monitor on?\n",
372 #else /* !HAVE_DPMS_EXTENSION */
375 monitor_powered_on_p (saver_info *si)
381 monitor_power_on (saver_info *si)
386 #endif /* !HAVE_DPMS_EXTENSION */