Fix typo in lissajoux: s/availaible/available/g.
[free-sw/xcb/demo] / xcbrandr.c
1 /*
2  * $XFree86: xc/programs/xrandr/xrandr.c,v 1.11 2002/10/14 18:01:43 keithp Exp $
3  *
4  * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
5  * Copyright © 2002 Hewlett Pacard Company, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Keith Packard or HP not be used in
12  * advertising or publicity pertaining to distribution of the software without
13  * specific, written prior permission.  Keith Packard and HP makes no
14  * representations about the suitability of this software for any purpose.  It
15  * is provided "as is" without express or implied warranty.
16  *
17  * KEITH PACKARD and HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  *
25  * Blame Jim Gettys for any bugs; he wrote most of the client side code,
26  * and part of the server code for randr.
27  *
28  * Ported to XCB by Jeremy Kolb 2/8/2005
29  */
30
31 #include <stdio.h>
32 #include <X11/XCB/xcb.h>
33 #include <X11/XCB/xcb_aux.h>
34 #include <X11/XCB/randr.h>
35 #include <X11/XCB/render.h>     /* we share subpixel information */
36 #include <string.h>
37 #include <stdlib.h>
38
39 #define CurrentTime 0L /* special time apparently*/
40
41 static char *program_name;
42
43 static char *direction[5] = {
44   "normal", 
45   "left", 
46   "inverted", 
47   "right",
48   "\n"};
49
50 /* subpixel order */
51 static char *order[6] = {
52   "unknown",
53   "horizontal rgb",
54   "horizontal bgr",
55   "vertical rgb",
56   "vertical bgr",
57   "no subpixels"};
58
59
60 static void
61 usage(void)
62 {
63   fprintf(stderr, "usage: %s [options]\n", program_name);
64   fprintf(stderr, "  where options are:\n");
65   fprintf(stderr, "  -display <display> or -d <display>\n");
66   fprintf(stderr, "  -help\n");
67   fprintf(stderr, "  -o <normal,inverted,left,right,0,1,2,3>\n");
68   fprintf(stderr, "            or --orientation <normal,inverted,left,right,0,1,2,3>\n");
69   fprintf(stderr, "  -q        or --query\n");
70   fprintf(stderr, "  -s <size>/<width>x<height> or --size <size>/<width>x<height>\n");
71   fprintf(stderr, "  -r <rate> or --rate <rate>\n");
72   fprintf(stderr, "  -v        or --version\n");
73   fprintf(stderr, "  -x        (reflect in x)\n");
74   fprintf(stderr, "  -y        (reflect in y)\n");
75   fprintf(stderr, "  --screen <screen>\n");
76   fprintf(stderr, "  --verbose\n");
77   
78   exit(1);
79   /*NOTREACHED*/
80 }
81
82 /*
83  * Same idea as xc/lib/Xrandr.c (XRRConfigRates).
84  * Returns the rates for a given screen.
85  * Would be nice to put in another library or something.
86  */
87 short*
88 ConfigRates(XCBRandRGetScreenInfoRep *config, int sizeID, int *nrates)
89 {
90     int i = 0;
91     short *ents;
92     XCBRandRRefreshRatesIter ri = XCBRandRGetScreenInfoRatesIter(config);
93     
94     while (i++ < sizeID) {
95         XCBRandRRefreshRatesNext(&ri);
96     }
97     
98     ents = (short *)XCBRandRRefreshRatesRates(ri.data);
99     *nrates = XCBRandRRefreshRatesRatesLength(ri.data);
100     
101     if (!nrates) {
102         *nrates = 0;
103         return 0;
104     }
105     
106     return ents;
107 }
108
109 int
110 main (int argc, char **argv)
111 {
112   XCBConnection  *c;
113   XCBRandRScreenSize *sizes;
114   XCBRandRGetScreenInfoRep *sc;
115   int           nsize;
116   int           nrate;
117   short         *rates;
118   XCBSCREEN     *root;
119   int           status = XCBRandRSetConfigFailed;
120   int           rot = -1;
121   int           verbose = 0, query = 0;
122   short         rotation, current_rotation, rotations;
123   XCBGenericEvent *event;
124   XCBRandRScreenChangeNotifyEvent *sce;
125   char          *display_name = NULL;
126   int           i, j;
127   int           current_size;
128   short         current_rate;
129   short         rate = -1;
130   short         size = -1;
131   int           dirind = 0;
132   static int    setit = 0;
133   int           screen = -1;
134   int           version = 0;
135   int           event_base, error_base;
136   short         reflection = 0;
137   int           width = 0, height = 0;
138   int           have_pixel_size = 0;
139   XCBGenericError *err;
140   CARD16 mask = (CARD16) XCBEventMaskStructureNotify;
141   CARD32 values[1];
142   XCBRandRGetScreenInfoCookie scookie;
143   int major_version, minor_version;
144   XCBRandRQueryVersionRep *rr_version;
145
146   program_name = argv[0];
147   if (argc == 1) query = 1;
148   for (i = 1; i < argc; i++) {
149     if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
150       if (++i>=argc) usage ();
151       display_name = argv[i];
152       continue;
153     }
154     if (!strcmp("-help", argv[i])) {
155       usage();
156       continue;
157     }
158     if (!strcmp ("--verbose", argv[i])) {
159       verbose = 1;
160       continue;
161     }
162
163     if (!strcmp ("-s", argv[i]) || !strcmp ("--size", argv[i])) {
164       if (++i>=argc) usage ();
165       if (sscanf (argv[i], "%dx%d", &width, &height) == 2)
166         have_pixel_size = 1;
167       else {
168         size = atoi (argv[i]);
169         if (size < 0) usage();
170       }
171       setit = 1;
172       continue;
173     }
174
175     if (!strcmp ("-r", argv[i]) || !strcmp ("--rate", argv[i])) {
176       if (++i>=argc) usage ();
177       rate = atoi (argv[i]);
178       if (rate < 0) usage();
179       setit = 1;
180       continue;
181     }
182
183     if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) {
184       version = 1;
185       continue;
186     }
187
188     if (!strcmp ("-x", argv[i])) {
189       reflection |= XCBRandRRotationReflect_X;
190       setit = 1;
191       continue;
192     }
193     if (!strcmp ("-y", argv[i])) {
194       reflection |= XCBRandRRotationReflect_Y;
195       setit = 1;
196       continue;
197     }
198     if (!strcmp ("--screen", argv[i])) {
199       if (++i>=argc) usage ();
200       screen = atoi (argv[i]);
201       if (screen < 0) usage();
202       continue;
203     }
204     if (!strcmp ("-q", argv[i]) || !strcmp ("--query", argv[i])) {
205       query = 1;
206       continue;
207     }
208     if (!strcmp ("-o", argv[i]) || !strcmp ("--orientation", argv[i])) {
209       char *endptr;
210       if (++i>=argc) usage ();
211       dirind = strtol(argv[i], &endptr, 0);
212       if (*endptr != '\0') {
213         for (dirind = 0; dirind < 4; dirind++) {
214           if (strcmp (direction[dirind], argv[i]) == 0) break;
215         }
216         if ((dirind < 0) || (dirind > 3))  usage();
217       }
218       rot = dirind;
219       setit = 1;
220       continue;
221     }
222     
223     usage();
224   }
225  
226   if (verbose) query = 1;
227
228   if (!display_name)
229       display_name = getenv("DISPLAY");
230   if (!display_name) {
231       fprintf (stderr, "No display available\n");
232       exit (1);
233   }
234   c = XCBConnect(display_name, &screen);
235   if (!c) {
236       fprintf (stderr, "Can't open display %s\n", display_name);
237       exit (1);
238   }
239   root = XCBAuxGetScreen(c, screen);
240   rr_version = XCBRandRQueryVersionReply(c, XCBRandRQueryVersion(c, 1, 1), 0);
241   if (!rr_version) {
242       fprintf(stderr, "Can't get VersionReply.\n");
243       exit (1);
244   }
245   major_version = rr_version->major_version;
246   minor_version = rr_version->minor_version;
247
248   scookie = XCBRandRGetScreenInfo(c, root->root);
249   sc = XCBRandRGetScreenInfoReply(c, scookie, 0);
250   if (!sc) {
251         fprintf(stderr, "Can't get ScreenInfo.\n");
252         exit (1);
253   }
254
255   current_rotation = sc->rotation;
256   current_size = sc->sizeID;
257   
258   nsize = sc->nSizes;
259   sizes = XCBRandRGetScreenInfoSizes(sc);
260
261   if (have_pixel_size) {
262     for (size = 0; size < nsize; size++)
263     {
264       if (sizes[size].width == width && sizes[size].height == height)
265         break;
266     }
267   }
268   else if (size < 0)
269     size = current_size;
270
271   if (size >= nsize) usage();
272
273   if (rot < 0)
274   {
275     for (rot = 0; rot < 4; rot++)
276         if (1 << rot == (current_rotation & 0xf))
277             break;
278   }
279
280   current_rate = sc->rate;
281   
282   if (rate < 0)
283   {
284     if (size == current_size)
285         rate = current_rate;
286     else
287         rate = 0;
288   }
289
290   if (version) {
291     printf("Server reports RandR version %d.%d\n", 
292            major_version, minor_version);
293   }
294   
295   if (query) {
296     printf(" SZ:    Pixels          Physical       Refresh\n");
297     for (i = 0; i < nsize; i++) {
298       printf ("%c%-2d %5d x %-5d  (%4dmm x%4dmm )",
299            i == current_size ? '*' : ' ',
300            i, sizes[i].width, sizes[i].height,
301            sizes[i].mwidth, sizes[i].mheight);
302       rates = ConfigRates (sc, i, &nrate);
303
304       if (nrate) printf ("  ");
305       for (j = 0; j < nrate; j++)
306         printf ("%c%-4d",
307                 i == current_size && rates[j] == current_rate ? '*' : ' ',
308                 rates[j]);
309       printf ("\n");
310     }
311   }
312
313 #if 0
314   rotations = XRRConfigRotations(sc, &current_rotation);
315 #else
316   rotations = sc->rotation;
317 #endif
318
319   rotation = 1 << rot ;
320   if (query) {
321     for (i = 0; i < 4; i ++) {
322       if ((current_rotation >> i) & 1) 
323         printf("Current rotation - %s\n", direction[i]);
324     }
325
326     printf("Current reflection - ");
327     if (current_rotation & (XCBRandRRotationReflect_X|XCBRandRRotationReflect_Y))
328     {
329         if (current_rotation & XCBRandRRotationReflect_X) printf ("X Axis ");
330         if (current_rotation & XCBRandRRotationReflect_Y) printf ("Y Axis");
331     }
332     else
333         printf ("none");
334     printf ("\n");
335     
336
337     printf ("Rotations possible - ");
338     for (i = 0; i < 4; i ++) {
339       if ((rotations >> i) & 1)  printf("%s ", direction[i]);
340     }
341     printf ("\n");
342
343     printf ("Reflections possible - ");
344     if (rotations & (XCBRandRRotationReflect_X|XCBRandRRotationReflect_Y))
345     {
346         if (rotations & XCBRandRRotationReflect_X) printf ("X Axis ");
347         if (rotations & XCBRandRRotationReflect_Y) printf ("Y Axis");
348     }
349     else
350         printf ("none");
351     printf ("\n");
352   }
353
354   if (verbose) { 
355     printf("Setting size to %d, rotation to %s\n",  size, direction[rot]);
356
357     printf ("Setting reflection on ");
358     if (reflection)
359     {
360         if (reflection & XCBRandRRotationReflect_X) printf ("X Axis ");
361         if (reflection & XCBRandRRotationReflect_Y) printf ("Y Axis");
362     }
363     else
364         printf ("neither axis");
365     printf ("\n");
366
367     if (reflection & XCBRandRRotationReflect_X) printf("Setting reflection on X axis\n");
368
369     if (reflection & XCBRandRRotationReflect_Y) printf("Setting reflection on Y axis\n");
370   }
371
372   /* we should test configureNotify on the root window */
373   values[0] = 1;
374   XCBConfigureWindow(c, root->root, mask, values);
375
376   if (setit) XCBRandRSelectInput (c, root->root, XCBRandRSMScreenChangeNotify);
377
378   if (setit) {
379     XCBRandRSetScreenConfigCookie sscc;
380     XCBRandRSetScreenConfigRep *config;
381     sscc = XCBRandRSetScreenConfig(c, root->root, CurrentTime, sc->config_timestamp, size,
382             (short) (rotation | reflection), rate);
383     config = XCBRandRSetScreenConfigReply(c, sscc, &err);
384     if (!config) {
385         fprintf(stderr, "Can't set the screen. Error Code: %i Status:%i\n",
386                 err->error_code, status);
387         exit(1);
388     }
389     status = config->status;
390   }
391     
392   const XCBQueryExtensionRep *qrre_rep = XCBRandRInit(c);
393   event_base = qrre_rep->first_event;
394   error_base = qrre_rep->first_error;
395   
396   if (verbose && setit) {
397     if (status == XCBRandRSetConfigSuccess)
398       {
399         while (1) {
400         int spo;
401         event = XCBWaitForEvent(c);
402         
403         printf ("Event received, type = %d\n", event->response_type);
404 #if 0
405         /*
406          * update Xlib's knowledge of the event
407          * Not sure what the equiv of this is or if we need it.
408          */
409         XRRUpdateConfiguration (&event);
410 #endif
411         
412         switch (event->response_type - event_base) {
413         case XCBRandRScreenChangeNotify:
414           sce = (XCBRandRScreenChangeNotifyEvent *) event;
415
416           printf("Got a screen change notify event!\n");
417           printf(" window = %d\n root = %d\n size_index = %d\n rotation %d\n", 
418                (int) sce->request_window.xid, (int) sce->root.xid, 
419                sce->sizeID,  sce->rotation);
420           printf(" timestamp = %ld, config_timestamp = %ld\n",
421                sce->timestamp, sce->config_timestamp);
422           printf(" Rotation = %x\n", sce->rotation);
423           printf(" %d X %d pixels, %d X %d mm\n",
424                  sce->width, sce->height, sce->mwidth, sce->mheight);
425           
426           printf("Display width   %d, height   %d\n",
427                  root->width_in_pixels, root->height_in_pixels);
428           printf("Display widthmm %d, heightmm %d\n", 
429                  root->width_in_millimeters, root->height_in_millimeters);
430           
431           spo = sce->subpixel_order;
432           if ((spo < 0) || (spo > 5))
433             printf ("Unknown subpixel order, value = %d\n", spo);
434           else printf ("new Subpixel rendering model is %s\n", order[spo]);
435           break;
436         default:
437           if (event->response_type == XCBConfigureNotify)
438             printf("Received ConfigureNotify Event!\n");
439           else
440             printf("unknown event received, type = %d!\n", event->response_type);
441         }
442         }
443       }
444   }
445 #if 0
446   XRRFreeScreenConfigInfo(sc);
447 #endif
448   free(sc);
449   free(c);
450   return(0);
451 }