63887efa670744f774768d9204bd7af903c77a9e
[xscreensaver] / driver / test-randr.c
1 /* test-randr.c --- playing with the Resize And Rotate extension.
2  * xscreensaver, Copyright (c) 2004 Jamie Zawinski <jwz@jwz.org>
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 <stdlib.h>
18 #ifdef HAVE_UNISTD_H
19 # include <unistd.h>
20 #endif
21
22 #include <stdio.h>
23 #include <time.h>
24 #include <sys/time.h>
25
26 #include <X11/Xlib.h>
27 #include <X11/Xatom.h>
28 #include <X11/Intrinsic.h>
29
30 #include <X11/Xproto.h>
31 #include <X11/extensions/Xrandr.h>
32
33 char *progname = 0;
34 char *progclass = "XScreenSaver";
35
36 static const char *
37 blurb (void)
38 {
39   static char buf[255];
40   time_t now = time ((time_t *) 0);
41   char *ct = (char *) ctime (&now);
42   int n = strlen(progname);
43   if (n > 100) n = 99;
44   strncpy(buf, progname, n);
45   buf[n++] = ':';
46   buf[n++] = ' ';
47   strncpy(buf+n, ct+11, 8);
48   strcpy(buf+n+9, ": ");
49   return buf;
50 }
51
52
53 int
54 main (int argc, char **argv)
55 {
56   int event_number, error_number;
57   int major, minor;
58   int nscreens = 0;
59   int i;
60
61   XtAppContext app;
62   Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0,
63                                            &argc, argv, 0, 0, 0);
64   Display *dpy = XtDisplay (toplevel_shell);
65   XtGetApplicationNameAndClass (dpy, &progname, &progclass);
66
67   nscreens = ScreenCount(dpy);
68
69   if (!XRRQueryExtension(dpy, &event_number, &error_number))
70     {
71       fprintf(stderr, "%s: XRRQueryExtension(dpy, ...) ==> False\n",
72               blurb());
73       fprintf(stderr, "%s: server does not support the RANDR extension.\n",
74               blurb());
75       major = -1;
76     }
77   else
78     {
79       fprintf(stderr, "%s: XRRQueryExtension(dpy, ...) ==> %d, %d\n",
80               blurb(), event_number, error_number);
81
82       if (!XRRQueryVersion(dpy, &major, &minor))
83         {
84           fprintf(stderr, "%s: XRRQueryVersion(dpy, ...) ==> False\n",
85                   blurb());
86           fprintf(stderr, "%s: server didn't report RANDR version numbers?\n",
87                   blurb());
88         }
89       else
90         fprintf(stderr, "%s: XRRQueryVersion(dpy, ...) ==> %d, %d\n", blurb(),
91                 major, minor);
92     }
93
94   for (i = 0; i < nscreens; i++)
95     {
96       XRRScreenConfiguration *rrc =
97         (major >= 0 ? XRRGetScreenInfo (dpy, RootWindow (dpy, i)) : 0);
98
99       if (rrc)
100         {
101           SizeID current_size = -1;
102           Rotation current_rotation = ~0;
103
104           fprintf (stderr, "\n%s: Screen %d\n", blurb(), i);
105
106           current_size =
107             XRRConfigCurrentConfiguration (rrc, &current_rotation);
108
109           /* Times */
110           {
111             Time server_time, config_time;
112             server_time = XRRConfigTimes (rrc, &config_time);
113             if (config_time == 0 || server_time == 0)
114               fprintf (stderr, "%s:   config has never been changed\n",
115                        blurb());
116             else
117               fprintf (stderr, "%s:   config changed %lu seconds ago\n",
118                        blurb(), (unsigned long) (server_time - config_time));
119           }
120
121           /* Rotations */
122           {
123             Rotation available, current;
124             available = XRRConfigRotations (rrc, &current);
125
126             fprintf (stderr, "%s:   Available Rotations:\t", blurb());
127             if (available & RR_Rotate_0)   fprintf (stderr,   " 0");
128             if (available & RR_Rotate_90)  fprintf (stderr,  " 90");
129             if (available & RR_Rotate_180) fprintf (stderr, " 180");
130             if (available & RR_Rotate_270) fprintf (stderr, " 270");
131             if (! (available & (RR_Rotate_0   | RR_Rotate_90 |
132                                 RR_Rotate_180 | RR_Rotate_270)))
133               fprintf (stderr, " none");
134             fprintf (stderr, "\n");
135
136             if (current_rotation != current)
137               fprintf (stderr,
138                        "%s:   WARNING: rotation inconsistency: 0x%X vs 0x%X\n",
139                        blurb(), current_rotation, current);
140
141             fprintf (stderr, "%s:   Current Rotation:\t", blurb());
142             if (current & RR_Rotate_0)   fprintf (stderr,   " 0");
143             if (current & RR_Rotate_90)  fprintf (stderr,  " 90");
144             if (current & RR_Rotate_180) fprintf (stderr, " 180");
145             if (current & RR_Rotate_270) fprintf (stderr, " 270");
146             if (! (current & (RR_Rotate_0   | RR_Rotate_90 |
147                               RR_Rotate_180 | RR_Rotate_270)))
148               fprintf (stderr, " none");
149             fprintf (stderr, "\n");
150
151             fprintf (stderr, "%s:   Available Reflections:\t", blurb());
152             if (available & RR_Reflect_X) fprintf (stderr,   " X");
153             if (available & RR_Reflect_Y) fprintf (stderr,   " Y");
154             if (! (available & (RR_Reflect_X | RR_Reflect_Y)))
155               fprintf (stderr, " none");
156             fprintf (stderr, "\n");
157
158             fprintf (stderr, "%s:   Current Reflections:\t", blurb());
159             if (current & RR_Reflect_X) fprintf (stderr,   " X");
160             if (current & RR_Reflect_Y) fprintf (stderr,   " Y");
161             if (! (current & (RR_Reflect_X | RR_Reflect_Y)))
162               fprintf (stderr, " none");
163             fprintf (stderr, "\n");
164           }
165
166           /* Sizes */
167           {
168             int nsizes, j;
169             XRRScreenSize *rrsizes;
170
171             rrsizes = XRRConfigSizes (rrc, &nsizes);
172             if (nsizes <= 0)
173                 fprintf (stderr, "%s:   sizes:\t none\n", blurb());
174             else
175               for (j = 0; j < nsizes; j++)
176                 {
177                   short *rates;
178                   int nrates, k;
179                   fprintf (stderr,
180                            "%s:   %c size %d: %d x %d\t rates:",
181                            blurb(), 
182                            (j == current_size ? '+' : ' '),
183                            j,
184                            rrsizes[j].width, rrsizes[j].height);
185
186                   rates = XRRConfigRates (rrc, j, &nrates);
187                   if (nrates == 0)
188                     fprintf (stderr, " none?");
189                   else
190                     for (k = 0; k < nrates; k++)
191                       fprintf (stderr, " %d", rates[k]);
192                   fprintf (stderr, "\n");
193                   /* don't free 'rates' */
194                 }
195             /* don't free 'rrsizes' */
196           }
197
198           XRRFreeScreenConfigInfo (rrc);
199         }
200       else if (major >= 0)
201         {
202           fprintf(stderr, "%s:   XRRGetScreenInfo(dpy, %d) ==> NULL\n",
203                   blurb(), i);
204         }
205     }
206
207   if (major > 0)
208     {
209       Window w[20];
210       XWindowAttributes xgwa[20];
211
212       for (i = 0; i < nscreens; i++)
213         {
214           XRRSelectInput (dpy, RootWindow (dpy, i), RRScreenChangeNotifyMask);
215           w[i] = RootWindow (dpy, i);
216           XGetWindowAttributes (dpy, w[i], &xgwa[i]);
217         }
218
219       XSync (dpy, False);
220       fprintf (stderr, "\n%s: awaiting events...\n", progname);
221       while (1)
222         {
223           XEvent event;
224           XNextEvent (dpy, &event);
225
226           if (event.type == event_number + RRScreenChangeNotify)
227             {
228               XRRScreenChangeNotifyEvent *xrr_event =
229                 (XRRScreenChangeNotifyEvent *) &event;
230               int screen = XRRRootToScreen (dpy, xrr_event->window);
231
232               fprintf (stderr, "%s: screen %d: RRScreenChangeNotify event\n",
233                        progname, screen);
234
235               fprintf (stderr, "%s: screen %d: old size: \t%d x %d\n",
236                        progname, screen,
237                        DisplayWidth (dpy, screen),
238                        DisplayHeight (dpy, screen));
239               fprintf (stderr, "%s: screen %d: old root 0x%lx:\t%d x %d\n",
240                        progname, screen, (unsigned long) w[screen],
241                        xgwa[screen].width, xgwa[screen].height);
242
243               XRRUpdateConfiguration (&event);
244               XSync (dpy, False);
245
246               fprintf (stderr, "%s: screen %d: new size: \t%d x %d\n",
247                        progname, screen,
248                        DisplayWidth (dpy, screen),
249                        DisplayHeight (dpy, screen));
250
251               w[screen] = RootWindow (dpy, screen);
252               XGetWindowAttributes (dpy, w[screen], &xgwa[screen]);
253               fprintf (stderr, "%s: screen %d: new root 0x%lx:\t%d x %d\n",
254                        progname, screen, (unsigned long) w[screen],
255                        xgwa[screen].width, xgwa[screen].height);
256               fprintf (stderr, "\n");
257             }
258           else
259             {
260               fprintf (stderr, "%s: event %d\n", progname, event.type);
261             }
262         }
263     }
264
265   XSync (dpy, False);
266   exit (0);
267 }