~ubuntu-branches/ubuntu/breezy/xscreensaver/breezy

« back to all changes in this revision

Viewing changes to driver/xscreensaver.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2005-10-11 21:00:42 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20051011210042-u7q6zslgevdxspr3
Tags: 4.21-4ubuntu17
updated pt_BR again, fixed to UTF-8 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* xscreensaver, Copyright (c) 1991-2001 Jamie Zawinski <jwz@jwz.org>
 
1
/* xscreensaver, Copyright (c) 1991-2005 Jamie Zawinski <jwz@jwz.org>
2
2
 *
3
3
 * Permission to use, copy, modify, distribute, and sell this software and its
4
4
 * documentation for any purpose is hereby granted without fee, provided that
16
16
 *   on (nearly) all windows; or by waiting for the MIT-SCREEN-SAVER extension
17
17
 *   to send us a "you are idle" event.
18
18
 *
19
 
 *   Then, we map a full screen black window (or, in the case of the 
20
 
 *   MIT-SCREEN-SAVER extension, use the one it gave us.)
 
19
 *   Then, we map a full screen black window.
21
20
 *
22
21
 *   We place a __SWM_VROOT property on this window, so that newly-started
23
 
 *   clients will think that this window is a "virtual root" window.
 
22
 *   clients will think that this window is a "virtual root" window (as per
 
23
 *   the logic in the historical "vroot.h" header.)
24
24
 *
25
25
 *   If there is an existing "virtual root" window (one that already had
26
26
 *   an __SWM_VROOT property) then we remove that property from that window.
38
38
 *   When they are, we kill the inferior process, unmap the window, and restore
39
39
 *   the __SWM_VROOT property to the real virtual root window if there was one.
40
40
 *
41
 
 *   While we are waiting, we also set up timers so that, after a certain 
42
 
 *   amount of time has passed, we can start a different screenhack.  We do
43
 
 *   this by killing the running child process with SIGTERM, and then starting
44
 
 *   a new one in the same way.
 
41
 *   On multi-screen systems, we do the above on each screen, and start
 
42
 *   multiple programs, each with a different value of $DISPLAY.
 
43
 *
 
44
 *   On Xinerama systems, we do a similar thing, but instead create multiple
 
45
 *   windows on the (only) display, and tell the subprocess which one to use
 
46
 *   via the $XSCREENSAVER_WINDOW environment variable -- this trick requires
 
47
 *   a recent (Aug 2003) revision of vroot.h.
 
48
 *
 
49
 *   While we are waiting for user activity, we also set up timers so that,
 
50
 *   after a certain amount of time has passed, we can start a different
 
51
 *   screenhack.  We do this by killing the running child process with
 
52
 *   SIGTERM, and then starting a new one in the same way.
45
53
 *
46
54
 *   If there was a real virtual root, meaning that we removed the __SWM_VROOT
47
55
 *   property from it, meaning we must (absolutely must) restore it before we
57
65
 *   can really fuck up the world by killing this process with "kill -9".
58
66
 *
59
67
 *   This program accepts ClientMessages of type SCREENSAVER; these messages
60
 
 *   may contain the atom ACTIVATE or DEACTIVATE, meaning to turn the 
 
68
 *   may contain the atoms ACTIVATE, DEACTIVATE, etc, meaning to turn the 
61
69
 *   screensaver on or off now, regardless of the idleness of the user,
62
70
 *   and a few other things.  The included "xscreensaver-command" program
63
71
 *   sends these messsages.
92
100
 *   "client changing event mask" problem that the KeyPress events hack does.
93
101
 *   I think polling is more reliable.
94
102
 *
95
 
 *   None of this crap happens if we're using one of the extensions, so install
96
 
 *   one of them if the description above sounds just too flaky to live.  It
97
 
 *   is, but those are your choices.
 
103
 *   On systems with /proc/interrupts (Linux) we poll that file and note when
 
104
 *   the interrupt counter numbers on the "keyboard" and "PS/2" lines change.
 
105
 *   (There is no reliable way, using /proc/interrupts, to detect non-PS/2
 
106
 *   mice, so it doesn't help for serial or USB mice.)
 
107
 *
 
108
 *   None of this crap happens if we're using one of the extensions.  Sadly,
 
109
 *   the XIdle extension hasn't been available for many years; the SGI
 
110
 *   extension only exists on SGIs; and the MIT extension, while widely
 
111
 *   deployed, is garbage in several ways.
98
112
 *
99
113
 *   A third idle-detection option could be implemented (but is not): when
100
114
 *   running on the console display ($DISPLAY is `localhost`:0) and we're on a
127
141
#include <stdio.h>
128
142
#include <ctype.h>
129
143
#include <X11/Xlib.h>
 
144
 
 
145
#include <X11/Xlibint.h>
 
146
 
130
147
#include <X11/Xatom.h>
131
148
#include <X11/Intrinsic.h>
132
149
#include <X11/StringDefs.h>
133
150
#include <X11/Shell.h>
134
151
#include <X11/Xos.h>
 
152
#include <time.h>
 
153
#include <sys/time.h>
135
154
#include <netdb.h>      /* for gethostbyname() */
136
155
#ifdef HAVE_XMU
137
156
# ifndef VMS
147
166
# include <X11/extensions/xidle.h>
148
167
#endif /* HAVE_XIDLE_EXTENSION */
149
168
 
 
169
#ifdef HAVE_XINERAMA
 
170
# include <X11/extensions/Xinerama.h>
 
171
#endif /* HAVE_XINERAMA */
 
172
 
150
173
#include "xscreensaver.h"
151
174
#include "version.h"
152
175
#include "yarandom.h"
169
192
 
170
193
 
