Update demos for removal of XID structs and xcb_poll_for_reply error param.
[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 <xcb/xcb.h>
33 #include <xcb/xcb_aux.h>
34 #include <xcb/randr.h>
35 #include <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(xcb_randr_get_screen_info_reply_t *config, int sizeID, int *nrates)
89 {
90     int i = 0;
91     short *ents;
92     xcb_randr_refresh_rates_iterator_t ri = xcb_randr_get_screen_info_rates_iterator(config);
93     
94     while (i++ < sizeID) {
95         xcb_randr_refresh_rates_next(&ri);
96     }
97     
98     ents = (short *)xcb_randr_refresh_rates_rates(ri.data);
99     *nrates = xcb_randr_refresh_rates_rates_length(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   xcb_connection_t  *c;
113   xcb_randr_screen_size_t *sizes;
114   xcb_randr_get_screen_info_reply_t *sc;
115   int           nsize;
116   int           nrate;
117   short         *rates;
118   xcb_screen_t  *root;
119   int           status = XCB_RANDR_SET_CONFIG_FAILED;
120   int           rot = -1;
121   int           verbose = 0, query = 0;
122   short         rotation, current_rotation, rotations;
123   xcb_generic_event_t *event;
124   xcb_randr_screen_change_notify_event_t *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   xcb_generic_error_t *err;
140   uint16_t mask = (uint16_t) XCB_EVENT_MASK_STRUCTURE_NOTIFY;
141   uint32_t values[1];
142   xcb_randr_get_screen_info_cookie_t scookie;
143   int major_version, minor_version;
144   xcb_randr_query_version_reply_t *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 |= XCB_RANDR_ROTATION_REFLECT_X;
190       setit = 1;
191       continue;
192     }
193     if (!strcmp ("-y", argv[i])) {
194       reflection |= XCB_RANDR_ROTATION_REFLECT_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 = xcb_connect(display_name, &screen);
235   if (!c) {
236       fprintf (stderr, "Can't open display %s\n", display_name);
237       exit (1);
238   }
239   root = xcb_aux_get_screen(c, screen);
240   rr_version = xcb_randr_query_version_reply(c, xcb_randr_query_version(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 = xcb_randr_get_screen_info(c, root->root);
249   sc = xcb_randr_get_screen_info_reply(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 = xcb_randr_get_screen_info_sizes(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 & (XCB_RANDR_ROTATION_REFLECT_X|XCB_RANDR_ROTATION_REFLECT_Y))
328     {
329         if (current_rotation & XCB_RANDR_ROTATION_REFLECT_X) printf ("X Axis ");
330         if (current_rotation & XCB_RANDR_ROTATION_REFLECT_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 & (XCB_RANDR_ROTATION_REFLECT_X|XCB_RANDR_ROTATION_REFLECT_Y))
345     {
346         if (rotations & XCB_RANDR_ROTATION_REFLECT_X) printf ("X Axis ");
347         if (rotations & XCB_RANDR_ROTATION_REFLECT_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 & XCB_RANDR_ROTATION_REFLECT_X) printf ("X Axis ");
361         if (reflection & XCB_RANDR_ROTATION_REFLECT_Y) printf ("Y Axis");
362     }
363     else
364         printf ("neither axis");
365     printf ("\n");
366
367     if (reflection & XCB_RANDR_ROTATION_REFLECT_X) printf("Setting reflection on X axis\n");
368
369     if (reflection & XCB_RANDR_ROTATION_REFLECT_Y) printf("Setting reflection on Y axis\n");
370   }
371
372   /* we should test configureNotify on the root window */
373   values[0] = 1;
374   xcb_configure_window(c, root->root, mask, values);
375
376   if (setit) xcb_randr_select_input (c, root->root, XCB_RANDR_SM_SCREEN_CHANGE_NOTIFY);
377
378   if (setit) {
379     xcb_randr_set_screen_config_cookie_t sscc;
380     xcb_randr_set_screen_config_reply_t *config;
381     sscc = xcb_randr_set_screen_config(c, root->root, CurrentTime, sc->config_timestamp, size,
382             (short) (rotation | reflection), rate);
383     config = xcb_randr_set_screen_config_reply(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 xcb_query_extension_reply_t *qrre_rep;
393   qrre_rep = xcb_get_extension_data(c, &xcb_randr_id);
394   event_base = qrre_rep->first_event;
395   error_base = qrre_rep->first_error;
396   
397   if (verbose && setit) {
398     if (status == XCB_RANDR_SET_CONFIG_SUCCESS)
399       {
400         while (1) {
401         int spo;
402         event = xcb_wait_for_event(c);
403         
404         printf ("Event received, type = %d\n", event->response_type);
405 #if 0
406         /*
407          * update Xlib's knowledge of the event
408          * Not sure what the equiv of this is or if we need it.
409          */
410         XRRUpdateConfiguration (&event);
411 #endif
412         
413         switch (event->response_type - event_base) {
414         case XCB_RANDR_SCREEN_CHANGE_NOTIFY:
415           sce = (xcb_randr_screen_change_notify_event_t *) event;
416
417           printf("Got a screen change notify event!\n");
418           printf(" window = %d\n root = %d\n size_index = %d\n rotation %d\n", 
419                (int) sce->request_window, (int) sce->root, 
420                sce->sizeID,  sce->rotation);
421           printf(" timestamp = %d, config_timestamp = %d\n",
422                sce->timestamp, sce->config_timestamp);
423           printf(" Rotation = %x\n", sce->rotation);
424           printf(" %d X %d pixels, %d X %d mm\n",
425                  sce->width, sce->height, sce->mwidth, sce->mheight);
426           
427           printf("Display width   %d, height   %d\n",
428                  root->width_in_pixels, root->height_in_pixels);
429           printf("Display widthmm %d, heightmm %d\n", 
430                  root->width_in_millimeters, root->height_in_millimeters);
431           
432           spo = sce->subpixel_order;
433           if ((spo < 0) || (spo > 5))
434             printf ("Unknown subpixel order, value = %d\n", spo);
435           else printf ("new Subpixel rendering model is %s\n", order[spo]);
436           break;
437         default:
438           if (event->response_type == XCB_CONFIGURE_NOTIFY)
439             printf("Received ConfigureNotify Event!\n");
440           else
441             printf("unknown event received, type = %d!\n", event->response_type);
442         }
443         }
444       }
445   }
446 #if 0
447   XRRFreeScreenConfigInfo(sc);
448 #endif
449   free(sc);
450   free(rr_version);
451   xcb_disconnect(c);
452   return(0);
453 }