1 /* xset.c --- interacting with server extensions and the builtin screensaver.
2 * xscreensaver, Copyright (c) 1991-1998 Jamie Zawinski <jwz@netscape.com>
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 /* MIT SCREEN-SAVER server extension hackery.
37 #ifdef HAVE_MIT_SAVER_EXTENSION
39 # include <X11/extensions/scrnsaver.h>
42 query_mit_saver_extension (saver_info *si)
44 return XScreenSaverQueryExtension (si->dpy,
45 &si->mit_saver_ext_event_number,
46 &si->mit_saver_ext_error_number);
50 ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
56 init_mit_saver_extension (saver_info *si)
59 Pixmap *blank_pix = (Pixmap *) calloc (sizeof(Pixmap), si->nscreens);
61 for (i = 0; i < si->nscreens; i++)
63 saver_screen_info *ssi = &si->screens[i];
66 Window root = RootWindowOfScreen (ssi->screen);
67 blank_pix[i] = XCreatePixmap (si->dpy, root, 1, 1, 1);
69 /* Kill off the old MIT-SCREEN-SAVER client if there is one.
70 This tends to generate X errors, though (possibly due to a bug
71 in the server extension itself?) so just ignore errors here. */
72 if (XScreenSaverGetRegistered (si->dpy,
73 XScreenNumberOfScreen (ssi->screen),
75 && kill_id != blank_pix[i])
77 XErrorHandler old_handler =
78 XSetErrorHandler (ignore_all_errors_ehandler);
79 XKillClient (si->dpy, kill_id);
80 XSync (si->dpy, False);
81 XSetErrorHandler (old_handler);
83 XScreenSaverSelectInput (si->dpy, root, ScreenSaverNotifyMask);
84 XScreenSaverRegister (si->dpy,
85 XScreenNumberOfScreen (ssi->screen),
86 (XID) blank_pix[i], XA_PIXMAP);
90 #endif /* HAVE_MIT_SAVER_EXTENSION */
93 /* SGI SCREEN_SAVER server extension hackery.
96 #ifdef HAVE_SGI_SAVER_EXTENSION
98 # include <X11/extensions/XScreenSaver.h>
101 query_sgi_saver_extension (saver_info *si)
103 return XScreenSaverQueryExtension (si->dpy,
104 &si->sgi_saver_ext_event_number,
105 &si->sgi_saver_ext_error_number);
109 init_sgi_saver_extension (saver_info *si)
111 saver_preferences *p = &si->prefs;
113 if (si->screen_blanked_p)
114 /* If you mess with this while the server thinks it's active,
115 the server crashes. */
118 for (i = 0; i < si->nscreens; i++)
120 saver_screen_info *ssi = &si->screens[i];
121 XScreenSaverDisable (si->dpy, XScreenNumberOfScreen(ssi->screen));
122 if (! XScreenSaverEnable (si->dpy, XScreenNumberOfScreen(ssi->screen)))
125 "%s: SGI SCREEN_SAVER extension exists, but can't be initialized;\n\
126 perhaps some other screensaver program is already running?\n",
128 p->use_sgi_saver_extension = False;
134 #endif /* HAVE_SGI_SAVER_EXTENSION */
137 /* Figuring out what the appropriate XSetScreenSaver() parameters are
138 (one wouldn't expect this to be rocket science.)
142 disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
144 saver_preferences *p = &si->prefs;
145 int current_server_timeout, current_server_interval;
146 int current_prefer_blank, current_allow_exp;
147 int desired_server_timeout, desired_server_interval;
148 int desired_prefer_blank, desired_allow_exp;
150 XGetScreenSaver (si->dpy, ¤t_server_timeout, ¤t_server_interval,
151 ¤t_prefer_blank, ¤t_allow_exp);
153 desired_server_timeout = current_server_timeout;
154 desired_server_interval = current_server_interval;
155 desired_prefer_blank = current_prefer_blank;
156 desired_allow_exp = current_allow_exp;
158 /* On SGIs, if interval is non-zero, it is the number of seconds after
159 screen saving starts at which the monitor should be powered down.
160 Obviously I don't want that, so set it to 0 (meaning "never".)
162 Power saving is disabled if DontPreferBlanking, but in that case,
163 we don't get extension events either. So we can't turn it off that way.
165 Note: if you're running Irix 6.3 (O2), you may find that your monitor is
166 powering down anyway, regardless of the xset settings. This is fixed by
167 installing SGI patches 2447 and 2537.
169 desired_server_interval = 0;
171 /* I suspect (but am not sure) that DontAllowExposures might have
172 something to do with powering off the monitor as well. */
173 desired_allow_exp = AllowExposures;
175 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
176 if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
178 desired_server_timeout = (p->timeout / 1000);
180 /* The SGI extension won't give us events unless blanking is on.
181 I think (unsure right now) that the MIT extension is the opposite. */
182 if (p->use_sgi_saver_extension)
183 desired_prefer_blank = PreferBlanking;
185 desired_prefer_blank = DontPreferBlanking;
188 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
190 desired_server_timeout = 0;
193 if (desired_server_timeout != current_server_timeout ||
194 desired_server_interval != current_server_interval ||
195 desired_prefer_blank != current_prefer_blank ||
196 desired_allow_exp != current_allow_exp)
198 if (desired_server_timeout == 0)
199 printf ("%s%sisabling server builtin screensaver.\n\
200 You can re-enable it with \"xset s on\".\n",
201 (p->verbose_p ? "" : blurb()),
202 (p->verbose_p ? "\n\tD" : ": d"));
205 fprintf (stderr, "%s: (xset s %d %d %s %s)\n", blurb(),
206 desired_server_timeout, desired_server_interval,
207 (desired_prefer_blank ? "blank" : "noblank"),
208 (desired_allow_exp ? "noexpose" : "expose"));
210 XSetScreenSaver (si->dpy,
211 desired_server_timeout, desired_server_interval,
212 desired_prefer_blank, desired_allow_exp);
213 XSync(si->dpy, False);
217 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
219 static Bool extension_initted = False;
220 if (!extension_initted)
222 extension_initted = True;
223 # ifdef HAVE_MIT_SAVER_EXTENSION
224 if (p->use_mit_saver_extension) init_mit_saver_extension(si);
226 # ifdef HAVE_SGI_SAVER_EXTENSION
227 if (p->use_sgi_saver_extension) init_sgi_saver_extension(si);
231 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
234 /* Turn off the server builtin saver if it is now running. */
235 XForceScreenSaver (si->dpy, ScreenSaverReset);
239 /* Display Power Management System (DPMS.)
241 On XFree86 systems, "man xset" reports:
243 -dpms The -dpms option disables DPMS (Energy Star) features.
244 +dpms The +dpms option enables DPMS (Energy Star) features.
247 The dpms option allows the DPMS (Energy Star)
248 parameters to be set. The option can take up to three
249 numerical values, or the `force' flag followed by a
250 DPMS state. The `force' flags forces the server to
251 immediately switch to the DPMS state specified. The
252 DPMS state can be one of `standby', `suspend', or
253 `off'. When numerical values are given, they set the
254 inactivity period before the three modes are activated.
255 The first value given is for the `standby' mode, the
256 second is for the `suspend' mode, and the third is for
257 the `off' mode. Setting these values implicitly
258 enables the DPMS features. A value of zero disables a
261 However, note that the implementation is more than a little bogus,
262 in that there is code in /usr/X11R6/lib/libXdpms.a to implement all
263 the usual server-extension-querying utilities -- but there are no
264 prototypes in any header file! Thus, the prototypes here. (The
265 stuff in X11/extensions/dpms.h and X11/extensions/dpmsstr.h define
266 the raw X protcol, they don't define the API to libXdpms.a.)
269 #ifdef HAVE_DPMS_EXTENSION
271 #include <X11/Xproto.h> /* for CARD16 */
272 #include <X11/extensions/dpms.h>
273 #include <X11/extensions/dpmsstr.h>
275 extern Bool DPMSQueryExtension (Display *dpy, int *event_ret, int *error_ret);
276 extern Bool DPMSCapable (Display *dpy);
277 extern Status DPMSForceLevel (Display *dpy, CARD16 level);
278 extern Status DPMSInfo (Display *dpy, CARD16 *power_level, BOOL *state);
280 #if 0 /* others we don't use */
281 extern Status DPMSGetVersion (Display *dpy, int *major_ret, int *minor_ret);
282 extern Status DPMSSetTimeouts (Display *dpy,
283 CARD16 standby, CARD16 suspend, CARD16 off);
284 extern Bool DPMSGetTimeouts (Display *dpy,
285 CARD16 *standby, CARD16 *suspend, CARD16 *off);
286 extern Status DPMSEnable (Display *dpy);
287 extern Status DPMSDisable (Display *dpy);
292 monitor_powered_on_p (saver_info *si)
295 int event_number, error_number;
299 if (!DPMSQueryExtension(si->dpy, &event_number, &error_number))
300 /* Server doesn't know -- assume the monitor is on. */
303 else if (!DPMSCapable(si->dpy))
304 /* Server says the monitor doesn't do power management -- so it's on. */
309 DPMSInfo(si->dpy, &state, &onoff);
311 /* Server says DPMS is disabled -- so the monitor is on. */
315 case DPMSModeOn: result = True; break; /* really on */
316 case DPMSModeStandby: result = False; break; /* kinda off */
317 case DPMSModeSuspend: result = False; break; /* pretty off */
318 case DPMSModeOff: result = False; break; /* really off */
319 default: result = True; break; /* protocol error? */
327 monitor_power_on (saver_info *si)
329 if (!monitor_powered_on_p (si))
331 DPMSForceLevel(si->dpy, DPMSModeOn);
332 XSync(si->dpy, False);
333 if (!monitor_powered_on_p (si))
335 "%s: DPMSForceLevel(dpy, DPMSModeOn) did not power the monitor on?\n",
340 #else /* !HAVE_DPMS_EXTENSION */
343 monitor_powered_on_p (saver_info *si)
349 monitor_power_on (saver_info *si)
354 #endif /* !HAVE_DPMS_EXTENSION */