171
194
static XrmOptionDescRec options [] = {
 
195
 
 
196
  { "-verbose",            ".verbose",          XrmoptionNoArg, "on" },
 
197
  { "-silent",             ".verbose",          XrmoptionNoArg, "off" },
 
198
 
 
199
  /* xscreensaver-demo uses this one */
 
200
  { "-nosplash",           ".splash",           XrmoptionNoArg, "off" },
 
201
  { "-no-splash",          ".splash",           XrmoptionNoArg, "off" },
 
202
 
 
203
  /* useful for debugging */
 
204
  { "-no-capture-stderr",  ".captureStderr",    XrmoptionNoArg, "off" },
 
205
 
 
206
  /* There's really no reason to have these command-line args; they just
 
207
     lead to confusion when the .xscreensaver file has conflicting values.
 
208
   */
 
209
#if 0
 
210
  { "-splash",             ".splash",           XrmoptionNoArg, "on" },
 
211
  { "-capture-stderr",     ".captureStderr",    XrmoptionNoArg, "on" },
172
212
  { "-timeout",            ".timeout",          XrmoptionSepArg, 0 },
173
213
  { "-cycle",              ".cycle",            XrmoptionSepArg, 0 },
174
214
  { "-lock-mode",          ".lock",             XrmoptionNoArg, "on" },
180
220
  { "-visual",             ".visualID",         XrmoptionSepArg, 0 },
181
221
  { "-install",            ".installColormap",  XrmoptionNoArg, "on" },
182
222
  { "-no-install",         ".installColormap",  XrmoptionNoArg, "off" },
183
 
  { "-verbose",            ".verbose",          XrmoptionNoArg, "on" },
184
 
  { "-silent",             ".verbose",          XrmoptionNoArg, "off" },
185
223
  { "-timestamp",          ".timestamp",        XrmoptionNoArg, "on" },
186
 
  { "-capture-stderr",     ".captureStderr",    XrmoptionNoArg, "on" },
187
 
  { "-no-capture-stderr",  ".captureStderr",    XrmoptionNoArg, "off" },
188
224
  { "-xidle-extension",    ".xidleExtension",   XrmoptionNoArg, "on" },
189
225
  { "-no-xidle-extension", ".xidleExtension",   XrmoptionNoArg, "off" },
190
226
  { "-mit-extension",      ".mitSaverExtension",XrmoptionNoArg, "on" },
193
229
  { "-no-sgi-extension",   ".sgiSaverExtension",XrmoptionNoArg, "off" },
194
230
  { "-proc-interrupts",    ".procInterrupts",   XrmoptionNoArg, "on" },
195
231
  { "-no-proc-interrupts", ".procInterrupts",   XrmoptionNoArg, "off" },
196
 
  { "-splash",             ".splash",           XrmoptionNoArg, "on" },
197
 
  { "-no-splash",          ".splash",           XrmoptionNoArg, "off" },
198
 
  { "-nosplash",           ".splash",           XrmoptionNoArg, "off" },
199
232
  { "-idelay",             ".initialDelay",     XrmoptionSepArg, 0 },
200
233
  { "-nice",               ".nice",             XrmoptionSepArg, 0 },
201
 
 
202
 
  /* Actually these are built in to Xt, but just to be sure... */
203
 
  { "-synchronous",        ".synchronous",      XrmoptionNoArg, "on" },
204
 
  { "-xrm",                NULL,                XrmoptionResArg, NULL }
 
234
#endif /* 0 */
205
235
};
206
236
 
 
237
#ifdef __GNUC__
 
238
 __extension__     /* shut up about "string length is greater than the length
 
239
                      ISO C89 compilers are required to support" when including
 
240
                      the .ad file... */
 
241
#endif
 
242
 
207
243
static char *defaults[] = {
208
244
#include "XScreenSaver_ad.h"
209
245
 0
219
255
  fflush (stdout);
220
256
  fflush (stderr);
221
257
  fprintf (stdout, "\
222
 
xscreensaver %s, copyright (c) 1991-2001 by Jamie Zawinski <jwz@jwz.org>\n\
223
 
The standard Xt command-line options are accepted; other options include:\n\
224
 
\n\
225
 
    -timeout <minutes>       When the screensaver should activate.\n\
226
 
    -cycle <minutes>         How long to let each hack run before switching.\n\
227
 
    -lock-mode               Require a password before deactivating.\n\
228
 
    -lock-timeout <minutes>  Grace period before locking; default 0.\n\
229
 
    -visual <id-or-class>    Which X visual to run on.\n\
230
 
    -install                 Install a private colormap.\n\
231
 
    -verbose                 Be loud.\n\
232
 
    -no-splash               Don't display a splash-screen at startup.\n\
233
 
    -help                    This message.\n\
234
 
\n\
235
 
See the manual for other options and X resources.\n\
236
 
\n\
237
 
The `xscreensaver' program should be left running in the background.\n\
238
 
Use the `xscreensaver-demo' and `xscreensaver-command' programs to\n\
239
 
manipulate a running xscreensaver.\n\
240
 
\n\
241
 
The `*programs' resource controls which graphics demos will be launched by\n\
242
 
the screensaver.  See `man xscreensaver' or the web page for more details.\n\
243
 
\n\
244
 
Just getting started?  Try this:\n\
 
258
xscreensaver %s, copyright (c) 1991-2005 by Jamie Zawinski <jwz@jwz.org>\n\
 
259
\n\
 
260
  All xscreensaver configuration is via the `~/.xscreensaver' file.\n\
 
261
  Rather than editing that file by hand, just run `xscreensaver-demo':\n\
 
262
  that program lets you configure the screen saver graphically,\n\
 
263
  including timeouts, locking, and display modes.\n\
 
264
\n",
 
265
          si->version);
 
266
  fprintf (stdout, "\
 
267
  Just getting started?  Try this:\n\
245
268
\n\
246
269
        xscreensaver &\n\
247
270
        xscreensaver-demo\n\
248
271
\n\
249
 
For updates, check http://www.jwz.org/xscreensaver/\n\
250
 
\n",
251
 
          si->version);
 
272
  For updates, online manual, and FAQ, please see the web page:\n\
 
273
\n\
 
274
       http://www.jwz.org/xscreensaver/\n\
 
275
\n");
 
276
 
252
277
  fflush (stdout);
253
278
  fflush (stderr);
254
279
  exit (1);
293
318
{
294
319
  saver_info *si = global_si_kludge;    /* I hate C so much... */
295
320
  int i;
 
321
  Bool fatal_p;
296
322
 
297
323
  if (!real_stderr) real_stderr = stderr;
298
324
 
303
329
           blurb());
304
330
 
305
331
  for (i = 0; i < si->nscreens; i++)
306
 
    fprintf (real_stderr, "%s: screen %d: 0x%x, 0x%x, 0x%x\n",
307
 
             blurb(), i,
308
 
             RootWindowOfScreen (si->screens[i].screen),
309
 
             si->screens[i].real_vroot,
310
 
             si->screens[i].screensaver_window);
 
332
    {
 
333
      saver_screen_info *ssi = &si->screens[i];
 
334
      fprintf (real_stderr, "%s: screen %d/%d: 0x%x, 0x%x, 0x%x\n",
 
335
               blurb(), ssi->real_screen_number, ssi->number,
 
336
               (unsigned int) RootWindowOfScreen (si->screens[i].screen),
 
337
               (unsigned int) si->screens[i].real_vroot,
 
338
               (unsigned int) si->screens[i].screensaver_window);
 
339
    }
311
340
 
312
341
  fprintf (real_stderr, "\n"
313
342
           "#######################################"
314
343
           "#######################################\n\n");
315
344
 
316
 
  if (XmuPrintDefaultErrorMessage (dpy, error, real_stderr))
 
345
  fatal_p = XmuPrintDefaultErrorMessage (dpy, error, real_stderr);
 
346
 
 
347
  fatal_p = True;  /* The only time I've ever seen a supposedly nonfatal error,
 
348
                      it has been BadImplementation / Xlib sequence lost, which
 
349
                      are in truth pretty damned fatal.
 
350
                    */
 
351
 
 
352
  fprintf (real_stderr, "\n");
 
353
 
 
354
  if (! fatal_p)
 
355
    fprintf (real_stderr, "%s: nonfatal error.\n\n", blurb());
 
356
  else
317
357
    {
318
 
      fprintf (real_stderr, "\n");
319
358
      if (si->prefs.xsync_p)
320
359
        {
321
360
          saver_exit (si, -1, "because of synchronous X Error");
331
370
   "    bug.  That will cause xscreensaver to dump a `core' file to the\n"
332
371
   "    current directory.  Please include the stack trace from that core\n"
333
372
   "    file in your bug report.  *DO NOT* mail the core file itself!\n"
334
 
   "    That won't work.\n"
 
373
   "    That won't work.\n");
 
374
          fprintf (real_stderr,
335
375
   "\n"
336
376
   "    http://www.jwz.org/xscreensaver/bugs.html explains how to create\n"
337
377
   "    the most useful bug reports, and how to examine core files.\n"
346
386
          saver_exit (si, -1, 0);
347
387
        }
348
388
    }
349
 
  else
350
 
    fprintf (real_stderr, " (nonfatal.)\n");
 
389
 
351
390
  return 0;
352
391
}
353
392
 
