2 * $XFree86: xc/programs/xrandr/xrandr.c,v 1.11 2002/10/14 18:01:43 keithp Exp $
4 * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
5 * Copyright © 2002 Hewlett Pacard Company, Inc.
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.
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.
25 * Blame Jim Gettys for any bugs; he wrote most of the client side code,
26 * and part of the server code for randr.
28 * Ported to XCB by Jeremy Kolb 2/8/2005
33 #include <xcb/xcb_aux.h>
34 #include <xcb/randr.h>
35 #include <xcb/render.h> /* we share subpixel information */
39 #define CurrentTime 0L /* special time apparently*/
41 static char *program_name;
43 static char *direction[5] = {
51 static char *order[6] = {
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");
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.
88 ConfigRates(xcb_randr_get_screen_info_reply_t *config, int sizeID, int *nrates)
92 xcb_randr_refresh_rates_iterator_t ri = xcb_randr_get_screen_info_rates_iterator(config);
94 while (i++ < sizeID) {
95 xcb_randr_refresh_rates_next(&ri);
98 ents = (short *)xcb_randr_refresh_rates_rates(ri.data);
99 *nrates = xcb_randr_refresh_rates_rates_length(ri.data);
110 main (int argc, char **argv)
113 xcb_randr_screen_size_t *sizes;
114 xcb_randr_get_screen_info_reply_t *sc;
119 int status = XCB_RANDR_SET_CONFIG_FAILED;
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;
132 static int setit = 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;
142 xcb_randr_get_screen_info_cookie_t scookie;
143 int major_version, minor_version;
144 xcb_randr_query_version_reply_t *rr_version;
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];
154 if (!strcmp("-help", argv[i])) {
158 if (!strcmp ("--verbose", argv[i])) {
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)
168 size = atoi (argv[i]);
169 if (size < 0) usage();
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();
183 if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) {
188 if (!strcmp ("-x", argv[i])) {
189 reflection |= XCB_RANDR_ROTATION_REFLECT_X;
193 if (!strcmp ("-y", argv[i])) {
194 reflection |= XCB_RANDR_ROTATION_REFLECT_Y;
198 if (!strcmp ("--screen", argv[i])) {
199 if (++i>=argc) usage ();
200 screen = atoi (argv[i]);
201 if (screen < 0) usage();
204 if (!strcmp ("-q", argv[i]) || !strcmp ("--query", argv[i])) {
208 if (!strcmp ("-o", argv[i]) || !strcmp ("--orientation", argv[i])) {
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;
216 if ((dirind < 0) || (dirind > 3)) usage();
226 if (verbose) query = 1;
229 display_name = getenv("DISPLAY");
231 fprintf (stderr, "No display available\n");
234 c = xcb_connect(display_name, &screen);
235 if (xcb_connection_has_error(c)) {
236 fprintf (stderr, "Can't open display %s\n", display_name);
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);
242 fprintf(stderr, "Can't get VersionReply.\n");
245 major_version = rr_version->major_version;
246 minor_version = rr_version->minor_version;
248 scookie = xcb_randr_get_screen_info(c, root->root);
249 sc = xcb_randr_get_screen_info_reply(c, scookie, 0);
251 fprintf(stderr, "Can't get ScreenInfo.\n");
255 current_rotation = sc->rotation;
256 current_size = sc->sizeID;
259 sizes = xcb_randr_get_screen_info_sizes(sc);
261 if (have_pixel_size) {
262 for (size = 0; size < nsize; size++)
264 if (sizes[size].width == width && sizes[size].height == height)
271 if (size >= nsize) usage();
275 for (rot = 0; rot < 4; rot++)
276 if (1 << rot == (current_rotation & 0xf))
280 current_rate = sc->rate;
284 if (size == current_size)
291 printf("Server reports RandR version %d.%d\n",
292 major_version, minor_version);
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);
304 if (nrate) printf (" ");
305 for (j = 0; j < nrate; j++)
307 i == current_size && rates[j] == current_rate ? '*' : ' ',
314 rotations = XRRConfigRotations(sc, ¤t_rotation);
316 rotations = sc->rotation;
319 rotation = 1 << rot ;
321 for (i = 0; i < 4; i ++) {
322 if ((current_rotation >> i) & 1)
323 printf("Current rotation - %s\n", direction[i]);
326 printf("Current reflection - ");
327 if (current_rotation & (XCB_RANDR_ROTATION_REFLECT_X|XCB_RANDR_ROTATION_REFLECT_Y))
329 if (current_rotation & XCB_RANDR_ROTATION_REFLECT_X) printf ("X Axis ");
330 if (current_rotation & XCB_RANDR_ROTATION_REFLECT_Y) printf ("Y Axis");
337 printf ("Rotations possible - ");
338 for (i = 0; i < 4; i ++) {
339 if ((rotations >> i) & 1) printf("%s ", direction[i]);
343 printf ("Reflections possible - ");
344 if (rotations & (XCB_RANDR_ROTATION_REFLECT_X|XCB_RANDR_ROTATION_REFLECT_Y))
346 if (rotations & XCB_RANDR_ROTATION_REFLECT_X) printf ("X Axis ");
347 if (rotations & XCB_RANDR_ROTATION_REFLECT_Y) printf ("Y Axis");
355 printf("Setting size to %d, rotation to %s\n", size, direction[rot]);
357 printf ("Setting reflection on ");
360 if (reflection & XCB_RANDR_ROTATION_REFLECT_X) printf ("X Axis ");
361 if (reflection & XCB_RANDR_ROTATION_REFLECT_Y) printf ("Y Axis");
364 printf ("neither axis");
367 if (reflection & XCB_RANDR_ROTATION_REFLECT_X) printf("Setting reflection on X axis\n");
369 if (reflection & XCB_RANDR_ROTATION_REFLECT_Y) printf("Setting reflection on Y axis\n");
372 /* we should test configureNotify on the root window */
374 xcb_configure_window(c, root->root, mask, values);
376 if (setit) xcb_randr_select_input (c, root->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
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);
385 fprintf(stderr, "Can't set the screen. Error Code: %i Status:%i\n",
386 err->error_code, status);
389 status = config->status;
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;
397 if (verbose && setit) {
398 if (status == XCB_RANDR_SET_CONFIG_SUCCESS)
402 event = xcb_wait_for_event(c);
404 printf ("Event received, type = %d\n", event->response_type);
407 * update Xlib's knowledge of the event
408 * Not sure what the equiv of this is or if we need it.
410 XRRUpdateConfiguration (&event);
413 switch (event->response_type - event_base) {
414 case XCB_RANDR_SCREEN_CHANGE_NOTIFY:
415 sce = (xcb_randr_screen_change_notify_event_t *) event;
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);
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);
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]);
438 if (event->response_type == XCB_CONFIGURE_NOTIFY)
439 printf("Received ConfigureNotify Event!\n");
441 printf("unknown event received, type = %d!\n", event->response_type);
447 XRRFreeScreenConfigInfo(sc);