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 p->use_sgi_saver_extension = False;
138 #endif /* HAVE_SGI_SAVER_EXTENSION */
141 /* Figuring out what the appropriate XSetScreenSaver() parameters are
142 (one wouldn't expect this to be rocket science.)
146 disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
148 saver_preferences *p = &si->prefs;
149 int current_server_timeout, current_server_interval;
150 int current_prefer_blank, current_allow_exp;
151 int desired_server_timeout, desired_server_interval;
152 int desired_prefer_blank, desired_allow_exp;
154 XGetScreenSaver (si->dpy, ¤t_server_timeout, ¤t_server_interval,
155 ¤t_prefer_blank, ¤t_allow_exp);
157 desired_server_timeout = current_server_timeout;
158 desired_server_interval = current_server_interval;
159 desired_prefer_blank = current_prefer_blank;
160 desired_allow_exp = current_allow_exp;
162 /* On SGIs, if interval is non-zero, it is the number of seconds after
163 screen saving starts at which the monitor should be powered down.
164 Obviously I don't want that, so set it to 0 (meaning "never".)
166 Power saving is disabled if DontPreferBlanking, but in that case,
167 we don't get extension events either. So we can't turn it off that way.
169 Note: if you're running Irix 6.3 (O2), you may find that your monitor is
170 powering down anyway, regardless of the xset settings. This is fixed by
171 installing SGI patches 2447 and 2537.
173 desired_server_interval = 0;
175 /* I suspect (but am not sure) that DontAllowExposures might have
176 something to do with powering off the monitor as well. */
177 desired_allow_exp = AllowExposures;
179 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
180 if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
182 desired_server_timeout = (p->timeout / 1000);
184 /* The SGI extension won't give us events unless blanking is on.
185 I think (unsure right now) that the MIT extension is the opposite. */
186 if (p->use_sgi_saver_extension)
187 desired_prefer_blank = PreferBlanking;
189 desired_prefer_blank = DontPreferBlanking;
192 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
194 desired_server_timeout = 0;
197 if (desired_server_timeout != current_server_timeout ||
198 desired_server_interval != current_server_interval ||
199 desired_prefer_blank != current_prefer_blank ||
200 desired_allow_exp != current_allow_exp)
202 if (desired_server_timeout == 0)
204 "%s%sisabling server builtin screensaver.\n"
205 "\tYou can re-enable it with \"xset s on\".\n",
206 (p->verbose_p ? "" : blurb()),
207 (p->verbose_p ? "\n\tD" : ": d"));
210 fprintf (stderr, "%s: (xset s %d %d %s %s)\n", blurb(),
211 desired_server_timeout, desired_server_interval,
212 (desired_prefer_blank ? "blank" : "noblank"),
213 (desired_allow_exp ? "noexpose" : "expose"));
215 XSetScreenSaver (si->dpy,
216 desired_server_timeout, desired_server_interval,
217 desired_prefer_blank, desired_allow_exp);
218 XSync(si->dpy, False);
222 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
224 static Bool extension_initted = False;
225 if (!extension_initted)
227 extension_initted = True;
228 # ifdef HAVE_MIT_SAVER_EXTENSION
229 if (p->use_mit_saver_extension) init_mit_saver_extension(si);
231 # ifdef HAVE_SGI_SAVER_EXTENSION
232 if (p->use_sgi_saver_extension) init_sgi_saver_extension(si);
236 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
239 /* Turn off the server builtin saver if it is now running. */
240 XForceScreenSaver (si->dpy, ScreenSaverReset);
244 /* Display Power Management System (DPMS.)
246 On XFree86 systems, "man xset" reports:
248 -dpms The -dpms option disables DPMS (Energy Star) features.
249 +dpms The +dpms option enables DPMS (Energy Star) features.
252 The dpms option allows the DPMS (Energy Star)
253 parameters to be set. The option can take up to three
254 numerical values, or the `force' flag followed by a
255 DPMS state. The `force' flags forces the server to
256 immediately switch to the DPMS state specified. The
257 DPMS state can be one of `standby', `suspend', or
258 `off'. When numerical values are given, they set the
259 inactivity period before the three modes are activated.
260 The first value given is for the `standby' mode, the
261 second is for the `suspend' mode, and the third is for
262 the `off' mode. Setting these values implicitly
263 enables the DPMS features. A value of zero disables a
266 However, note that the implementation is more than a little bogus,
267 in that there is code in /usr/X11R6/lib/libXdpms.a to implement all
268 the usual server-extension-querying utilities -- but there are no
269 prototypes in any header file! Thus, the prototypes here. (The
270 stuff in X11/extensions/dpms.h and X11/extensions/dpmsstr.h define
271 the raw X protcol, they don't define the API to libXdpms.a.)
274 #ifdef HAVE_DPMS_EXTENSION
276 #include <X11/Xproto.h> /* for CARD16 */
277 #include <X11/extensions/dpms.h>
278 #include <X11/extensions/dpmsstr.h>
280 extern Bool DPMSQueryExtension (Display *dpy, int *event_ret, int *error_ret);
281 extern Bool DPMSCapable (Display *dpy);
282 extern Status DPMSForceLevel (Display *dpy, CARD16 level);
283 extern Status DPMSInfo (Display *dpy, CARD16 *power_level, BOOL *state);
285 #if 0 /* others we don't use */
286 extern Status DPMSGetVersion (Display *dpy, int *major_ret, int *minor_ret);
287 extern Status DPMSSetTimeouts (Display *dpy,
288 CARD16 standby, CARD16 suspend, CARD16 off);
289 extern Bool DPMSGetTimeouts (Display *dpy,
290 CARD16 *standby, CARD16 *suspend, CARD16 *off);
291 extern Status DPMSEnable (Display *dpy);
292 extern Status DPMSDisable (Display *dpy);
297 monitor_powered_on_p (saver_info *si)
300 int event_number, error_number;
304 if (!DPMSQueryExtension(si->dpy, &event_number, &error_number))
305 /* Server doesn't know -- assume the monitor is on. */
308 else if (!DPMSCapable(si->dpy))
309 /* Server says the monitor doesn't do power management -- so it's on. */
314 DPMSInfo(si->dpy, &state, &onoff);
316 /* Server says DPMS is disabled -- so the monitor is on. */
320 case DPMSModeOn: result = True; break; /* really on */
321 case DPMSModeStandby: result = False; break; /* kinda off */
322 case DPMSModeSuspend: result = False; break; /* pretty off */
323 case DPMSModeOff: result = False; break; /* really off */
324 default: result = True; break; /* protocol error? */
332 monitor_power_on (saver_info *si)
334 if (!monitor_powered_on_p (si))
336 DPMSForceLevel(si->dpy, DPMSModeOn);
337 XSync(si->dpy, False);
338 if (!monitor_powered_on_p (si))
340 "%s: DPMSForceLevel(dpy, DPMSModeOn) did not power the monitor on?\n",
345 #else /* !HAVE_DPMS_EXTENSION */
348 monitor_powered_on_p (saver_info *si)
354 monitor_power_on (saver_info *si)
359 #endif /* !HAVE_DPMS_EXTENSION */