477
516
      si->locking_disabled_p = True;
478
517
      si->nolock_reason = "error getting password";
479
518
    }
 
519
 
 
520
  /* If locking is currently enabled, but the environment indicates that
 
521
     we have been launched as GDM's "Background" program, then disable
 
522
     locking just in case.
 
523
   */
 
524
  if (!si->locking_disabled_p && getenv ("RUNNING_UNDER_GDM"))
 
525
    {
 
526
      si->locking_disabled_p = True;
 
527
      si->nolock_reason = "running under GDM";
 
528
    }
 
529
 
 
530
  /* If the server is XDarwin (MacOS X) then disable locking.
 
531
     (X grabs only affect X programs, so you can use Command-Tab
 
532
     to bring any other Mac program to the front, e.g., Terminal.)
 
533
   */
 
534
  if (!si->locking_disabled_p)
 
535
    {
 
536
      int op = 0, event = 0, error = 0;
 
537
      Bool macos_p = False;
 
538
 
 
539
#ifdef __APPLE__
 
540
      /* Disable locking if *running* on Apple hardware, since we have no
 
541
         reliable way to determine whether the server is running on MacOS.
 
542
         Hopefully __APPLE__ means "MacOS" and not "Linux on Mac hardware"
 
543
         but I'm not really sure about that.
 
544
       */
 
545
      macos_p = True;
 
546
#endif
 
547
 
 
548
      if (!macos_p)
 
549
        /* This extension exists on the Apple X11 server, but not
 
550
           on earlier versions of the XDarwin server. */
 
551
        macos_p = XQueryExtension (si->dpy, "Apple-DRI", &op, &event, &error);
 
552
 
 
553
      if (macos_p)
 
554
        {
 
555
          si->locking_disabled_p = True;
 
556
          si->nolock_reason = "Cannot lock securely on MacOS X";
 
557
        }
 
558
    }
 
559
 
480
560
#endif /* NO_LOCKING */
481
 
 
482
 
  hack_uid (si);
483
561
}
484
562
 
485
563
 
494
572
  char *d = getenv ("DISPLAY");
495
573
  if (!d || !*d)
496
574
    {
497
 
      char ndpy[] = "DISPLAY=:0.0";
 
575
      char *ndpy = strdup("DISPLAY=:0.0");
498
576
      /* if (si->prefs.verbose_p) */      /* sigh, too early to test this... */
499
577
        fprintf (stderr,
500
578
                 "%s: warning: $DISPLAY is not set: defaulting to \"%s\".\n",
501
579
                 blurb(), ndpy+8);
502
580
      if (putenv (ndpy))
503
581
        abort ();
 
582
      /* don't free (ndpy) -- some implementations of putenv (BSD 4.4,
 
583
         glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2)
 
584
         do not.  So we must leak it (and/or the previous setting). Yay.
 
585
       */
504
586
    }
505
587
#endif /* HAVE_PUTENV */
506
588
 
529
611
  XA_SCREENSAVER_RESPONSE = XInternAtom (si->dpy, "_SCREENSAVER_RESPONSE",
530
612
                                         False);
531
613
  XA_XSETROOT_ID = XInternAtom (si->dpy, "_XSETROOT_ID", False);
 
614
  XA_ESETROOT_PMAP_ID = XInternAtom (si->dpy, "ESETROOT_PMAP_ID", False);
 
615
  XA_XROOTPMAP_ID = XInternAtom (si->dpy, "_XROOTPMAP_ID", False);
532
616
  XA_ACTIVATE = XInternAtom (si->dpy, "ACTIVATE", False);
533
617
  XA_DEACTIVATE = XInternAtom (si->dpy, "DEACTIVATE", False);
534
618
  XA_RESTART = XInternAtom (si->dpy, "RESTART", False);
635
719
 
636
720
  if (p->verbose_p)
637
721
    fprintf (stderr,
638
 
             "%s %s, copyright (c) 1991-2001 "
 
722
             "%s %s, copyright (c) 1991-2005 "
639
723
             "by Jamie Zawinski <jwz@jwz.org>.\n",
640
724
             progname, si->version);
641
725
 
668
752
      fprintf (stderr, "%s: in process %lu.\n", blurb(),
669
753
               (unsigned long) getpid());
670
754
    }
 
755
}
 
756
 
 
757
static void
 
758
print_lock_failure_banner (saver_info *si)
 
759
{
 
760
  saver_preferences *p = &si->prefs;
671
761
 
672
762
  /* If locking was not able to be initalized for some reason, explain why.
673
763
     (This has to be done after we've read the lock_p resource.)
674
764
   */
675
 
  if (p->lock_p && si->locking_disabled_p)
 
765
  if (si->locking_disabled_p)
676
766
    {
677
767
      p->lock_p = False;
678
768
      fprintf (stderr, "%s: locking is disabled (%s).\n", blurb(),
687
777
                 "\t See the manual for details.\n",
688
778
                 blurb());
689
779
    }
 
780
 
690
781
}
691
782
 
