ftp://ftp.uni-heidelberg.de/pub/X11/contrib/applications/xscreensaver-2.07.tar.gz
[xscreensaver] / driver / xset.c
1 /* xset.c --- interacting with server extensions and the builtin screensaver.
2  * xscreensaver, Copyright (c) 1991-1997 Jamie Zawinski <jwz@netscape.com>
3  *
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 
10  * implied warranty.
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <stdio.h>
18 #include <X11/Xlib.h>
19 #include <X11/Xutil.h>
20 #include <X11/Xatom.h>
21 #include <X11/Xos.h>
22
23 /* This file doesn't need the Xt headers, so stub these types out... */
24 #undef XtPointer
25 #define XtAppContext void*
26 #define XrmDatabase  void*
27 #define XtIntervalId void*
28 #define XtPointer    void*
29 #define Widget       void*
30
31 #include "xscreensaver.h"
32
33 \f
34 /* MIT SCREEN-SAVER server extension hackery.
35  */
36
37 #ifdef HAVE_MIT_SAVER_EXTENSION
38
39 # include <X11/extensions/scrnsaver.h>
40
41 Bool
42 query_mit_saver_extension (saver_info *si)
43 {
44   return XScreenSaverQueryExtension (si->dpy,
45                                      &si->mit_saver_ext_event_number,
46                                      &si->mit_saver_ext_error_number);
47 }
48
49 static int
50 ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
51 {
52   return 0;
53 }
54
55 static void
56 init_mit_saver_extension (saver_info *si)
57 {
58   int i;
59   Pixmap *blank_pix = (Pixmap *) calloc (sizeof(Pixmap), si->nscreens);
60
61   for (i = 0; i < si->nscreens; i++)
62     {
63       saver_screen_info *ssi = &si->screens[i];
64       XID kill_id = 0;
65       Atom kill_type = 0;
66       Window root = RootWindowOfScreen (ssi->screen);
67       blank_pix[i] = XCreatePixmap (si->dpy, root, 1, 1, 1);
68
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),
74                                      &kill_id, &kill_type)
75           && kill_id != blank_pix[i])
76         {
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);
82         }
83       XScreenSaverSelectInput (si->dpy, root, ScreenSaverNotifyMask);
84       XScreenSaverRegister (si->dpy,
85                             XScreenNumberOfScreen (ssi->screen),
86                             (XID) blank_pix[i], XA_PIXMAP);
87     }
88   free(blank_pix);
89 }
90 #endif /* HAVE_MIT_SAVER_EXTENSION */
91
92 \f
93 /* SGI SCREEN_SAVER server extension hackery.
94  */
95
96 #ifdef HAVE_SGI_SAVER_EXTENSION
97
98 # include <X11/extensions/XScreenSaver.h>
99
100 Bool
101 query_sgi_saver_extension (saver_info *si)
102 {
103   return XScreenSaverQueryExtension (si->dpy,
104                                      &si->sgi_saver_ext_event_number,
105                                      &si->sgi_saver_ext_error_number);
106 }
107
108 static void
109 init_sgi_saver_extension (saver_info *si)
110 {
111   saver_preferences *p = &si->prefs;
112   int i;
113   if (si->screen_blanked_p)
114     /* If you mess with this while the server thinks it's active,
115        the server crashes. */
116     return;
117
118   for (i = 0; i < si->nscreens; i++)
119     {
120       saver_screen_info *ssi = &si->screens[i];
121       XScreenSaverDisable (si->dpy, XScreenNumberOfScreen(ssi->screen));
122       if (! XScreenSaverEnable (si->dpy, XScreenNumberOfScreen(ssi->screen)))
123         {
124           fprintf (stderr,
125        "%s: SGI SCREEN_SAVER extension exists, but can't be initialized;\n\
126                 perhaps some other screensaver program is already running?\n",
127                    progname);
128           p->use_sgi_saver_extension = False;
129           return;
130         }
131     }
132 }
133
134 #endif /* HAVE_SGI_SAVER_EXTENSION */
135
136 \f
137 /* Figuring out what the appropriate XSetScreenSaver() paramters are
138    (one wouldn't expect this to be rocket science.)
139  */
140
141 void
142 disable_builtin_screensaver (saver_info *si, Bool turn_off_p)
143 {
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;
149
150   XGetScreenSaver (si->dpy, &current_server_timeout, &current_server_interval,
151                    &current_prefer_blank, &current_allow_exp);
152
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;
157
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 make sure it's 0.
161
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.
164    */
165   desired_server_interval = 0;
166
167   /* I suspect (but am not sure) that DontAllowExposures might have
168      something to do with powering off the monitor as well. */
169   desired_allow_exp = AllowExposures;
170
171 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
172   if (p->use_mit_saver_extension || p->use_sgi_saver_extension)
173     {
174       desired_server_timeout = (p->timeout / 1000);
175
176       /* The SGI extension won't give us events unless blanking is on.
177          I think (unsure right now) that the MIT extension is the opposite. */
178       if (p->use_sgi_saver_extension)
179         desired_prefer_blank = PreferBlanking;
180       else
181         desired_prefer_blank = DontPreferBlanking;
182     }
183   else
184 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
185     {
186       desired_server_timeout = 0;
187     }
188
189   if (desired_server_timeout != current_server_timeout ||
190       desired_server_interval != current_server_interval ||
191       desired_prefer_blank != current_prefer_blank ||
192       desired_allow_exp != current_allow_exp)
193     {
194       if (desired_server_timeout == 0)
195         printf ("%s%sisabling server builtin screensaver.\n\
196         You can re-enable it with \"xset s on\".\n",
197                 (p->verbose_p ? "" : progname),
198                 (p->verbose_p ? "\n\tD" : ": d"));
199
200       if (p->verbose_p)
201         fprintf (stderr, "%s: (xset s %d %d %s %s)\n", progname,
202                  desired_server_timeout, desired_server_interval,
203                  (desired_prefer_blank ? "blank" : "noblank"),
204                  (desired_allow_exp ? "noexpose" : "expose"));
205
206       XSetScreenSaver (si->dpy,
207                        desired_server_timeout, desired_server_interval,
208                        desired_prefer_blank, desired_allow_exp);
209       XSync(si->dpy, False);
210     }
211
212
213 #if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION)
214   {
215     static Bool extension_initted = False;
216     if (!extension_initted)
217       {
218         extension_initted = True;
219 # ifdef HAVE_MIT_SAVER_EXTENSION
220         if (p->use_mit_saver_extension) init_mit_saver_extension(si);
221 # endif
222 # ifdef HAVE_SGI_SAVER_EXTENSION
223         if (p->use_sgi_saver_extension) init_sgi_saver_extension(si);
224 # endif
225       }
226   }
227 #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */
228
229   if (turn_off_p)
230     /* Turn off the server builtin saver if it is now running. */
231     XForceScreenSaver (si->dpy, ScreenSaverReset);
232 }