Remove RandR output options.
[xorg/xrandr] / xrandr12.c
1 /*
2  * Copyright © 2006 Keith Packard
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 copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdio.h>
24 #include <X11/Xlib.h>
25 #include <X11/Xlibint.h>
26 #include <X11/Xatom.h>
27 #include <X11/Xproto.h>
28 #include <X11/extensions/Xrandr.h>
29 #include <X11/extensions/Xrender.h>     /* we share subpixel information */
30 #include <string.h>
31 #include <stdlib.h>
32
33 static char *program_name;
34
35 static char *direction[5] = {
36     "normal", 
37     "left", 
38     "inverted", 
39     "right",
40     "\n"};
41
42 /* subpixel order */
43 static char *order[6] = {
44     "unknown",
45     "horizontal rgb",
46     "horizontal bgr",
47     "vertical rgb",
48     "vertical bgr",
49     "no subpixels"};
50
51 static char *connection[3] = {
52     "connected",
53     "disconnected",
54     "unknown connection"};
55
56 static void
57 usage(void)
58 {
59     fprintf(stderr, "usage: %s [options]\n", program_name);
60     fprintf(stderr, "  where options are:\n");
61     fprintf(stderr, "  -display <display> or -d <display>\n");
62     fprintf(stderr, "  -help\n");
63     fprintf(stderr, "  -o <normal,inverted,left,right,0,1,2,3>\n");
64     fprintf(stderr, "            or --orientation <normal,inverted,left,right,0,1,2,3>\n");
65     fprintf(stderr, "  -q        or --query\n");
66     fprintf(stderr, "  -s <size>/<width>x<height> or --size <size>/<width>x<height>\n");
67     fprintf(stderr, "  -r <rate> or --rate <rate>\n");
68     fprintf(stderr, "  -v        or --version\n");
69     fprintf(stderr, "  -x        (reflect in x)\n");
70     fprintf(stderr, "  -y        (reflect in y)\n");
71     fprintf(stderr, "  --screen <screen>\n");
72     fprintf(stderr, "  --verbose\n");
73
74     exit(1);
75     /*NOTREACHED*/
76 }
77
78 int
79 main (int argc, char **argv)
80 {
81     Display       *dpy;
82     XRRScreenResources  *sr;
83     XRRScreenSize *sizes;
84     XRRScreenConfiguration *sc;
85     int         nsize;
86     int         nrate;
87     short               *rates;
88     Window      root;
89     Status      status = RRSetConfigFailed;
90     int         rot = -1;
91     int         verbose = 0, query = 0;
92     Rotation    rotation = RR_Rotate_0, current_rotation, rotations;
93     XEvent      event;
94     XRRScreenChangeNotifyEvent *sce;    
95     char          *display_name = NULL;
96     int                 i, j;
97     SizeID      current_size;
98     short               current_rate;
99     int         rate = -1;
100     int         size = -1;
101     int         dirind = 0;
102     int         setit = 0;
103     int         screen = -1;
104     int         version = 0;
105     int         event_base, error_base;
106     int         reflection = 0;
107     int         width = 0, height = 0;
108     int         mmwidth = 0, mmheight = 0;
109     int         ret = 0;
110     int         have_size = 0, have_mm_size = 0;
111     int         major_version, minor_version;
112     RRMode      mode = (RRMode) -1;
113     RRCrtc      crtc = 0;
114     RROutput    output = (RROutput) -1;
115     int         x = 0;
116     int         y = 0;
117     int         minWidth, minHeight;
118     int         maxWidth, maxHeight;
119
120     program_name = argv[0];
121     if (argc == 1) query = 1;
122     for (i = 1; i < argc; i++) {
123         if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
124             if (++i>=argc) usage ();
125             display_name = argv[i];
126             continue;
127         }
128         if (!strcmp("-help", argv[i])) {
129             usage();
130             continue;
131         }
132         if (!strcmp ("--verbose", argv[i])) {
133             verbose = 1;
134             continue;
135         }
136
137         if (!strcmp ("-s", argv[i]) || !strcmp ("--size", argv[i])) {
138             if (++i>=argc) usage ();
139             if (sscanf (argv[i], "%dx%d", &width, &height) == 2)
140                 have_size = 1;
141             else {
142                 usage();
143             }
144             continue;
145         }
146         if (!strcmp ("-mm", argv[i]) || !strcmp ("--mm", argv[i])) {
147             if (++i>=argc) usage ();
148             if (sscanf (argv[i], "%dx%d", &mmwidth, &mmheight) == 2)
149                 have_mm_size = 1;
150             else {
151                 usage();
152             }
153             continue;
154         }
155         if (!strcmp ("-m", argv[i]) || !strcmp ("--mode", argv[i])) {
156             if (++i>=argc) usage ();
157             mode = strtoul (argv[i], NULL, 0);
158             setit = 1;
159             continue;
160         }
161         if (!strcmp ("-c", argv[i]) || !strcmp ("--crtc", argv[i])) {
162             if (++i>=argc) usage ();
163             crtc = strtoul (argv[i], NULL, 0);
164             continue;
165         }
166         if (!strcmp ("-o", argv[i]) || !strcmp ("--output", argv[i])) {
167             if (++i>=argc) usage ();
168             output = strtoul (argv[i], NULL, 0);
169             continue;
170         }
171
172         if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) {
173             version = 1;
174             continue;
175         }
176
177         if (!strcmp ("-x", argv[i])) {
178             if (++i>=argc) usage ();
179             x = strtoul (argv[i], NULL, 0);
180             continue;
181         }
182         if (!strcmp ("-y", argv[i])) {
183             if (++i>=argc) usage ();
184             y = strtoul (argv[i], NULL, 0);
185             continue;
186         }
187         if (!strcmp ("--screen", argv[i])) {
188             if (++i>=argc) usage ();
189             screen = atoi (argv[i]);
190             if (screen < 0) usage();
191             continue;
192         }
193         if (!strcmp ("-q", argv[i]) || !strcmp ("--query", argv[i])) {
194             query = 1;
195             continue;
196         }
197         if (!strcmp ("-r", argv[i]) || !strcmp ("--rotation", argv[i])) {
198             char *endptr;
199             if (++i>=argc) usage ();
200             dirind = strtol(argv[i], &endptr, 0);
201             if (*endptr != '\0') {
202                 for (dirind = 0; dirind < 4; dirind++) {
203                     if (strcmp (direction[dirind], argv[i]) == 0) break;
204                 }
205                 if ((dirind < 0) || (dirind > 3))  usage();
206             }
207             rot = dirind;
208             setit = 1;
209             continue;
210         }
211         usage();
212     }
213     if (verbose) query = 1;
214
215     dpy = XOpenDisplay (display_name);
216
217     if (dpy == NULL) {
218         fprintf (stderr, "Can't open display %s\n", XDisplayName(display_name));
219         exit (1);
220     }
221     
222     XRRQueryVersion (dpy, &major_version, &minor_version);
223     if (!(major_version > 1 || minor_version >= 2))
224     {
225         fprintf (stderr, "Randr version too old (need 1.2 or better)\n");
226         exit (1);
227     }
228         
229     if (screen < 0)
230         screen = DefaultScreen (dpy);
231     if (screen >= ScreenCount (dpy)) {
232         fprintf (stderr, "Invalid screen number %d (display has %d)\n",
233                  screen, ScreenCount (dpy));
234         exit (1);
235     }
236
237     root = RootWindow (dpy, screen);
238
239     if (XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight,
240                                &maxWidth, &maxHeight))
241     {
242         printf ("min screen size: %d x %d\n", minWidth, minHeight);
243         printf ("max screen size: %d x %d\n", maxWidth, maxHeight);
244     }
245     sr = XRRGetScreenResources (dpy, root);
246
247     printf ("timestamp: %ld\n", sr->timestamp);
248     printf ("configTimestamp: %ld\n", sr->configTimestamp);
249     for (i = 0; i < sr->ncrtc; i++) {
250         XRRCrtcInfo     *xci;
251         int             j;
252         
253         printf ("\tcrtc: 0x%x\n", sr->crtcs[i]);
254         xci = XRRGetCrtcInfo (dpy, sr, sr->crtcs[i]);
255         printf ("\t\t%dx%d +%u+%u\n",
256                 xci->width, xci->height, xci->x, xci->y);
257         printf ("\t\tmode: 0x%x\n", xci->mode);
258         printf ("\t\toutputs:");
259         for (j = 0; j < xci->noutput; j++)
260             printf (" 0x%x", xci->outputs[j]);
261         printf ("\n");
262         printf ("\t\tpossible:");
263         for (j = 0; j < xci->npossible; j++)
264             printf (" 0x%x", xci->possible[j]);
265         printf ("\n");
266     }
267     for (i = 0; i < sr->noutput; i++) {
268         XRROutputInfo   *xoi;
269         Atom            *props;
270         int             j, nprop;
271
272         printf ("\toutput: 0x%x\n", sr->outputs[i]);
273         xoi = XRRGetOutputInfo (dpy, sr, sr->outputs[i]);
274         printf ("\t\tname: %s\n", xoi->name);
275         printf ("\t\ttimestamp: %d\n", xoi->timestamp);
276         printf ("\t\tcrtc: 0x%x\n", xoi->crtc);
277         printf ("\t\tconnection: %s\n", connection[xoi->connection]);
278         printf ("\t\tsubpixel_order: %s\n", order[xoi->subpixel_order]);
279         printf ("\t\tphysical_size: %5d x %5d\n", xoi->mm_width,xoi->mm_height);
280         printf ("\t\tmodes:");
281         for (j = 0; j < xoi->nmode; j++)
282             printf(" 0x%x%s", xoi->modes[j], j < xoi->npreferred ? "*" : "");
283         printf ("\n");
284         printf ("\t\tclones:");
285         for (j = 0; j < xoi->nclone; j++)
286             printf(" 0x%x", xoi->clones[j]);
287         printf ("\n");
288
289         props = XRRListOutputProperties (dpy, sr->outputs[i], &nprop);
290         printf ("\t\tproperties:\n");
291         for (j = 0; j < nprop; j++) {
292             char *prop;
293             int actual_format;
294             unsigned long nitems, bytes_after;
295             Atom actual_type;
296
297             XRRGetOutputProperty (dpy, sr->outputs[i], props[j],
298                                   0, 100, False, AnyPropertyType,
299                                   &actual_type, &actual_format,
300                                   &nitems, &bytes_after, &prop);
301
302             if (actual_type == XA_INTEGER && actual_format == 8) {
303                 int k;
304
305                 printf("\t\t\t%s:\n", XGetAtomName (dpy, props[j]));
306                 for (k = 0; k < nitems; k++) {
307                     if (k % 16 == 0)
308                         printf ("\t\t\t");
309                     printf("%02x", (unsigned char)prop[k]);
310                     if (k % 16 == 15)
311                         printf("\n");
312                 }
313             } else if (actual_format == 8) {
314                 printf ("\t\t\t%s: %s%s\n", XGetAtomName (dpy, props[j]),
315                         prop, bytes_after ? "..." : "");
316             } else {
317                 printf ("\t\t\t%s: ????\n", XGetAtomName (dpy, props[j]));
318             }
319         }
320
321         XRRFreeOutputInfo (xoi);
322     }
323     for (i = 0; i < sr->nmode; i++) {
324         double  rate;
325         printf ("\tmode: 0x%04x", sr->modes[i].id);
326         printf (" %15.15s", sr->modes[i].name);
327         printf (" %5d x %5d", sr->modes[i].width, sr->modes[i].height);
328         if (sr->modes[i].hTotal && sr->modes[i].vTotal)
329             rate = ((double) sr->modes[i].dotClock / 
330                     ((double) sr->modes[i].hTotal * (double) sr->modes[i].vTotal));
331         else
332             rate = 0;
333         printf (" %6.1fHz %6.1fMhz (with blanking: %d x %d)", rate,
334                 (float)sr->modes[i].dotClock / 1000000,
335                 sr->modes[i].hTotal, sr->modes[i].vTotal);
336         printf ("\n");
337     }
338     if (sr == NULL) 
339     {
340         fprintf (stderr, "Cannot get screen resources\n");
341         exit (1);
342     }
343
344     if (have_size)
345     {
346         if (!have_mm_size)
347         {
348             mmwidth = DisplayWidthMM(dpy, screen);
349             mmheight = DisplayHeightMM(dpy, screen);
350         }
351         XRRSetScreenSize (dpy, root, width, height, mmwidth, mmheight);
352     }
353     if (setit)
354     {
355         int noutput;
356         
357         if (!crtc)
358             crtc = sr->crtcs[0];
359
360         switch (output) {
361         case None:
362             noutput = 0;
363             break;
364         case (RROutput) -1:
365             output = sr->outputs[0];
366         default:
367             noutput = 1;
368             break;
369         }
370
371         if (mode != (RRMode) -1)
372         {
373             Status status;
374             
375             status = XRRSetCrtcConfig (dpy, sr, crtc, CurrentTime, x, y,
376                                        mode, rotation, &output, noutput);
377             printf ("status: %d\n", status);
378         }
379     }
380
381     XRRFreeScreenResources (sr);
382
383     XSync (dpy, False);
384
385     
386     return(ret);
387 }