164
166
# include "xmu.h"
165
167
#endif /* !HAVE_XMU */
169
#ifdef HAVE_MIT_SAVER_EXTENSION
170
#include <X11/extensions/scrnsaver.h>
171
#endif /* HAVE_MIT_SAVER_EXTENSION */
167
173
#ifdef HAVE_XIDLE_EXTENSION
168
174
# include <X11/extensions/xidle.h>
169
175
#endif /* HAVE_XIDLE_EXTENSION */
177
#ifdef HAVE_SGI_VC_EXTENSION
178
# include <X11/extensions/XSGIvc.h>
179
#endif /* HAVE_SGI_VC_EXTENSION */
181
#ifdef HAVE_READ_DISPLAY_EXTENSION
182
# include <X11/extensions/readdisplay.h>
183
#endif /* HAVE_READ_DISPLAY_EXTENSION */
185
#ifdef HAVE_XSHM_EXTENSION
186
# include <X11/extensions/XShm.h>
187
#endif /* HAVE_XSHM_EXTENSION */
189
#ifdef HAVE_DPMS_EXTENSION
190
# include <X11/extensions/dpms.h>
191
#endif /* HAVE_DPMS_EXTENSION */
194
#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
195
# include <X11/extensions/Xdbe.h>
196
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
198
#ifdef HAVE_XF86VMODE
199
# include <X11/extensions/xf86vmode.h>
200
#endif /* HAVE_XF86VMODE */
202
#ifdef HAVE_XF86MISCSETGRABKEYSSTATE
203
# include <X11/extensions/xf86misc.h>
204
#endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
171
206
#ifdef HAVE_XINERAMA
172
207
# include <X11/extensions/Xinerama.h>
173
208
#endif /* HAVE_XINERAMA */
211
# include <X11/extensions/Xrandr.h>
212
#endif /* HAVE_RANDR */
175
215
#include "xscreensaver.h"
176
216
#include "version.h"
177
217
#include "yarandom.h"
337
fprintf (real_stderr,
338
"#######################################"
339
"#######################################\n\n");
340
fprintf (real_stderr,
379
__extension__ /* don't warn about "string length is greater than the
380
length ISO C89 compilers are required to support". */
382
fprintf (real_stderr,
383
"#######################################################################\n"
341
385
" If at all possible, please re-run xscreensaver with the command\n"
342
" line arguments `-sync -verbose -no-capture', and reproduce this\n"
386
" line arguments `-sync -verbose -log log.txt', and reproduce this\n"
343
387
" bug. That will cause xscreensaver to dump a `core' file to the\n"
344
388
" current directory. Please include the stack trace from that core\n"
345
" file in your bug report. *DO NOT* mail the core file itself!\n"
346
" That won't work.\n");
347
fprintf (real_stderr,
389
" file in your bug report. *DO NOT* mail the core file itself! That\n"
390
" won't work. A \"log.txt\" file will also be written. Please *do*\n"
391
" include the complete \"log.txt\" file with your bug report.\n"
349
393
" http://www.jwz.org/xscreensaver/bugs.html explains how to create\n"
350
394
" the most useful bug reports, and how to examine core files.\n"
352
396
" The more information you can provide, the better. But please\n"
353
397
" report this bug, regardless!\n"
399
"#######################################################################\n"
355
fprintf (real_stderr,
356
"#######################################"
357
"#######################################\n\n");
359
403
saver_exit (si, -1, 0);
761
screens_overlap_p (XineramaScreenInfo *a, XineramaScreenInfo *b)
763
/* Two rectangles overlap if the max of the tops is less than the
764
min of the bottoms and the max of the lefts is less than the min
769
# define MAX(A,B) ((A)>(B)?(A):(B))
770
# define MIN(A,B) ((A)<(B)?(A):(B))
772
int maxleft = MAX(a->x_org, b->x_org);
773
int maxtop = MAX(a->y_org, b->y_org);
774
int minright = MIN(a->x_org + a->width - 1, b->x_org + b->width);
775
int minbot = MIN(a->y_org + a->height - 1, b->y_org + b->height);
776
return (maxtop < minbot && maxleft < minright);
780
/* Go through the list of Xinerama screen descriptions, and mark the
781
ones that appear to be insane, so that we don't use them.
784
check_xinerama_sanity (int count, Bool verbose_p, XineramaScreenInfo *xsi)
786
static Bool printed_p = False;
791
# define X1 xsi[i].x_org
792
# define X2 xsi[j].x_org
793
# define Y1 xsi[i].y_org
794
# define Y2 xsi[j].y_org
795
# define W1 xsi[i].width
796
# define W2 xsi[j].width
797
# define H1 xsi[i].height
798
# define H2 xsi[j].height
800
# define WHINE() do { \
803
fprintf (stderr, "%s: compensating for Xinerama braindamage:\n", \
807
fprintf (stderr, "%s: %d: %s\n", blurb(), xsi[i].screen_number,err); \
809
xsi[i].screen_number = -1; \
812
/* If a screen is enclosed by any other screen, that's insane.
814
for (i = 0; i < count; i++)
815
for (j = 0; j < count; j++)
817
xsi[i].screen_number >= 0 &&
818
xsi[j].screen_number >= 0 &&
819
X1 >= X2 && Y1 >= Y2 && (X1+W1) <= (X2+W2) && (X1+H1) <= (X2+H2))
821
sprintf (err, "%dx%d+%d+%d enclosed by %dx%d+%d+%d",
828
/* After checking for enclosure, check for other lossage against earlier
829
screens. We do enclosure first so that we make sure to pick the
832
for (i = 0; i < count; i++)
833
for (j = 0; j < i; j++)
835
if (xsi[i].screen_number < 0) continue; /* already marked */
838
if (X1 == X2 && Y1 == Y2 && W1 == W2 && H1 == H2)
839
sprintf (err, "%dx%d+%d+%d duplicated", W1, H1, X1, Y1);
841
else if (screens_overlap_p (&xsi[i], &xsi[j]))
842
sprintf (err, "%dx%d+%d+%d overlaps %dx%d+%d+%d",
859
#endif /* HAVE_XINERAMA */
795
/* called from screens.c so that all the Xt crud is here. */
797
initialize_screen_root_widget (saver_screen_info *ssi)
799
saver_info *si = ssi->global;
800
if (ssi->toplevel_shell)
801
XtDestroyWidget (ssi->toplevel_shell);
802
ssi->toplevel_shell =
803
XtVaAppCreateShell (progname, progclass,
804
applicationShellWidgetClass,
806
XtNscreen, ssi->screen,
807
XtNvisual, ssi->current_visual,
808
XtNdepth, visual_depth (ssi->screen,
809
ssi->current_visual),
863
814
/* Examine all of the display's screens, and populate the `saver_screen_info'
867
818
initialize_per_screen_info (saver_info *si, Widget toplevel_shell)
869
Bool found_any_writable_cells = False;
872
# ifdef HAVE_XINERAMA
875
si->xinerama_p = (XineramaQueryExtension (si->dpy, &event, &error) &&
876
XineramaIsActive (si->dpy));
879
if (si->xinerama_p && ScreenCount (si->dpy) != 1)
881
si->xinerama_p = False;
882
if (si->prefs.verbose_p)
884
"%s: Xinerama AND %d screens? Disabling Xinerama support!\n",
885
blurb(), ScreenCount(si->dpy));
891
XineramaScreenInfo *xsi = XineramaQueryScreens (si->dpy, &nscreens);
893
si->xinerama_p = False;
897
si->screens = (saver_screen_info *)
898
calloc(sizeof(saver_screen_info), nscreens);
899
check_xinerama_sanity (nscreens, si->prefs.verbose_p, xsi);
900
for (i = 0; i < nscreens; i++)
902
if (xsi[i].screen_number < 0) /* deemed insane */
904
si->screens[j].x = xsi[i].x_org;
905
si->screens[j].y = xsi[i].y_org;
906
si->screens[j].width = xsi[i].width;
907
si->screens[j].height = xsi[i].height;
913
si->default_screen = &si->screens[0];
914
si->default_screen->real_screen_p = True;
916
# endif /* !HAVE_XINERAMA */
920
si->nscreens = ScreenCount(si->dpy);
921
si->screens = (saver_screen_info *)
922
calloc(sizeof(saver_screen_info), si->nscreens);
923
si->default_screen = &si->screens[DefaultScreen(si->dpy)];
925
for (i = 0; i < si->nscreens; i++)
927
saver_screen_info *ssi = &si->screens[i];
928
ssi->width = DisplayWidth (si->dpy, i);
929
ssi->height = DisplayHeight (si->dpy, i);
930
ssi->real_screen_p = True;
931
ssi->real_screen_number = i;
937
/* In "quad mode", we use the Xinerama code to pretend that there are 4
938
screens for every physical screen, and run four times as many hacks...
940
if (si->prefs.quad_p)
942
int ns2 = si->nscreens * 4;
943
saver_screen_info *ssi2 = (saver_screen_info *)
944
calloc(sizeof(saver_screen_info), ns2);
946
for (i = 0; i < si->nscreens; i++)
948
saver_screen_info *old = &si->screens[i];
950
if (si->prefs.debug_p) old->width = old->width / 2;
957
ssi2[i*4 ].width /= 2;
958
ssi2[i*4 ].height /= 2;
960
ssi2[i*4+1].x += ssi2[i*4 ].width;
961
ssi2[i*4+1].width -= ssi2[i*4 ].width;
962
ssi2[i*4+1].height /= 2;
964
ssi2[i*4+2].y += ssi2[i*4 ].height;
965
ssi2[i*4+2].width /= 2;
966
ssi2[i*4+2].height -= ssi2[i*4 ].height;
968
ssi2[i*4+3].x += ssi2[i*4+2].width;
969
ssi2[i*4+3].y += ssi2[i*4+2].height;
970
ssi2[i*4+3].width -= ssi2[i*4+2].width;
971
ssi2[i*4+3].height -= ssi2[i*4+2].height;
973
ssi2[i*4+1].real_screen_p = False;
974
ssi2[i*4+2].real_screen_p = False;
975
ssi2[i*4+3].real_screen_p = False;
981
si->default_screen = &si->screens[DefaultScreen(si->dpy) * 4];
982
si->xinerama_p = True;
984
# endif /* QUAD_MODE */
986
/* finish initializing the screens.
822
update_screen_layout (si);
824
/* Check to see whether fading is ever possible -- if any of the
825
screens on the display has a PseudoColor visual, then fading can
826
work (on at least some screens.) If no screen has a PseudoColor
827
visual, then don't bother ever trying to fade, because it will
828
just cause a delay without causing any visible effect.
988
830
for (i = 0; i < si->nscreens; i++)
990
832
saver_screen_info *ssi = &si->screens[i];
994
ssi->screen = ScreenOfDisplay (si->dpy, ssi->real_screen_number);
995
ssi->poll_mouse_last_root_x = -1;
996
ssi->poll_mouse_last_root_y = -1;
833
if (has_writable_cells (ssi->screen, ssi->current_visual) ||
834
get_visual (ssi->screen, "PseudoColor", True, False) ||
835
get_visual (ssi->screen, "GrayScale", True, False))
1000
ssi->width = WidthOfScreen (ssi->screen);
1001
ssi->height = HeightOfScreen (ssi->screen);
837
si->fading_possible_p = True;
1004
/* Note: we can't use the resource ".visual" because Xt is SO FUCKED. */
1005
ssi->default_visual =
1006
get_visual_resource (ssi->screen, "visualID", "VisualID", False);
1008
ssi->current_visual = ssi->default_visual;
1009
ssi->current_depth = visual_depth (ssi->screen, ssi->current_visual);
1011
/* Execute a subprocess to find the GL visual. */
1012
ssi->best_gl_visual = get_best_gl_visual (ssi);
1014
if (ssi == si->default_screen)
1015
/* Since this is the default screen, use the one already created. */
1016
ssi->toplevel_shell = toplevel_shell;
1018
/* Otherwise, each screen must have its own unmapped root widget. */
1019
ssi->toplevel_shell =
1020
XtVaAppCreateShell (progname, progclass, applicationShellWidgetClass,
1022
XtNscreen, ssi->screen,
1023
XtNvisual, ssi->current_visual,
1024
XtNdepth, visual_depth (ssi->screen,
1025
ssi->current_visual),
1028
if (! found_any_writable_cells)
1030
/* Check to see whether fading is ever possible -- if any of the
1031
screens on the display has a PseudoColor visual, then fading can
1032
work (on at least some screens.) If no screen has a PseudoColor
1033
visual, then don't bother ever trying to fade, because it will
1034
just cause a delay without causing any visible effect.
1036
if (has_writable_cells (ssi->screen, ssi->current_visual) ||
1037
get_visual (ssi->screen, "PseudoColor", True, False) ||
1038
get_visual (ssi->screen, "GrayScale", True, False))
1039
found_any_writable_cells = True;
1043
si->fading_possible_p = found_any_writable_cells;
1045
842
#ifdef HAVE_XF86VMODE_GAMMA
1046
843
si->fading_possible_p = True; /* if we can gamma fade, go for it */
1068
865
si->using_proc_interrupts = p->use_proc_interrupts;
1070
867
#ifdef HAVE_XIDLE_EXTENSION
1071
server_has_xidle_extension_p = query_xidle_extension (si);
870
server_has_xidle_extension_p = XidleQueryExtension (si->dpy, &ev, &er);
1073
873
#ifdef HAVE_SGI_SAVER_EXTENSION
1074
server_has_sgi_saver_extension_p = query_sgi_saver_extension (si);
874
server_has_sgi_saver_extension_p =
875
XScreenSaverQueryExtension (si->dpy,
876
&si->sgi_saver_ext_event_number,
877
&si->sgi_saver_ext_error_number);
1076
879
#ifdef HAVE_MIT_SAVER_EXTENSION
1077
server_has_mit_saver_extension_p = query_mit_saver_extension (si);
880
server_has_mit_saver_extension_p =
881
XScreenSaverQueryExtension (si->dpy,
882
&si->mit_saver_ext_event_number,
883
&si->mit_saver_ext_error_number);
1079
885
#ifdef HAVE_PROC_INTERRUPTS
1080
886
system_has_proc_interrupts_p = query_proc_interrupts_available (si, &piwhy);
1118
/* These are incompatible (or at least, our support for them is...) */
1119
if (si->xinerama_p && si->using_mit_saver_extension)
925
if (XRRQueryExtension (si->dpy,
926
&si->randr_event_number, &si->randr_error_number))
1121
si->using_mit_saver_extension = False;
928
int nscreens = ScreenCount (si->dpy); /* number of *real* screens */
1122
931
if (p->verbose_p)
1123
fprintf (stderr, "%s: Xinerama in use: disabling MIT-SCREEN-SAVER.\n",
932
fprintf (stderr, "%s: selecting RANDR events\n", blurb());
933
for (i = 0; i < nscreens; i++)
934
# ifdef RRScreenChangeNotifyMask /* randr.h 1.5, 2002/09/29 */
935
XRRSelectInput (si->dpy, RootWindow (si->dpy, i),
936
RRScreenChangeNotifyMask);
937
# else /* !RRScreenChangeNotifyMask */ /* Xrandr.h 1.4, 2001/06/07 */
938
XRRScreenChangeSelectInput (si->dpy, RootWindow (si->dpy, i), True);
939
# endif /* !RRScreenChangeNotifyMask */
1128
query_randr_extension (si);
941
# endif /* HAVE_RANDR */
1131
943
if (!system_has_proc_interrupts_p)
2175
2023
static struct {
2176
const char *name; const char *desc; Bool useful_p;
2024
const char *name; const char *desc;
2026
Status (*version_fn) (Display *, int *majP, int *minP);
2179
2029
{ "SCREEN_SAVER", /* underscore */ "SGI Screen-Saver",
2180
2030
# ifdef HAVE_SGI_SAVER_EXTENSION
2185
2035
}, { "SCREEN-SAVER", /* dash */ "SGI Screen-Saver",
2186
2036
# ifdef HAVE_SGI_SAVER_EXTENSION
2191
2041
}, { "MIT-SCREEN-SAVER", "MIT Screen-Saver",
2192
2042
# ifdef HAVE_MIT_SAVER_EXTENSION
2043
True, XScreenSaverQueryVersion
2197
2047
}, { "XIDLE", "XIdle",
2198
2048
# ifdef HAVE_XIDLE_EXTENSION
2203
2053
}, { "SGI-VIDEO-CONTROL", "SGI Video-Control",
2204
2054
# ifdef HAVE_SGI_VC_EXTENSION
2055
True, XSGIvcQueryVersion
2209
2059
}, { "READDISPLAY", "SGI Read-Display",
2210
2060
# ifdef HAVE_READ_DISPLAY_EXTENSION
2061
True, XReadDisplayQueryVersion
2215
2065
}, { "MIT-SHM", "Shared Memory",
2216
2066
# ifdef HAVE_XSHM_EXTENSION
2067
True, (Status (*) (Display*,int*,int*)) XShmQueryVersion /* 4 args */
2221
2071
}, { "DOUBLE-BUFFER", "Double-Buffering",
2222
2072
# ifdef HAVE_DOUBLE_BUFFER_EXTENSION
2073
True, XdbeQueryExtension
2227
2077
}, { "DPMS", "Power Management",
2228
2078
# ifdef HAVE_DPMS_EXTENSION
2079
True, DPMSGetVersion
2233
2083
}, { "GLX", "GLX",
2234
2084
# ifdef HAVE_GL
2239
2089
}, { "XFree86-VidModeExtension", "XF86 Video-Mode",
2240
2090
# ifdef HAVE_XF86VMODE
2091
True, XF86VidModeQueryVersion
2095
}, { "XC-VidModeExtension", "XC Video-Mode",
2096
# ifdef HAVE_XF86VMODE
2097
True, XF86VidModeQueryVersion
2101
}, { "XFree86-MISC", "XF86 Misc",
2102
# ifdef HAVE_XF86MISCSETGRABKEYSSTATE
2103
True, XF86MiscQueryVersion
2107
}, { "XC-MISC", "XC Misc",
2108
# ifdef HAVE_XF86MISCSETGRABKEYSSTATE
2109
True, XF86MiscQueryVersion
2245
2113
}, { "XINERAMA", "Xinerama",
2246
2114
# ifdef HAVE_XINERAMA
2115
True, XineramaQueryVersion
2251
2119
}, { "RANDR", "Resize-and-Rotate",
2252
2120
# ifdef HAVE_RANDR
2121
True, XRRQueryVersion
2257
2127
}, { "Apple-DRI", "Apple-DRI (XDarwin)",
2262
fprintf (stderr, "%s: running on display \"%s\" (%d %sscreen%s).\n",
2264
DisplayString(si->dpy),
2266
(si->xinerama_p ? "Xinerama " : ""),
2267
(si->nscreens == 1 ? "" : "s"));
2132
fprintf (stderr, "%s: running on display \"%s\"\n", blurb(),
2133
DisplayString(si->dpy));
2268
2134
fprintf (stderr, "%s: vendor is %s, %d.\n", blurb(),
2269
2135
ServerVendor(si->dpy), VendorRelease(si->dpy));
2274
2140
int op = 0, event = 0, error = 0;
2275
2141
char buf [255];
2142
int maj = 0, min = 0;
2143
int dummy1, dummy2, dummy3;
2146
/* Most of the extension version functions take 3 args,
2147
writing results into args 2 and 3, but some take more.
2148
We only ever care about the first two results, but we
2149
pass in three extra pointers just in case.
2151
Status (*version_fn_2) (Display*,int*,int*,int*,int*,int*) =
2152
(Status (*) (Display*,int*,int*,int*,int*,int*)) exts[i].version_fn;
2277
2154
if (!XQueryExtension (si->dpy, exts[i].name, &op, &event, &error))
2279
2156
sprintf (buf, "%s: ", blurb());
2280
2157
j = strlen (buf);
2281
2158
strcat (buf, exts[i].desc);
2162
else if (version_fn_2 (si->dpy, &maj, &min, &dummy1, &dummy2, &dummy3))
2163
sprintf (buf+strlen(buf), " (%d.%d)", maj, min);
2165
strcat (buf, " (unavailable)");
2282
2167
if (!exts[i].useful_p)
2283
2168
strcat (buf, " (disabled at compile time)");
2284
2169
fprintf (stderr, "%s\n", buf);