692
783
 
699
790
  Bool found_any_writable_cells = False;
700
791
  int i;
701
792
 
702
 
  si->nscreens = ScreenCount(si->dpy);
703
 
  si->screens = (saver_screen_info *)
704
 
    calloc(sizeof(saver_screen_info), si->nscreens);
705
 
 
706
 
  si->default_screen = &si->screens[DefaultScreen(si->dpy)];
707
 
 
 
793
# ifdef HAVE_XINERAMA
 
794
  {
 
795
    int event, error;
 
796
    si->xinerama_p = (XineramaQueryExtension (si->dpy, &event, &error) &&
 
797
                      XineramaIsActive (si->dpy));
 
798
  }
 
799
 
 
800
  if (si->xinerama_p && ScreenCount (si->dpy) != 1)
 
801
    {
 
802
      si->xinerama_p = False;
 
803
      if (si->prefs.verbose_p)
 
804
        fprintf (stderr,
 
805
                 "%s: Xinerama AND %d screens?  Disabling Xinerama support!\n",
 
806
                 blurb(), ScreenCount(si->dpy));
 
807
    }
 
808
 
 
809
  if (si->xinerama_p)
 
810
    {
 
811
      XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &si->nscreens);
 
812
      if (!xsi)
 
813
        si->xinerama_p = False;
 
814
      else
 
815
        {
 
816
          si->screens = (saver_screen_info *)
 
817
            calloc(sizeof(saver_screen_info), si->nscreens);
 
818
          for (i = 0; i < si->nscreens; i++)
 
819
            {
 
820
              si->screens[i].x      = xsi[i].x_org;
 
821
              si->screens[i].y      = xsi[i].y_org;
 
822
              si->screens[i].width  = xsi[i].width;
 
823
              si->screens[i].height = xsi[i].height;
 
824
            }
 
825
          XFree (xsi);
 
826
        }
 
827
      si->default_screen = &si->screens[0];
 
828
      si->default_screen->real_screen_p = True;
 
829
    }
 
830
# endif /* !HAVE_XINERAMA */
 
831
 
 
832
  if (!si->xinerama_p)
 
833
    {
 
834
      si->nscreens = ScreenCount(si->dpy);
 
835
      si->screens = (saver_screen_info *)
 
836
        calloc(sizeof(saver_screen_info), si->nscreens);
 
837
      si->default_screen = &si->screens[DefaultScreen(si->dpy)];
 
838
 
 
839
      for (i = 0; i < si->nscreens; i++)
 
840
        {
 
841
          saver_screen_info *ssi = &si->screens[i];
 
842
          ssi->width  = DisplayWidth  (si->dpy, i);
 
843
          ssi->height = DisplayHeight (si->dpy, i);
 
844
          ssi->real_screen_p = True;
 
845
          ssi->real_screen_number = i;
 
846
        }
 
847
    }
 
848
 
 
849
 
 
850
  /* In "quad mode", we use the Xinerama code to pretend that there are 4
 
851
     screens for every physical screen, and run four times as many hacks...
 
852
   */
 
853
  if (si->prefs.quad_p)
 
854
    {
 
855
      int ns2 = si->nscreens * 4;
 
856
      saver_screen_info *ssi2 = (saver_screen_info *)
 
857
        calloc(sizeof(saver_screen_info), ns2);
 
858
 
 
859
      for (i = 0; i < si->nscreens; i++)
 
860
        {
 
861
          saver_screen_info *old = &si->screens[i];
 
862
 
 
863
          if (si->prefs.debug_p) old->width = old->width / 2;
 
864
 
 
865
          ssi2[i*4  ] = *old;
 
866
          ssi2[i*4+1] = *old;
 
867
          ssi2[i*4+2] = *old;
 
868
          ssi2[i*4+3] = *old;
 
869
 
 
870
          ssi2[i*4  ].width  /= 2;
 
871
          ssi2[i*4  ].height /= 2;
 
872
 
 
873
          ssi2[i*4+1].x      += ssi2[i*4  ].width;
 
874
          ssi2[i*4+1].width  -= ssi2[i*4  ].width;
 
875
          ssi2[i*4+1].height /= 2;
 
876
 
 
877
          ssi2[i*4+2].y      += ssi2[i*4  ].height;
 
878
          ssi2[i*4+2].width  /= 2;
 
879
          ssi2[i*4+2].height -= ssi2[i*4  ].height;
 
880
 
 
881
          ssi2[i*4+3].x      += ssi2[i*4+2].width;
 
882
          ssi2[i*4+3].y      += ssi2[i*4+2].height;
 
883
          ssi2[i*4+3].width  -= ssi2[i*4+2].width;
 
884
          ssi2[i*4+3].height -= ssi2[i*4+2].height;
 
885
 
 
886
          ssi2[i*4+1].real_screen_p = False;
 
887
          ssi2[i*4+2].real_screen_p = False;
 
888
          ssi2[i*4+3].real_screen_p = False;
 
889
        }
 
890
 
 
891
      si->nscreens = ns2;
 
892
      free (si->screens);
 
893
      si->screens = ssi2;
 
894
      si->default_screen = &si->screens[DefaultScreen(si->dpy) * 4];
 
895
      si->xinerama_p = True;
 
896
    }
 
897
 
 
898
  /* finish initializing the screens.
 
899
   */
708
900
  for (i = 0; i < si->nscreens; i++)
709
901
    {
710
902
      saver_screen_info *ssi = &si->screens[i];
711
903
      ssi->global = si;
712
 
      ssi->screen = ScreenOfDisplay (si->dpy, i);
 
904
 
 
905
      ssi->number = i;
 
906
      ssi->screen = ScreenOfDisplay (si->dpy, ssi->real_screen_number);
 
907
      ssi->poll_mouse_last_root_x = -1;
 
908
      ssi->poll_mouse_last_root_y = -1;
 
909
 
 
910
      if (!si->xinerama_p)
 
911
        {
 
912
          ssi->width  = WidthOfScreen  (ssi->screen);
 
913
          ssi->height = HeightOfScreen (ssi->screen);
 
914
        }
713
915
 
714
916
      /* Note: we can't use the resource ".visual" because Xt is SO FUCKED. */
715
917
      ssi->default_visual =
733
935
                              XtNvisual, ssi->current_visual,
734
936
                              XtNdepth,  visual_depth (ssi->screen,
735
937
                                                       ssi->current_visual),
736
 
                              0);
 
938
                              NULL);
737
939
 
738
940
      if (! found_any_writable_cells)
739
941
        {
825
1027
                 blurb());
826
1028
    }
827
1029
 
 
1030
  /* These are incompatible (or at least, our support for them is...) */
 
1031
  if (si->xinerama_p && si->using_mit_saver_extension)
 
1032
    {
 
1033
      si->using_mit_saver_extension = False;
 
1034
      if (p->verbose_p)
 
1035
        fprintf (stderr, "%s: Xinerama in use: disabling MIT-SCREEN-SAVER.\n",
 
1036
                 blurb());
 
1037
    }
 
1038
 
 
1039
#ifdef HAVE_RANDR
 
1040
  query_randr_extension (si);
 
1041
#endif
 
1042
 
828
1043
  if (!system_has_proc_interrupts_p)
829
1044
    {
830
1045
      si->using_proc_interrupts = False;
889
1104
     for window creation events, so that new subwindows will be noticed.
890
1105
   */
891
1106
  for (i = 0; i < si->nscreens; i++)
892
 
    start_notice_events_timer (si, RootWindowOfScreen (si->screens[i].screen),
893
 
                               False);
 
1107
    {
 
1108
      saver_screen_info *ssi = &si->screens[i];
 
1109
      if (ssi->real_screen_p)
 
1110
        start_notice_events_timer (si,
 
1111
           RootWindowOfScreen (si->screens[i].screen), False);
 
1112
    }
894
1113
 
895
1114
  if (p->verbose_p)
896
1115
    fprintf (stderr, " done.\n");
915
1134
 
916
1135
      /* If the DPMS settings in the init file have changed,
917
1136
         change the settings on the server to match. */
918
 
      sync_server_dpms_settings (si->dpy, p->dpms_enabled_p,
 
1137
      sync_server_dpms_settings (si->dpy,
 
1138
                                 (p->dpms_enabled_p  &&
 
1139
                                  p->mode != DONT_BLANK),
919
1140
                                 p->dpms_standby / 1000,
920
1141
                                 p->dpms_suspend / 1000,
921
1142
                                 p->dpms_off / 1000,
942
1163
  while (1)
943
1164
    {
944
1165
      Bool was_locked = False;
 
1166
 
 
1167
      if (p->verbose_p)
 
1168
        fprintf (stderr, "%s: awaiting idleness.\n", blurb());
 
1169
 
 
1170
      check_for_leaks ("unblanked A");
945
1171
      sleep_until_idle (si, True);
 
1172
      check_for_leaks ("unblanked B");
946
1173
 
947
1174
      if (p->verbose_p)
948
1175
        {
950
1177
            fprintf (stderr, "%s: demoing %d at %s.\n", blurb(),
951
1178
                     si->selection_mode, timestring());
952
1179
          else
953
 
            if (p->verbose_p)
954
 
              fprintf (stderr, "%s: blanking screen at %s.\n", blurb(),
955
 
                       timestring());
 
1180
            fprintf (stderr, "%s: blanking screen at %s.\n", blurb(),
 
1181
                     timestring());
956
1182
        }
957
1183
 
958
1184
      maybe_reload_init_file (si);
959
1185
 
 
1186
      if (p->mode == DONT_BLANK)
 
1187
        {
 
1188
          if (p->verbose_p)
 
1189
            fprintf (stderr, "%s: idle with blanking disabled at %s.\n",
 
1190
                     blurb(), timestring());
 
1191
 
 
1192
          /* Go around the loop and wait for the next bout of idleness,
 
1193
             or for the init file to change, or for a remote command to
 
1194
             come in, or something.
 
1195
 
 
1196
             But, if locked_p is true, go ahead.  This can only happen
 
1197
             if we're in "disabled" mode but a "lock" clientmessage came
 
1198
             in: in that case, we should go ahead and blank/lock the screen.
 
1199
           */
 
1200
          if (!si->locked_p)
 
1201
            continue;
 
1202
        }
 
1203
 
 
1204
      /* Since we're about to blank the screen, kill the de-race timer,
 
1205
         if any.  It might still be running if we have unblanked and then
 
1206
         re-blanked in a short period (e.g., when using the "next" button
 
1207
         in xscreensaver-demo.)
 
1208
       */
 
1209
      if (si->de_race_id)
 
1210
        {
 
1211
          if (p->verbose_p)
 
1212
            fprintf (stderr, "%s: stopping de-race timer (%d remaining.)\n",
 
1213
                     blurb(), si->de_race_ticks);
 
1214
          XtRemoveTimeOut (si->de_race_id);
 
1215
          si->de_race_id = 0;
 
1216
        }
 
1217
 
 
1218
 
 
1219
      /* Now, try to blank.
 
1220
       */
 
1221
 
960
1222
      if (! blank_screen (si))
961
1223
        {
962
1224
          /* We were unable to grab either the keyboard or mouse.
967
1229
             see any events, and the display would be wedged.
968
1230
 
969
1231
             So, just go around the loop again and wait for the
970
 
             next bout of idleness.
 
1232
             next bout of idleness.  (If the user remains idle, we
 
1233
             will next try to blank the screen again in no more than
 
1234
             60 seconds.)
971
1235
          */
 
1236
          Time retry = 60 * 1000;
 
1237
          if (p->timeout < retry)
 
1238
            retry = p->timeout;
972
1239
 
973
 
          fprintf (stderr,
 
1240
          if (p->debug_p)
 
1241
            {
 
1242
              fprintf (stderr,
 
1243
                  "%s: DEBUG MODE: unable to grab -- BLANKING ANYWAY.\n",
 
1244
                       blurb());
 
1245
            }
 
1246
          else
 
1247
            {
 
1248
              fprintf (stderr,
974
1249
                  "%s: unable to grab keyboard or mouse!  Blanking aborted.\n",
975
 
                   blurb());
976
 
          continue;
 
1250
                       blurb());
 
1251
 
 
1252
              schedule_wakeup_event (si, retry, p->debug_p);
 
1253
              continue;
 
1254
            }
977
1255
        }
978
1256
 
979
1257
      kill_screenhack (si);
995
1273
 
996
1274
 
997
1275
#ifndef NO_LOCKING
 
1276
      /* Maybe start locking the screen.
 
1277
       */
998
1278
      {
999
1279
        Time lock_timeout = p->lock_timeout;
1000
1280
 
1034
1314
      ok_to_unblank = True;
1035
1315
      do {
1036
1316
 
 
1317
        check_for_leaks ("blanked A");
1037
1318
        sleep_until_idle (si, False);           /* until not idle */
 
1319
        check_for_leaks ("blanked B");
 
1320
 
1038
1321
        maybe_reload_init_file (si);
1039
1322
 
1040
1323
#ifndef NO_LOCKING
 
1324
        /* Maybe unlock the screen.
 
1325
         */
1041
1326
        if (si->locked_p)
1042
1327
          {
1043
1328
            saver_screen_info *ssi = si->default_screen;
1108
1393
          si->lock_id = 0;
1109
1394
        }
1110
1395
 
1111
 
      if (p->verbose_p)
1112
 
        fprintf (stderr, "%s: awaiting idleness.\n", blurb());
 
1396
      /* Since we're unblanked now, break race conditions and make
 
1397
         sure we stay that way (see comment in timers.c.) */
 
1398
      if (! si->de_race_id)
 
1399
        de_race_timer ((XtPointer) si, 0);
1113
1400
    }
1114
1401
}
1115
1402
 
1116
1403
static void analyze_display (saver_info *si);
 
1404
static void fix_fds (void);
1117
1405
 
1118
1406
int
1119
1407
main (int argc, char **argv)
1127
1415
  memset(si, 0, sizeof(*si));
1128
1416
  global_si_kludge = si;        /* I hate C so much... */
1129
1417
 
 
1418
  fix_fds();
 
1419
 
1130
1420
# undef ya_rand_init
1131
1421
  ya_rand_init (0);
1132
1422
 
1140
1430
  print_banner (si);
1141
1431
 
1142
1432
  load_init_file (p);  /* must be before initialize_per_screen_info() */
 
1433
  blurb_timestamp_p = p->timestamp_p;  /* kludge */
1143
1434
  initialize_per_screen_info (si, shell); /* also sets si->fading_possible_p */
1144
1435
 
1145
 
  /* We can only issue this warnings now. */
 
1436
  /* We can only issue this warning now. */
1146
1437
  if (p->verbose_p && !si->fading_possible_p && (p->fade_p || p->unfade_p))
1147
1438
    fprintf (stderr,
1148
1439
             "%s: there are no PseudoColor or GrayScale visuals.\n"
1150
1441
             blurb(), blurb());
1151
1442
 
1152
1443
  for (i = 0; i < si->nscreens; i++)
1153
 
    if (ensure_no_screensaver_running (si->dpy, si->screens[i].screen))
1154
 
      exit (1);
 
1444
    {
 
1445
      saver_screen_info *ssi = &si->screens[i];
 
1446
      if (ssi->real_screen_p)
 
1447
        if (ensure_no_screensaver_running (si->dpy, si->screens[i].screen))
 
1448
          exit (1);
 
1449
    }
1155
1450
 
1156
1451
  lock_initialization (si, &argc, argv);
 
1452
  print_lock_failure_banner (si);
1157
1453
 
1158
1454
  if (p->xsync_p) XSynchronize (si->dpy, True);
1159
 
  blurb_timestamp_p = p->timestamp_p;  /* kludge */
1160
1455
 
1161
1456
  if (p->verbose_p) analyze_display (si);
1162
1457
  initialize_server_extensions (si);
1168
1463
  init_sigchld ();
1169
1464
 
1170
1465
  disable_builtin_screensaver (si, True);
1171
 
  sync_server_dpms_settings (si->dpy, p->dpms_enabled_p,
 
1466
  sync_server_dpms_settings (si->dpy,
 
1467
                             (p->dpms_enabled_p  &&
 
1468
                              p->mode != DONT_BLANK),
1172
1469
                             p->dpms_standby / 1000,
1173
1470
                             p->dpms_suspend / 1000,
1174
1471
                             p->dpms_off / 1000,
1175
1472
                             False);
1176
1473
 
1177
1474
  initialize_stderr (si);
 
1475
  handle_signals (si);
1178
1476
 
1179
1477
  make_splash_dialog (si);
1180
1478
 
1182
1480
  return 0;
1183
1481
}
1184
1482
 
 
1483
static void
 
1484
fix_fds (void)
 
1485
{
 
1486
  /* Bad Things Happen if stdin, stdout, and stderr have been closed
 
1487
     (as by the `sh incantation "xscreensaver >&- 2>&-").  When you do
 
1488
     that, the X connection gets allocated to one of these fds, and
 
1489
     then some random library writes to stderr, and random bits get
 
1490
     stuffed down the X pipe, causing "Xlib: sequence lost" errors.
 
1491
     So, we cause the first three file descriptors to be open to
 
1492
     /dev/null if they aren't open to something else already.  This
 
1493
     must be done before any other files are opened (or the closing
 
1494
     of that other file will again free up one of the "magic" first
 
1495
     three FDs.)
 
1496
 
 
1497
     We do this by opening /dev/null three times, and then closing
 
1498
     those fds, *unless* any of them got allocated as #0, #1, or #2,
 
1499
     in which case we leave them open.  Gag.
 
1500
 
 
1501
     Really, this crap is technically required of *every* X program,
 
1502
     if you want it to be robust in the face of "2>&-".
 
1503
   */
 
1504
  int fd0 = open ("/dev/null", O_RDWR);
 
1505
  int fd1 = open ("/dev/null", O_RDWR);
 
1506
  int fd2 = open ("/dev/null", O_RDWR);
 
1507
  if (fd0 > 2) close (fd0);
 
1508
  if (fd1 > 2) close (fd1);
 
1509
  if (fd2 > 2) close (fd2);
 
1510
}
 
1511
 
 
1512
 
1185
1513
 
1186
1514
/* Processing ClientMessage events.
1187
1515
 */
1221
1549
  else
1222
1550
    {
1223
1551
      char buf[100];
1224
 
      sprintf (buf, "<<undefined atom 0x%04X>>", (unsigned long) atom);
 
1552
      sprintf (buf, "<<undefined atom 0x%04X>>", (unsigned int) atom);
1225
1553
      return strdup (buf);
1226
1554
    }
1227
1555
}
1266
1594
  free (proto);
1267
1595
}
1268
1596
 
 
1597
 
 
1598
static void
 
1599
bogus_clientmessage_warning (saver_info *si, XEvent *event)
 
1600
{
 
1601
  char *str = XGetAtomName_safe (si->dpy, event->xclient.message_type);
 
1602
  Window w = event->xclient.window;
 
1603
  char wdesc[255];
 
1604
  int screen = 0;
 
1605
 
 
1606
  *wdesc = 0;
 
1607
  for (screen = 0; screen < si->nscreens; screen++)
 
1608
    if (w == si->screens[screen].screensaver_window)
 
1609
      {
 
1610
        strcpy (wdesc, "xscreensaver");
 
1611
        break;
 
1612
      }
 
1613
    else if (w == RootWindow (si->dpy, screen))
 
1614
      {
 
1615
        strcpy (wdesc, "root");
 
1616
        break;
 
1617
      }
 
1618
 
 
1619
  if (!*wdesc)
 
1620
    {
 
1621
      XErrorHandler old_handler;
 
1622
      XClassHint hint;
 
1623
      XWindowAttributes xgwa;
 
1624
      memset (&hint, 0, sizeof(hint));
 
1625
      memset (&xgwa, 0, sizeof(xgwa));
 
1626
 
 
1627
      XSync (si->dpy, False);
 
1628
      old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
 
1629
      XGetClassHint (si->dpy, w, &hint);
 
1630
      XGetWindowAttributes (si->dpy, w, &xgwa);
 
1631
      XSync (si->dpy, False);
 
1632
      XSetErrorHandler (old_handler);
 
1633
      XSync (si->dpy, False);
 
1634
 
 
1635
      screen = (xgwa.screen ? screen_number (xgwa.screen) : -1);
 
1636
 
 
1637
      sprintf (wdesc, "%.20s / %.20s",
 
1638
               (hint.res_name  ? hint.res_name  : "(null)"),
 
1639
               (hint.res_class ? hint.res_class : "(null)"));
 
1640
      if (hint.res_name)  XFree (hint.res_name);
 
1641
      if (hint.res_class) XFree (hint.res_class);
 
1642
    }
 
1643
 
 
1644
  fprintf (stderr, "%s: %d: unrecognised ClientMessage \"%s\" received\n",
 
1645
           blurb(), screen, (str ? str : "(null)"));
 
1646
  fprintf (stderr, "%s: %d: for window 0x%lx (%s)\n",
 
1647
           blurb(), screen, (unsigned long) w, wdesc);
 
1648
  if (str) XFree (str);
 
1649
}
 
1650
 
1269
1651
Bool
1270
1652
handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
1271
1653
{
1276
1658
  /* Preferences might affect our handling of client messages. */
1277
1659
  maybe_reload_init_file (si);
1278
1660
 
1279
 
  if (event->xclient.message_type != XA_SCREENSAVER)
1280
 
    {
1281
 
      char *str;
1282
 
      str = XGetAtomName_safe (si->dpy, event->xclient.message_type);
1283
 
        /*
1284
 
      fprintf (stderr, "%s: unrecognised ClientMessage type %s received\n",
1285
 
               blurb(), (str ? str : "(null)"));
1286
 
        */
1287
 
      if (str) XFree (str);
1288
 
      return False;
1289
 
    }
1290
 
  if (event->xclient.format != 32)
1291
 
    {
1292
 
      fprintf (stderr, "%s: ClientMessage of format %d received, not 32\n",
1293
 
               blurb(), event->xclient.format);
 
1661
  if (event->xclient.message_type != XA_SCREENSAVER ||
 
1662
      event->xclient.format != 32)
 
1663
    {
 
1664
      bogus_clientmessage_warning (si, event);
1294
1665
      return False;
1295
1666
    }
1296
1667
 
1299
1670
    {
1300
1671
      if (until_idle_p)
1301
1672
        {
 
1673
          if (p->mode == DONT_BLANK)
 
1674
            {
 
1675
              clientmessage_response(si, window, True,
 
1676
                         "ACTIVATE ClientMessage received in DONT_BLANK mode.",
 
1677
                                     "screen blanking is currently disabled.");
 
1678
              return False;
 
1679
            }
 
1680
 
1302
1681
          clientmessage_response(si, window, False,
1303
1682
                                 "ACTIVATE ClientMessage received.",
1304
1683
                                 "activating.");
1403
1782
      char buf2 [255];
1404
1783
      long which = event->xclient.data.l[1];
1405
1784
 
 
1785
      if (p->mode == DONT_BLANK)
 
1786
        {
 
1787
          clientmessage_response(si, window, True,
 
1788
                           "SELECT ClientMessage received in DONT_BLANK mode.",
 
1789
                                 "screen blanking is currently disabled.");
 
1790
          return False;
 
1791
        }
 
1792
 
1406
1793
      sprintf (buf, "SELECT %ld ClientMessage received.", which);
1407
1794
      sprintf (buf2, "activating (%ld).", which);
1408
1795
      clientmessage_response (si, window, False, buf, buf2);
1463
1850
              XSync (si->dpy, False);
1464
1851
            }
1465
1852
 
1466
 
          fflush (stdout);
1467
 
          fflush (stderr);
1468
 
          if (real_stdout) fflush (real_stdout);
1469
 
          if (real_stderr) fflush (real_stderr);
1470
 
          /* make sure error message shows up before exit. */
1471
 
          if (real_stderr && stderr != real_stderr)
1472
 
            dup2 (fileno(real_stderr), fileno(stderr));
1473
 
 
1474
 
          restart_process (si);
1475
 
          exit (1);     /* shouldn't get here; but if restarting didn't work,
1476
 
                           make this command be the same as EXIT. */
 
1853
          restart_process (si);  /* does not return */
 
1854
          abort();
1477
1855
        }
1478
1856
      else
1479
1857
        clientmessage_response (si, window, True,
1575
1953
    }
1576
1954
  else if (type == XA_THROTTLE)
1577
1955
    {
 
1956
      /* The THROTTLE command is deprecated -- it predates the XDPMS
 
1957
         extension.  Instead of using -throttle, users should instead
 
1958
         just power off the monitor (e.g., "xset dpms force off".)
 
1959
         In a few minutes, xscreensaver will notice that the monitor
 
1960
         is off, and cease running hacks.
 
1961
       */
1578
1962
      if (si->throttled_p)
1579
1963
        clientmessage_response (si, window, True,
1580
1964
                                "THROTTLE ClientMessage received, but "
1663
2047
    const char *name; const char *desc; Bool useful_p;
1664
2048
  } exts[] = {
1665
2049
 
1666
 
   { "SCREEN_SAVER",                            "SGI Screen-Saver",
 
2050
   { "SCREEN_SAVER", /* underscore */           "SGI Screen-Saver",
1667
2051
#     ifdef HAVE_SGI_SAVER_EXTENSION
1668
2052
        True
1669
2053
#     else
1670
2054
        False
1671
2055
#     endif
1672
 
   }, { "SCREEN-SAVER",                         "SGI Screen-Saver",
 
2056
   }, { "SCREEN-SAVER", /* dash */              "SGI Screen-Saver",
1673
2057
#     ifdef HAVE_SGI_SAVER_EXTENSION
1674
2058
        True
1675
2059
#     else
1730
2114
        False
1731
2115
#     endif
1732
2116
   }, { "XINERAMA",                             "Xinerama",
 
2117
#     ifdef HAVE_XINERAMA
 
2118
        True
 
2119
#     else
 
2120
        False
 
2121
#     endif
 
2122
   }, { "RANDR",                                "Resize-and-Rotate",
 
2123
#     ifdef HAVE_RANDR
 
2124
        True
 
2125
#     else
 
2126
        False
 
2127
#     endif
 
2128
   }, { "Apple-DRI",                            "Apple-DRI (XDarwin)",
1733
2129
        True
1734
2130
   },
1735
2131
  };
1736
2132
 
1737
 
  fprintf (stderr, "%s: running on display \"%s\"\n", blurb(),
1738
 
           DisplayString(si->dpy));
1739
 
  fprintf (stderr, "%s: vendor is %s, %d\n", blurb(),
 
2133
  fprintf (stderr, "%s: running on display \"%s\" (%d %sscreen%s).\n",
 
2134
           blurb(),
 
2135
           DisplayString(si->dpy),
 
2136
           si->nscreens,
 
2137
           (si->xinerama_p ? "Xinerama " : ""),
 
2138
           (si->nscreens == 1 ? "" : "s"));
 
2139
  fprintf (stderr, "%s: vendor is %s, %d.\n", blurb(),
1740
2140
           ServerVendor(si->dpy), VendorRelease(si->dpy));
1741
2141
 
1742
2142
  fprintf (stderr, "%s: useful extensions:\n", blurb());
1743
2143
  for (i = 0; i < countof(exts); i++)
1744
2144
    {
1745
2145
      int op = 0, event = 0, error = 0;
1746
 
      if (XQueryExtension (si->dpy, exts[i].name, &op, &event, &error))
1747
 
        fprintf (stderr, "%s:  %s%s\n", blurb(),
1748
 
                 exts[i].desc,
1749
 
                 (exts[i].useful_p ? "" :
1750
 
                  "       \t<== unsupported at compile-time!"));
 
2146
      char buf [255];
 
2147
      int j;
 
2148
      if (!XQueryExtension (si->dpy, exts[i].name, &op, &event, &error))
 
2149
        continue;
 
2150
      sprintf (buf, "%s:   ", blurb());
 
2151
      j = strlen (buf);
 
2152
      strcat (buf, exts[i].desc);
 
2153
      if (!exts[i].useful_p)
 
2154
        {
 
2155
          int k = j + 18;
 
2156
          while (strlen (buf) < k) strcat (buf, " ");
 
2157
          strcat (buf, "<-- not supported at compile time!");
 
2158
        }
 
2159
      fprintf (stderr, "%s\n", buf);
1751
2160
    }
1752
2161
 
1753
2162
  for (i = 0; i < si->nscreens; i++)
1754
2163
    {
 
2164
      saver_screen_info *ssi = &si->screens[i];
1755
2165
      unsigned long colormapped_depths = 0;
1756
2166
      unsigned long non_mapped_depths = 0;
1757
2167
      XVisualInfo vi_in, *vi_out;
1758
2168
      int out_count;
1759
 
      vi_in.screen = i;
 
2169
 
 
2170
      if (!ssi->real_screen_p) continue;
 
2171
 
 
2172
      vi_in.screen = ssi->real_screen_number;
1760
2173
      vi_out = XGetVisualInfo (si->dpy, VisualScreenMask, &vi_in, &out_count);
1761
2174
      if (!vi_out) continue;
1762
2175
      for (j = 0; j < out_count; j++)
1768
2181
 
1769
2182
      if (colormapped_depths)
1770
2183
        {
1771
 
          fprintf (stderr, "%s: screen %d colormapped depths:", blurb(), i);
 
2184
          fprintf (stderr, "%s: screen %d colormapped depths:", blurb(),
 
2185
                   ssi->real_screen_number);
1772
2186
          for (j = 0; j < 32; j++)
1773
2187
            if (colormapped_depths & (1 << j))
1774
2188
              fprintf (stderr, " %d", j);
1775
 
          fprintf (stderr, "\n");
 
2189
          fprintf (stderr, ".\n");
1776
2190
        }
1777
2191
      if (non_mapped_depths)
1778
2192
        {
1779
 
          fprintf (stderr, "%s: screen %d non-mapped depths:", blurb(), i);
 
2193
          fprintf (stderr, "%s: screen %d non-colormapped depths:",
 
2194
                   blurb(), ssi->real_screen_number);
1780
2195
          for (j = 0; j < 32; j++)
1781
2196
            if (non_mapped_depths & (1 << j))
1782
2197
              fprintf (stderr, " %d", j);
1783
 
          fprintf (stderr, "\n");
 
2198
          fprintf (stderr, ".\n");
1784
2199
        }
1785
2200
    }
 
2201
 
 
2202
  if (si->xinerama_p)
 
2203
    {
 
2204
      fprintf (stderr, "%s: Xinerama layout:\n", blurb());
 
2205
      for (i = 0; i < si->nscreens; i++)
 
2206
        {
 
2207
          saver_screen_info *ssi = &si->screens[i];
 
2208
          fprintf (stderr, "%s:   %c %d/%d: %dx%d+%d+%d\n",
 
2209
                   blurb(),
 
2210
                   (ssi->real_screen_p ? '+' : ' '),
 
2211
                   ssi->number, ssi->real_screen_number,
 
2212
                   ssi->width, ssi->height, ssi->x, ssi->y);
 
2213
        }
 
2214
    }
1786
2215
}
1787
2216
 
1788
2217
Bool
1831
2260
    }
1832
2261
  return !not_on_console;
1833
2262
}
 
2263
 
 
2264
 
 
2265
/* Do a little bit of heap introspection...
 
2266
 */
 
2267
void
 
2268
check_for_leaks (const char *where)
 
2269
{
 
2270
#if defined(HAVE_SBRK) && defined(LEAK_PARANOIA)
 
2271
  static unsigned long last_brk = 0;
 
2272
  int b = (unsigned long) sbrk(0);
 
2273
  if (last_brk && last_brk < b)
 
2274
    fprintf (stderr, "%s: %s: brk grew by %luK.\n",
 
2275
             blurb(), where,
 
2276
             (((b - last_brk) + 1023) / 1024));
 
2277
  last_brk = b;
 
2278
#endif /* HAVE_SBRK */
 
2279
}