2 * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
3 * Copyright © 2002 Hewlett Packard Company, Inc.
4 * Copyright © 2006 Intel Corporation
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that copyright
9 * notice and this permission notice appear in supporting documentation, and
10 * that the name of the copyright holders not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. The copyright holders make no representations
13 * about the suitability of this software for any purpose. It is provided "as
14 * is" without express or implied warranty.
16 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * Thanks to Jim Gettys who wrote most of the client side code,
25 * and part of the server code for randr.
30 #include <X11/Xlibint.h>
31 #include <X11/Xproto.h>
32 #include <X11/Xatom.h>
33 #include <X11/extensions/Xrandr.h>
34 #include <X11/extensions/Xrender.h> /* we share subpixel information */
40 #if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 2)
41 #define HAS_RANDR_1_2 1
44 static char *program_name;
47 static int screen = -1;
48 static Bool verbose = False;
49 static Bool automatic = False;
50 static Bool properties = False;
52 static char *direction[5] = {
59 static char *reflections[5] = {
67 static char *order[6] = {
78 fprintf(stderr, "usage: %s [options]\n", program_name);
79 fprintf(stderr, " where options are:\n");
80 fprintf(stderr, " -display <display> or -d <display>\n");
81 fprintf(stderr, " -help\n");
82 fprintf(stderr, " -o <normal,inverted,left,right,0,1,2,3>\n");
83 fprintf(stderr, " or --orientation <normal,inverted,left,right,0,1,2,3>\n");
84 fprintf(stderr, " -q or --query\n");
85 fprintf(stderr, " -s <size>/<width>x<height> or --size <size>/<width>x<height>\n");
86 fprintf(stderr, " -r <rate> or --rate <rate> or --refresh <rate>\n");
87 fprintf(stderr, " -v or --version\n");
88 fprintf(stderr, " -x (reflect in x)\n");
89 fprintf(stderr, " -y (reflect in y)\n");
90 fprintf(stderr, " --screen <screen>\n");
91 fprintf(stderr, " --verbose\n");
92 fprintf(stderr, " --dryrun\n");
94 fprintf(stderr, " --prop or --properties\n");
95 fprintf(stderr, " --fb <width>x<height>\n");
96 fprintf(stderr, " --fbmm <width>x<height>\n");
97 fprintf(stderr, " --dpi <dpi>/<output>\n");
99 fprintf(stderr, " --clone\n");
100 fprintf(stderr, " --extend\n");
102 fprintf(stderr, " --output <output>\n");
103 fprintf(stderr, " --crtc <crtc>\n");
104 fprintf(stderr, " --mode <mode>\n");
105 fprintf(stderr, " --rate <rate> or --refresh <rate>\n");
106 fprintf(stderr, " --preferred\n");
107 fprintf(stderr, " --pos <x>x<y>\n");
108 fprintf(stderr, " --rotate normal,inverted,left,right\n");
109 fprintf(stderr, " --reflect normal,x,y,xy\n");
110 fprintf(stderr, " --auto\n");
111 fprintf(stderr, " --left-of <output>\n");
112 fprintf(stderr, " --right-of <output>\n");
113 fprintf(stderr, " --above <output>\n");
114 fprintf(stderr, " --below <output>\n");
115 fprintf(stderr, " --off\n");
123 fatal (const char *format, ...)
127 va_start (ap, format);
128 fprintf (stderr, "%s: ", program_name);
129 vfprintf (stderr, format, ap);
136 rotation_name (Rotation rotation)
140 if ((rotation & 0xf) == 0)
142 for (i = 0; i < 4; i++)
143 if (rotation & (1 << i))
145 return "invalid rotation";
149 reflection_name (Rotation rotation)
151 rotation &= (RR_Reflect_X|RR_Reflect_Y);
159 case RR_Reflect_X|RR_Reflect_Y:
160 return "X and Y axis";
165 typedef enum _policy {
169 typedef enum _relation {
170 left_of, right_of, above, below
173 typedef enum _changes {
175 changes_crtc = (1 << 0),
176 changes_mode = (1 << 1),
177 changes_relation = (1 << 2),
178 changes_position = (1 << 3),
179 changes_rotation = (1 << 4),
180 changes_reflection = (1 << 5),
181 changes_automatic = (1 << 6),
182 changes_refresh = (1 << 7),
185 typedef enum _name_kind {
187 name_string = (1 << 0),
189 name_index = (1 << 2),
190 name_preferred = (1 << 3),
200 typedef struct _crtc crtc_t;
201 typedef struct _output output_t;
206 XRRCrtcInfo *crtc_info;
208 XRRModeInfo *mode_info;
217 struct _output *next;
222 XRROutputInfo *output_info;
229 XRRModeInfo *mode_info;
240 static char *connection[3] = {
243 "unknown connection"};
245 #define OUTPUT_NAME 1
249 #define CRTC_INDEX 0x40000000
258 static output_t *outputs = NULL;
259 static output_t **outputs_tail = &outputs;
260 static crtc_t *crtcs;
261 static int num_crtcs;
262 static XRRScreenResources *res;
263 static int fb_width = 0, fb_height = 0;
264 static int fb_width_mm = 0, fb_height_mm = 0;
265 static float dpi = 0;
266 static char *dpi_output = NULL;
267 static Bool dryrun = False;
268 static int minWidth, maxWidth, minHeight, maxHeight;
269 static Bool has_1_2 = False;
272 mode_height (XRRModeInfo *mode_info, Rotation rotation)
274 switch (rotation & 0xf) {
277 return mode_info->height;
280 return mode_info->width;
287 mode_width (XRRModeInfo *mode_info, Rotation rotation)
289 switch (rotation & 0xf) {
292 return mode_info->width;
295 return mode_info->height;
301 /* v refresh frequency in Hz */
303 mode_refresh (XRRModeInfo *mode_info)
307 if (mode_info->hTotal && mode_info->vTotal)
308 rate = ((float) mode_info->dotClock /
309 ((float) mode_info->hTotal * (float) mode_info->vTotal));
315 /* h sync frequency in Hz */
317 mode_hsync (XRRModeInfo *mode_info)
321 if (mode_info->hTotal)
322 rate = (float) mode_info->dotClock / (float) mode_info->hTotal;
329 init_name (name_t *name)
331 name->kind = name_none;
335 set_name_string (name_t *name, char *string)
337 name->kind |= name_string;
338 name->string = string;
342 set_name_xid (name_t *name, XID xid)
344 name->kind |= name_xid;
349 set_name_index (name_t *name, int index)
351 name->kind |= name_index;
356 set_name_preferred (name_t *name)
358 name->kind |= name_preferred;
362 set_name_all (name_t *name, name_t *old)
364 if (old->kind & name_xid)
365 name->xid = old->xid;
366 if (old->kind & name_string)
367 name->string = old->string;
368 if (old->kind & name_index)
369 name->index = old->index;
370 name->kind |= old->kind;
374 set_name (name_t *name, char *string, name_kind_t valid)
379 if ((valid & name_xid) && sscanf (string, "0x%x", &xid) == 1)
380 set_name_xid (name, xid);
381 else if ((valid & name_index) && sscanf (string, "%d", &index) == 1)
382 set_name_index (name, index);
383 else if (valid & name_string)
384 set_name_string (name, string);
392 output_t *output = calloc (1, sizeof (output_t));
395 fatal ("out of memory");
397 *outputs_tail = output;
398 outputs_tail = &output->next;
403 find_output (name_t *name)
407 for (output = outputs; output; output = output->next)
409 name_kind_t common = name->kind & output->output.kind;
411 if ((common & name_xid) && name->xid == output->output.xid)
413 if ((common & name_string) && !strcmp (name->string, output->output.string))
415 if ((common & name_index) & name->index == output->output.index)
422 find_output_by_xid (RROutput output)
426 init_name (&output_name);
427 set_name_xid (&output_name, output);
428 return find_output (&output_name);
432 find_output_by_name (char *name)
436 init_name (&output_name);
437 set_name_string (&output_name, name);
438 return find_output (&output_name);
442 find_crtc (name_t *name)
447 for (c = 0; c < num_crtcs; c++)
452 common = name->kind & crtc->crtc.kind;
454 if ((common & name_xid) && name->xid == crtc->crtc.xid)
456 if ((common & name_string) && !strcmp (name->string, crtc->crtc.string))
458 if ((common & name_index) & name->index == crtc->crtc.index)
466 find_crtc_by_xid (RRCrtc crtc)
470 init_name (&crtc_name);
471 set_name_xid (&crtc_name, crtc);
472 return find_crtc (&crtc_name);
476 find_mode (name_t *name, float refresh)
479 XRRModeInfo *best = NULL;
482 for (m = 0; m < res->nmode; m++)
484 XRRModeInfo *mode = &res->modes[m];
485 if ((name->kind & name_xid) && name->xid == mode->id)
490 if ((name->kind & name_string) && !strcmp (name->string, mode->name))
495 dist = fabs (mode_refresh (mode) - refresh);
498 if (!best || dist < bestDist)
510 find_mode_by_xid (RRMode mode)
514 init_name (&mode_name);
515 set_name_xid (&mode_name, mode);
516 return find_mode (&mode_name, 0);
521 find_mode_for_output (output_t *output, name_t *name)
523 XRROutputInfo *output_info = output->output_info;
525 XRRModeInfo *best = NULL;
528 for (m = 0; m < output_info->nmode; m++)
532 mode = find_mode_by_xid (output_info->modes[m]);
534 if ((name->kind & name_xid) && name->xid == mode->id)
539 if ((name->kind & name_string) && !strcmp (name->string, mode->name))
544 dist = fabs (mode_refresh (mode) - output->refresh);
547 if (!best || dist < bestDist)
558 preferred_mode (output_t *output)
560 XRROutputInfo *output_info = output->output_info;
567 for (m = 0; m < output_info->nmode; m++)
569 XRRModeInfo *mode_info = find_mode_by_xid (output_info->modes[m]);
572 if (m < output_info->npreferred)
574 else if (output_info->mm_height)
575 dist = (1000 * DisplayHeight(dpy, screen) / DisplayHeightMM(dpy, screen) -
576 1000 * mode_info->height / output_info->mm_height);
578 dist = DisplayHeight(dpy, screen) - mode_info->height;
580 if (dist < 0) dist = -dist;
581 if (!best || dist < bestDist)
591 output_can_use_crtc (output_t *output, crtc_t *crtc)
593 XRROutputInfo *output_info = output->output_info;
596 for (c = 0; c < output_info->ncrtc; c++)
597 if (output_info->crtcs[c] == crtc->crtc.xid)
603 output_can_use_mode (output_t *output, XRRModeInfo *mode)
605 XRROutputInfo *output_info = output->output_info;
608 for (m = 0; m < output_info->nmode; m++)
609 if (output_info->modes[m] == mode->id)
615 crtc_can_use_rotation (crtc_t *crtc, Rotation rotation)
617 Rotation rotations = crtc->crtc_info->rotations;
618 Rotation dir = rotation & (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270);
619 Rotation reflect = rotation & (RR_Reflect_X|RR_Reflect_Y);
620 if (((rotations & dir) != 0) && ((rotations & reflect) == reflect))
626 * Report only rotations that are supported by all crtcs
629 output_rotations (output_t *output)
632 Rotation rotation = RR_Rotate_0;
633 XRROutputInfo *output_info = output->output_info;
636 for (c = 0; c < output_info->ncrtc; c++)
638 crtc_t *crtc = find_crtc_by_xid (output_info->crtcs[c]);
642 rotation = crtc->crtc_info->rotations;
645 rotation &= crtc->crtc_info->rotations;
652 output_can_use_rotation (output_t *output, Rotation rotation)
654 XRROutputInfo *output_info = output->output_info;
657 /* make sure all of the crtcs can use this rotation.
658 * yes, this is not strictly necessary, but it is
659 * simpler,and we expect most drivers to either
660 * support rotation everywhere or nowhere
662 for (c = 0; c < output_info->ncrtc; c++)
664 crtc_t *crtc = find_crtc_by_xid (output_info->crtcs[c]);
665 if (crtc && !crtc_can_use_rotation (crtc, rotation))
672 set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
674 /* sanity check output info */
675 if (output_info->connection != RR_Disconnected && !output_info->nmode)
676 fatal ("Output %s is not disconnected but has no modes\n",
679 /* set output name and info */
680 if (!(output->output.kind & name_xid))
681 set_name_xid (&output->output, xid);
682 if (!(output->output.kind & name_string))
683 set_name_string (&output->output, output_info->name);
684 output->output_info = output_info;
686 /* set crtc name and info */
687 if (!(output->changes & changes_crtc))
688 set_name_xid (&output->crtc, output_info->crtc);
690 if (output->crtc.kind == name_xid && output->crtc.xid == None)
691 output->crtc_info = NULL;
694 output->crtc_info = find_crtc (&output->crtc);
695 if (!output->crtc_info)
697 if (output->crtc.kind & name_xid)
698 fatal ("cannot find crtc 0x%x\n", output->crtc.xid);
699 if (output->crtc.kind & name_index)
700 fatal ("cannot find crtc %d\n", output->crtc.index);
702 if (!output_can_use_crtc (output, output->crtc_info))
703 fatal ("output %s cannot use crtc 0x%x\n", output->output.string,
704 output->crtc_info->crtc.xid);
707 /* set mode name and info */
708 if (!(output->changes & changes_mode))
710 if (output->crtc_info)
711 set_name_xid (&output->mode, output->crtc_info->crtc_info->mode);
713 set_name_xid (&output->mode, None);
714 if (output->mode.xid)
716 output->mode_info = find_mode_by_xid (output->mode.xid);
717 if (!output->mode_info)
718 fatal ("server did not report mode 0x%x for output %s\n",
719 output->mode.xid, output->output.string);
722 output->mode_info = NULL;
724 else if (output->mode.kind == name_xid && output->mode.xid == None)
725 output->mode_info = NULL;
728 if (output->mode.kind == name_preferred)
729 output->mode_info = preferred_mode (output);
731 output->mode_info = find_mode_for_output (output, &output->mode);
732 if (!output->mode_info)
734 if (output->mode.kind & name_preferred)
735 fatal ("cannot find preferred mode\n");
736 if (output->mode.kind & name_string)
737 fatal ("cannot find mode %s\n", output->mode.string);
738 if (output->mode.kind & name_xid)
739 fatal ("cannot find mode 0x%x\n", output->mode.xid);
741 if (!output_can_use_mode (output, output->mode_info))
742 fatal ("output %s cannot use mode %s\n", output->output.string,
743 output->mode_info->name);
747 if (!(output->changes & changes_position))
749 if (output->crtc_info)
751 output->x = output->crtc_info->crtc_info->x;
752 output->y = output->crtc_info->crtc_info->y;
762 if (!(output->changes & changes_rotation))
764 output->rotation &= ~0xf;
765 if (output->crtc_info)
766 output->rotation |= (output->crtc_info->crtc_info->rotation & 0xf);
768 output->rotation = RR_Rotate_0;
770 if (!(output->changes & changes_reflection))
772 output->rotation &= ~(RR_Reflect_X|RR_Reflect_Y);
773 if (output->crtc_info)
774 output->rotation |= (output->crtc_info->crtc_info->rotation &
775 (RR_Reflect_X|RR_Reflect_Y));
777 if (!output_can_use_rotation (output, output->rotation))
778 fatal ("output %s cannot use rotation \"%s\" reflection \"%s\"\n",
779 output->output.string,
780 rotation_name (output->rotation),
781 reflection_name (output->rotation));
788 fatal ("Server RandR version before 1.2\n");
790 XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight,
791 &maxWidth, &maxHeight);
793 res = XRRGetScreenResources (dpy, root);
794 if (!res) fatal ("could not get screen resources");
802 num_crtcs = res->ncrtc;
803 crtcs = calloc (num_crtcs, sizeof (crtc_t));
804 if (!crtcs) fatal ("out of memory");
806 for (c = 0; c < res->ncrtc; c++)
808 XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]);
809 set_name_xid (&crtcs[c].crtc, res->crtcs[c]);
810 set_name_index (&crtcs[c].crtc, c);
811 if (!crtc_info) fatal ("could not get crtc 0x%x information", res->crtcs[c]);
812 crtcs[c].crtc_info = crtc_info;
813 if (crtc_info->mode == None)
815 crtcs[c].mode_info = NULL;
818 crtcs[c].rotation = RR_Rotate_0;
824 crtc_add_output (crtc_t *crtc, output_t *output)
827 crtc->outputs = realloc (crtc->outputs, (crtc->noutput + 1) * sizeof (output_t *));
830 crtc->outputs = malloc (sizeof (output_t *));
833 crtc->rotation = output->rotation;
834 crtc->mode_info = output->mode_info;
836 if (!crtc->outputs) fatal ("out of memory");
837 crtc->outputs[crtc->noutput++] = output;
845 for (output = outputs; output; output = output->next)
847 if (!output->mode_info) continue;
848 crtc_add_output (output->crtc_info, output);
853 crtc_disable (crtc_t *crtc)
855 XRRCrtcInfo *crtc_info = crtc->crtc_info;
858 printf ("crtc %d: disable\n", crtc->crtc.index);
861 return RRSetConfigSuccess;
862 return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
863 0, 0, None, RR_Rotate_0, NULL, 0);
867 crtc_revert (crtc_t *crtc)
869 XRRCrtcInfo *crtc_info = crtc->crtc_info;
872 printf ("crtc %d: revert\n", crtc->crtc.index);
875 return RRSetConfigSuccess;
876 return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
877 crtc_info->x, crtc_info->y,
878 crtc_info->mode, crtc_info->rotation,
879 crtc_info->outputs, crtc_info->noutput);
883 crtc_apply (crtc_t *crtc)
885 RROutput *rr_outputs;
890 if (!crtc->changing || !crtc->mode_info)
891 return RRSetConfigSuccess;
893 rr_outputs = calloc (crtc->noutput, sizeof (RROutput));
896 for (o = 0; o < crtc->noutput; o++)
897 rr_outputs[o] = crtc->outputs[o]->output.xid;
898 mode = crtc->mode_info->id;
900 printf ("crtc %d: %12s %6.1f +%d+%d", crtc->crtc.index,
901 crtc->mode_info->name, mode_refresh (crtc->mode_info),
903 for (o = 0; o < crtc->noutput; o++)
904 printf (" \"%s\"", crtc->outputs[o]->output.string);
909 s = RRSetConfigSuccess;
911 s = XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
912 crtc->x, crtc->y, mode, crtc->rotation,
913 rr_outputs, crtc->noutput);
922 printf ("screen %d: revert\n");
926 XRRSetScreenSize (dpy, root,
927 DisplayWidth (dpy, screen),
928 DisplayHeight (dpy, screen),
929 DisplayWidthMM (dpy, screen),
930 DisplayHeightMM (dpy, screen));
936 if (fb_width == DisplayWidth (dpy, screen) &&
937 fb_height == DisplayHeight (dpy, screen) &&
938 fb_width_mm == DisplayWidthMM (dpy, screen) &&
939 fb_height_mm == DisplayHeightMM (dpy, screen))
944 printf ("screen %d: %dx%d %dx%d mm %6.2fdpi\n", screen,
945 fb_width, fb_height, fb_width_mm, fb_height_mm, dpi);
948 XRRSetScreenSize (dpy, root, fb_width, fb_height,
949 fb_width_mm, fb_height_mm);
957 /* first disable all crtcs */
958 for (c = 0; c < res->ncrtc; c++)
959 crtc_disable (&crtcs[c]);
960 /* next reset screen size */
962 /* now restore all crtcs */
963 for (c = 0; c < res->ncrtc; c++)
964 crtc_revert (&crtcs[c]);
968 * uh-oh, something bad happened in the middle of changing
969 * the configuration. Revert to the previous configuration
973 panic (Status s, crtc_t *crtc)
975 int c = crtc->crtc.index;
979 case RRSetConfigSuccess: message = "succeeded"; break;
980 case BadAlloc: message = "out of memory"; break;
981 case RRSetConfigFailed: message = "failed"; break;
982 case RRSetConfigInvalidConfigTime: message = "invalid config time"; break;
983 case RRSetConfigInvalidTime: message = "invalid time"; break;
984 default: message = "unknown failure"; break;
987 fprintf (stderr, "%s: Configure crtc %d %s\n", program_name, c, message);
999 * Turn off any crtcs which are to be disabled or which are
1000 * larger than the target size
1002 for (c = 0; c < res->ncrtc; c++)
1004 crtc_t *crtc = &crtcs[c];
1005 XRRCrtcInfo *crtc_info = crtc->crtc_info;
1007 /* if this crtc is already disabled, skip it */
1008 if (crtc_info->mode == None)
1012 * If this crtc is to be left enabled, make
1013 * sure the old size fits then new screen
1015 if (crtc->mode_info)
1017 XRRModeInfo *old_mode = find_mode_by_xid (crtc_info->mode);
1021 panic (RRSetConfigFailed, crtc);
1023 /* old position and size information */
1026 w = mode_width (old_mode, crtc_info->rotation);
1027 h = mode_height (old_mode, crtc_info->rotation);
1029 /* if it fits, skip it */
1030 if (x + w <= fb_width && y + h <= fb_height)
1032 crtc->changing = True;
1034 s = crtc_disable (crtc);
1035 if (s != RRSetConfigSuccess)
1040 * Hold the server grabbed while messing with
1041 * the screen so that apps which notice the resize
1042 * event and ask for xinerama information from the server
1043 * receive up-to-date information
1048 * Set the screen size
1056 for (c = 0; c < res->ncrtc; c++)
1058 crtc_t *crtc = &crtcs[c];
1060 s = crtc_apply (crtc);
1061 if (s != RRSetConfigSuccess)
1065 * Release the server grab and let all clients
1066 * respond to the updated state
1068 XUngrabServer (dpy);
1072 * Use current output state to complete the output list
1079 for (o = 0; o < res->noutput; o++)
1081 XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]);
1084 if (!output_info) fatal ("could not get output 0x%x information", res->outputs[o]);
1085 set_name_xid (&output_name, res->outputs[o]);
1086 set_name_index (&output_name, o);
1087 set_name_string (&output_name, output_info->name);
1088 output = find_output (&output_name);
1091 output = add_output ();
1092 set_name_all (&output->output, &output_name);
1094 * When global --automatic mode is set, turn on connected but off
1095 * outputs, turn off disconnected but on outputs
1099 switch (output_info->connection) {
1101 if (!output_info->crtc) {
1102 output->changes |= changes_automatic;
1103 output->automatic = True;
1106 case RR_Disconnected:
1107 if (output_info->crtc)
1109 output->changes |= changes_automatic;
1110 output->automatic = True;
1118 * Automatic mode -- track connection state and enable/disable outputs
1121 if (output->automatic)
1123 switch (output_info->connection) {
1125 case RR_UnknownConnection:
1126 if ((!(output->changes & changes_mode)))
1128 set_name_preferred (&output->mode);
1129 output->changes |= changes_mode;
1132 case RR_Disconnected:
1133 if ((!(output->changes & changes_mode)))
1135 set_name_xid (&output->mode, None);
1136 set_name_xid (&output->crtc, None);
1137 output->changes |= changes_mode;
1138 output->changes |= changes_crtc;
1144 set_output_info (output, res->outputs[o], output_info);
1149 mark_changing_crtcs (void)
1153 for (c = 0; c < num_crtcs; c++)
1155 crtc_t *crtc = &crtcs[c];
1159 /* walk old output list (to catch disables) */
1160 for (o = 0; o < crtc->crtc_info->noutput; o++)
1162 output = find_output_by_xid (crtc->crtc_info->outputs[o]);
1163 if (!output) fatal ("cannot find output 0x%x\n",
1164 crtc->crtc_info->outputs[o]);
1165 if (output->changes)
1166 crtc->changing = True;
1168 /* walk new output list */
1169 for (o = 0; o < crtc->noutput; o++)
1171 output = crtc->outputs[o];
1172 if (output->changes)
1173 crtc->changing = True;
1179 find_crtc_for_output (output_t *output)
1183 for (c = 0; c < output->output_info->ncrtc; c++)
1188 crtc = find_crtc_by_xid (output->output_info->crtcs[c]);
1189 if (!crtc) fatal ("cannot find crtc 0x%x\n", output->output_info->crtcs[c]);
1191 /* make sure all of the outputs currently connected can share */
1192 for (o = 0; o < crtc->noutput; o++)
1194 for (l = 0; l < output->output_info->nclone; l++)
1195 if (output->output_info->clones[l] == crtc->outputs[o]->output.xid)
1197 if (l != output->output_info->nclone) break;
1199 if (o != crtc->noutput) continue;
1203 /* make sure the state matches */
1204 if (crtc->mode_info != output->mode_info) continue;
1205 if (crtc->x != output->x) continue;
1206 if (crtc->y != output->y) continue;
1207 if (crtc->rotation != output->rotation) continue;
1215 set_positions (void)
1226 for (output = outputs; output; output = output->next)
1229 name_t relation_name;
1231 if (!(output->changes & changes_relation)) continue;
1233 init_name (&relation_name);
1234 set_name_string (&relation_name, output->relative_to);
1235 relation = find_output (&relation_name);
1236 if (!relation) fatal ("cannot find output \"%s\"\n", output->relative_to);
1238 if (relation->mode_info == NULL)
1242 output->changes |= changes_position;
1247 * Make sure the dependent object has been set in place
1249 if ((relation->changes & changes_relation) &&
1250 !(relation->changes & changes_position))
1256 switch (output->relation) {
1258 output->y = relation->y;
1259 output->x = relation->x - mode_width (output->mode_info, output->rotation);
1262 output->y = relation->y;
1263 output->x = relation->x + mode_width (relation->mode_info, relation->rotation);
1266 output->x = relation->x;
1267 output->y = relation->y - mode_height (output->mode_info, output->rotation);
1270 output->x = relation->x;
1271 output->y = relation->y + mode_height (relation->mode_info, relation->rotation);
1274 output->changes |= changes_position;
1280 fatal ("loop in relative position specifications\n");
1284 * Now normalize positions so the upper left corner of all outputs is at 0,0
1288 for (output = outputs; output; output = output->next)
1290 if (output->mode_info == NULL) continue;
1292 if (output->x < min_x) min_x = output->x;
1293 if (output->y < min_y) min_y = output->y;
1297 /* move all outputs */
1298 for (output = outputs; output; output = output->next)
1300 if (output->mode_info == NULL) continue;
1304 output->changes |= changes_position;
1310 set_screen_size (void)
1313 Bool fb_specified = fb_width != 0 && fb_height != 0;
1315 for (output = outputs; output; output = output->next)
1317 XRRModeInfo *mode_info = output->mode_info;
1320 if (!mode_info) continue;
1324 w = mode_width (mode_info, output->rotation);
1325 h = mode_height (mode_info, output->rotation);
1326 /* make sure output fits in specified size */
1329 if (x + w > fb_width || y + h > fb_height)
1330 fatal ("specified screen %dx%d not large enough for output %s (%dx%d+%d+%d)\n",
1331 fb_width, fb_height, output->output.string, w, h, x, y);
1333 /* fit fb to output */
1336 if (x + w > fb_width) fb_width = x + w;
1337 if (y + h > fb_height) fb_height = y + h;
1341 if (fb_width > maxWidth || fb_height > maxHeight)
1342 fatal ("screen cannot be larger than %dx%d (desired size %dx%d)\n",
1343 maxWidth, maxHeight, fb_width, fb_height);
1346 if (fb_width < minWidth || fb_height < minHeight)
1347 fatal ("screen must be at least %dx%d\n", minWidth, minHeight);
1351 if (fb_width < minWidth) fb_width = minWidth;
1352 if (fb_height < minHeight) fb_height = minHeight;
1359 main (int argc, char **argv)
1361 XRRScreenSize *sizes;
1362 XRRScreenConfiguration *sc;
1366 Status status = RRSetConfigFailed;
1369 Rotation rotation, current_rotation, rotations;
1371 XRRScreenChangeNotifyEvent *sce;
1372 char *display_name = NULL;
1374 SizeID current_size;
1380 Bool version = False;
1381 int event_base, error_base;
1383 int width = 0, height = 0;
1384 Bool have_pixel_size = False;
1387 output_t *output = NULL;
1389 policy_t policy = clone;
1390 Bool setit_1_2 = False;
1391 Bool query_1_2 = False;
1392 Bool query_1 = False;
1396 program_name = argv[0];
1397 if (argc == 1) query = True;
1398 for (i = 1; i < argc; i++) {
1399 if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
1400 if (++i>=argc) usage ();
1401 display_name = argv[i];
1404 if (!strcmp("-help", argv[i])) {
1408 if (!strcmp ("--verbose", argv[i])) {
1412 if (!strcmp ("--dryrun", argv[i])) {
1418 if (!strcmp ("-s", argv[i]) || !strcmp ("--size", argv[i])) {
1419 if (++i>=argc) usage ();
1420 if (sscanf (argv[i], "%dx%d", &width, &height) == 2)
1421 have_pixel_size = True;
1423 size = atoi (argv[i]);
1424 if (size < 0) usage();
1430 if (!strcmp ("-r", argv[i]) ||
1431 !strcmp ("--rate", argv[i]) ||
1432 !strcmp ("--refresh", argv[i]))
1434 if (++i>=argc) usage ();
1435 if (sscanf (argv[i], "%f", &rate) != 1)
1441 output->refresh = rate;
1442 output->changes |= changes_refresh;
1449 if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) {
1454 if (!strcmp ("-x", argv[i])) {
1455 reflection |= RR_Reflect_X;
1459 if (!strcmp ("-y", argv[i])) {
1460 reflection |= RR_Reflect_Y;
1464 if (!strcmp ("--screen", argv[i])) {
1465 if (++i>=argc) usage ();
1466 screen = atoi (argv[i]);
1467 if (screen < 0) usage();
1470 if (!strcmp ("-q", argv[i]) || !strcmp ("--query", argv[i])) {
1474 if (!strcmp ("-o", argv[i]) || !strcmp ("--orientation", argv[i])) {
1476 if (++i>=argc) usage ();
1477 dirind = strtol(argv[i], &endptr, 0);
1478 if (*endptr != '\0') {
1479 for (dirind = 0; dirind < 4; dirind++) {
1480 if (strcmp (direction[dirind], argv[i]) == 0) break;
1482 if ((dirind < 0) || (dirind > 3)) usage();
1489 if (!strcmp ("--prop", argv[i]) || !strcmp ("--properties", argv[i]))
1495 if (!strcmp ("--output", argv[i])) {
1496 if (++i >= argc) usage();
1497 output = add_output ();
1499 set_name (&output->output, argv[i], name_string|name_xid);
1504 if (!strcmp ("--crtc", argv[i])) {
1505 if (++i >= argc) usage();
1506 if (!output) usage();
1507 set_name (&output->crtc, argv[i], name_xid|name_index);
1508 output->changes |= changes_crtc;
1511 if (!strcmp ("--mode", argv[i])) {
1512 if (++i >= argc) usage();
1513 if (!output) usage();
1514 set_name (&output->mode, argv[i], name_string|name_xid);
1515 output->changes |= changes_mode;
1518 if (!strcmp ("--preferred", argv[i])) {
1519 if (!output) usage();
1520 set_name_preferred (&output->mode);
1521 output->changes |= changes_mode;
1524 if (!strcmp ("--pos", argv[i])) {
1525 if (++i>=argc) usage ();
1526 if (!output) usage();
1527 if (sscanf (argv[i], "%dx%d",
1528 &output->x, &output->y) != 2)
1530 output->changes |= changes_position;
1533 if (!strcmp ("--rotation", argv[i]) || !strcmp ("--rotate", argv[i])) {
1534 if (++i>=argc) usage ();
1535 if (!output) usage();
1536 for (dirind = 0; dirind < 4; dirind++) {
1537 if (strcmp (direction[dirind], argv[i]) == 0) break;
1541 output->rotation &= ~0xf;
1542 output->rotation |= 1 << dirind;
1543 output->changes |= changes_rotation;
1546 if (!strcmp ("--reflect", argv[i]) || !strcmp ("--reflection", argv[i])) {
1547 if (++i>=argc) usage ();
1548 if (!output) usage();
1549 for (dirind = 0; dirind < 4; dirind++) {
1550 if (strcmp (reflections[dirind], argv[i]) == 0) break;
1554 output->rotation &= ~(RR_Reflect_X|RR_Reflect_Y);
1555 output->rotation |= dirind * RR_Reflect_X;
1556 output->changes |= changes_reflection;
1559 if (!strcmp ("--left-of", argv[i])) {
1560 if (++i>=argc) usage ();
1561 if (!output) usage();
1562 output->relation = left_of;
1563 output->relative_to = argv[i];
1564 output->changes |= changes_relation;
1567 if (!strcmp ("--right-of", argv[i])) {
1568 if (++i>=argc) usage ();
1569 if (!output) usage();
1570 output->relation = right_of;
1571 output->relative_to = argv[i];
1572 output->changes |= changes_relation;
1575 if (!strcmp ("--above", argv[i])) {
1576 if (++i>=argc) usage ();
1577 if (!output) usage();
1578 output->relation = above;
1579 output->relative_to = argv[i];
1580 output->changes |= changes_relation;
1583 if (!strcmp ("--below", argv[i])) {
1584 if (++i>=argc) usage ();
1585 if (!output) usage();
1586 output->relation = below;
1587 output->relative_to = argv[i];
1588 output->changes |= changes_relation;
1591 if (!strcmp ("--off", argv[i])) {
1592 if (!output) usage();
1593 set_name_xid (&output->mode, None);
1594 set_name_xid (&output->crtc, None);
1595 output->changes |= changes_mode;
1598 if (!strcmp ("--fb", argv[i])) {
1599 if (++i>=argc) usage ();
1600 if (sscanf (argv[i], "%dx%d",
1601 &fb_width, &fb_height) != 2)
1606 if (!strcmp ("--fbmm", argv[i])) {
1607 if (++i>=argc) usage ();
1608 if (sscanf (argv[i], "%dx%d",
1609 &fb_width_mm, &fb_height_mm) != 2)
1614 if (!strcmp ("--dpi", argv[i])) {
1615 if (++i>=argc) usage ();
1616 if (sscanf (argv[i], "%f", &dpi) != 1)
1619 dpi_output = argv[i];
1624 if (!strcmp ("--clone", argv[i])) {
1629 if (!strcmp ("--extend", argv[i])) {
1634 if (!strcmp ("--auto", argv[i])) {
1637 output->automatic = True;
1638 output->changes |= changes_automatic;
1644 if (!strcmp ("--q12", argv[i]))
1649 if (!strcmp ("--q1", argv[i]))
1657 if (verbose) query = True;
1659 dpy = XOpenDisplay (display_name);
1662 fprintf (stderr, "Can't open display %s\n", XDisplayName(display_name));
1666 screen = DefaultScreen (dpy);
1667 if (screen >= ScreenCount (dpy)) {
1668 fprintf (stderr, "Invalid screen number %d (display has %d)\n",
1669 screen, ScreenCount (dpy));
1673 root = RootWindow (dpy, screen);
1676 if (!XRRQueryVersion (dpy, &major, &minor))
1678 fprintf (stderr, "RandR extension missing\n");
1681 if (major > 1 || (major == 1 && minor >= 2))
1686 XRROutputInfo *output_info;
1687 XRRCrtcInfo *crtc_info;
1688 XRRCrtcInfo *crtc_cur;
1689 XRRModeInfo *mode_info;
1690 RROutput *crtc_outputs;
1702 * Pick crtcs for any changing outputs that don't have one
1704 for (output = outputs; output; output = output->next)
1706 if (output->changes && output->mode_info && !output->crtc_info)
1708 output->crtc_info = find_crtc_for_output (output);
1709 if (!output->crtc_info)
1710 fatal ("cannot find crtc for output %s\n", output->output.string);
1715 * Assign outputs to crtcs
1720 * Mark changing crtcs
1722 mark_changing_crtcs ();
1725 * If an output was specified to track dpi, use it
1729 output_t *output = find_output_by_name (dpi_output);
1730 XRROutputInfo *output_info;
1731 XRRModeInfo *mode_info;
1733 fatal ("Cannot find output %s\n", dpi_output);
1734 output_info = output->output_info;
1735 mode_info = output->mode_info;
1736 if (output_info && mode_info && output_info->mm_height)
1739 * When this output covers the whole screen, just use
1740 * the known physical size
1742 if (fb_width == mode_info->width &&
1743 fb_height == mode_info->height)
1745 fb_width_mm = output_info->mm_width;
1746 fb_height_mm = output_info->mm_height;
1750 dpi = (25.4 * mode_info->height) / output_info->mm_height;
1756 * Compute physical screen size
1758 if (fb_width_mm == 0 || fb_height_mm == 0)
1760 if (fb_width != DisplayWidth (dpy, screen) ||
1761 fb_height != DisplayHeight (dpy, screen) || dpi != 0.0)
1764 dpi = (25.4 * DisplayHeight (dpy, screen)) / DisplayHeightMM(dpy, screen);
1766 fb_width_mm = (25.4 * fb_width) / dpi;
1767 fb_height_mm = (25.4 * fb_height) / dpi;
1771 fb_width_mm = DisplayWidthMM (dpy, screen);
1772 fb_height_mm = DisplayHeightMM (dpy, screen);
1777 * Now apply all of the changes
1784 if (query_1_2 || (query && has_1_2 && !query_1))
1792 printf ("Screen %d: minimum %d x %d, current %d x %d, maximum %d x %d\n",
1793 screen, minWidth, minHeight,
1794 DisplayWidth (dpy, screen), DisplayHeight(dpy, screen),
1795 maxWidth, maxHeight);
1797 for (output = outputs; output; output = output->next)
1799 XRROutputInfo *output_info = output->output_info;
1800 XRRModeInfo *mode = output->mode_info;
1804 Rotation rotations = output_rotations (output);
1806 printf ("%s %s", output_info->name, connection[output_info->connection]);
1809 printf (" %dx%d+%d+%d",
1810 mode_width (mode, output->rotation),
1811 mode_height (mode, output->rotation),
1812 output->x, output->y);
1813 if (output->rotation != RR_Rotate_0 || verbose)
1816 rotation_name (output->rotation));
1817 if (output->rotation & (RR_Reflect_X|RR_Reflect_Y))
1818 printf (" %s", reflection_name (output->rotation));
1821 if (rotations != RR_Rotate_0 || verbose)
1825 for (i = 0; i < 4; i ++) {
1826 if ((rotations >> i) & 1) {
1827 if (!first) printf (" "); first = False;
1828 printf("%s", direction[i]);
1832 if (rotations & RR_Reflect_X)
1834 if (!first) printf (" "); first = False;
1837 if (rotations & RR_Reflect_Y)
1839 if (!first) printf (" "); first = False;
1847 printf (" %dmm x %dmm",
1848 output_info->mm_width, output_info->mm_height);
1854 printf ("\tIdentifier: 0x%x\n", output->output.xid);
1855 printf ("\tTimestamp: %d\n", output_info->timestamp);
1856 printf ("\tSubpixel: %s\n", order[output_info->subpixel_order]);
1857 printf ("\tClones: ");
1858 for (j = 0; j < output_info->nclone; j++)
1860 output_t *clone = find_output_by_xid (output_info->clones[j]);
1862 if (clone) printf (" %s", clone->output.string);
1865 if (output->crtc_info)
1866 printf ("\tCRTC: %d\n", output->crtc_info->crtc.index);
1868 if (verbose || properties)
1870 props = XRRListOutputProperties (dpy, output->output.xid,
1872 for (j = 0; j < nprop; j++) {
1873 unsigned char *prop;
1875 unsigned long nitems, bytes_after;
1877 XRRPropertyInfo *propinfo;
1879 XRRGetOutputProperty (dpy, output->output.xid, props[j],
1880 0, 100, False, False,
1882 &actual_type, &actual_format,
1883 &nitems, &bytes_after, &prop);
1885 propinfo = XRRQueryOutputProperty(dpy, output->output.xid,
1888 if (actual_type == XA_INTEGER && actual_format == 8) {
1891 printf("\t%s:\n", XGetAtomName (dpy, props[j]));
1892 for (k = 0; k < nitems; k++) {
1895 printf("%02x", (unsigned char)prop[k]);
1899 } else if (actual_type == XA_INTEGER &&
1900 actual_format == 32)
1902 printf("\t%s: %d (0x%08x)",
1903 XGetAtomName (dpy, props[j]),
1906 if (propinfo->range && propinfo->num_values > 0) {
1907 printf(" range%s: ",
1908 (propinfo->num_values == 2) ? "" : "s");
1910 for (k = 0; k < propinfo->num_values / 2; k++)
1911 printf(" (%d,%d)", propinfo->values[k * 2],
1912 propinfo->values[k * 2 + 1]);
1916 } else if (actual_format == 8) {
1917 printf ("\t\t%s: %s%s\n", XGetAtomName (dpy, props[j]),
1918 prop, bytes_after ? "..." : "");
1920 printf ("\t\t%s: ????\n", XGetAtomName (dpy, props[j]));
1929 for (j = 0; j < output_info->nmode; j++)
1931 XRRModeInfo *mode = find_mode_by_xid (output_info->modes[j]);
1933 printf (" %s (0x%x) %6.1fMHz\n",
1934 mode->name, mode->id,
1935 (float)mode->dotClock / 1000000.0);
1936 printf (" h: width %4d start %4d end %4d total %4d skew %4d clock %6.1fKHz\n",
1937 mode->width, mode->hSyncStart, mode->hSyncEnd,
1938 mode->hTotal, mode->hSkew, mode_hsync (mode) / 1000);
1939 printf (" v: height %4d start %4d end %4d total %4d clock %6.1fHz\n",
1940 mode->height, mode->vSyncStart, mode->vSyncEnd, mode->vTotal,
1941 mode_refresh (mode));
1946 mode_shown = calloc (output_info->nmode, sizeof (Bool));
1947 if (!mode_shown) fatal ("out of memory\n");
1948 for (j = 0; j < output_info->nmode; j++)
1950 XRRModeInfo *jmode, *kmode;
1952 if (mode_shown[j]) continue;
1954 jmode = find_mode_by_xid (output_info->modes[j]);
1956 printf (" %-12s", jmode->name);
1957 for (k = j; k < output_info->nmode; k++)
1959 if (mode_shown[k]) continue;
1960 kmode = find_mode_by_xid (output_info->modes[k]);
1961 if (strcmp (jmode->name, kmode->name) != 0) continue;
1962 mode_shown[k] = True;
1963 printf (" %6.1f", mode_refresh (kmode));
1964 if (kmode == output->mode_info)
1968 if (k < output_info->npreferred)
1982 sc = XRRGetScreenInfo (dpy, root);
1987 current_size = XRRConfigCurrentConfiguration (sc, ¤t_rotation);
1989 sizes = XRRConfigSizes(sc, &nsize);
1991 if (have_pixel_size) {
1992 for (size = 0; size < nsize; size++)
1994 if (sizes[size].width == width && sizes[size].height == height)
1997 if (size >= nsize) {
1999 "Size %dx%d not found in available modes\n", width, height);
2004 size = current_size;
2008 for (rot = 0; rot < 4; rot++)
2009 if (1 << rot == (current_rotation & 0xf))
2013 current_rate = XRRConfigCurrentRate (sc);
2017 if (size == current_size)
2018 rate = current_rate;
2024 rates = XRRConfigRates (sc, size, &nrate);
2025 for (i = 0; i < nrate; i++)
2026 if (rate == rates[i])
2029 fprintf (stderr, "Rate %d not available for this size\n", rate);
2035 int major_version, minor_version;
2036 XRRQueryVersion (dpy, &major_version, &minor_version);
2037 printf("Server reports RandR version %d.%d\n",
2038 major_version, minor_version);
2042 printf(" SZ: Pixels Physical Refresh\n");
2043 for (i = 0; i < nsize; i++) {
2044 printf ("%c%-2d %5d x %-5d (%4dmm x%4dmm )",
2045 i == current_size ? '*' : ' ',
2046 i, sizes[i].width, sizes[i].height,
2047 sizes[i].mwidth, sizes[i].mheight);
2048 rates = XRRConfigRates (sc, i, &nrate);
2049 if (nrate) printf (" ");
2050 for (j = 0; j < nrate; j++)
2052 i == current_size && rates[j] == current_rate ? '*' : ' ',
2058 rotations = XRRConfigRotations(sc, ¤t_rotation);
2060 rotation = 1 << rot ;
2062 printf("Current rotation - %s\n",
2063 rotation_name (current_rotation));
2065 printf("Current reflection - %s\n",
2066 reflection_name (current_rotation));
2068 printf ("Rotations possible - ");
2069 for (i = 0; i < 4; i ++) {
2070 if ((rotations >> i) & 1) printf("%s ", direction[i]);
2074 printf ("Reflections possible - ");
2075 if (rotations & (RR_Reflect_X|RR_Reflect_Y))
2077 if (rotations & RR_Reflect_X) printf ("X Axis ");
2078 if (rotations & RR_Reflect_Y) printf ("Y Axis");
2086 printf("Setting size to %d, rotation to %s\n", size, direction[rot]);
2088 printf ("Setting reflection on ");
2091 if (reflection & RR_Reflect_X) printf ("X Axis ");
2092 if (reflection & RR_Reflect_Y) printf ("Y Axis");
2095 printf ("neither axis");
2098 if (reflection & RR_Reflect_X) printf("Setting reflection on X axis\n");
2100 if (reflection & RR_Reflect_Y) printf("Setting reflection on Y axis\n");
2103 /* we should test configureNotify on the root window */
2104 XSelectInput (dpy, root, StructureNotifyMask);
2106 if (setit && !dryrun) XRRSelectInput (dpy, root,
2107 RRScreenChangeNotifyMask);
2108 if (setit && !dryrun) status = XRRSetScreenConfigAndRate (dpy, sc,
2109 DefaultRootWindow (dpy),
2110 (SizeID) size, (Rotation) (rotation | reflection), rate, CurrentTime);
2112 XRRQueryExtension(dpy, &event_base, &error_base);
2114 if (setit && !dryrun && status == RRSetConfigFailed) {
2115 printf ("Failed to change the screen configuration!\n");
2119 if (verbose && setit && !dryrun) {
2120 if (status == RRSetConfigSuccess)
2124 XNextEvent(dpy, (XEvent *) &event);
2126 printf ("Event received, type = %d\n", event.type);
2127 /* update Xlib's knowledge of the event */
2128 XRRUpdateConfiguration (&event);
2129 if (event.type == ConfigureNotify)
2130 printf("Received ConfigureNotify Event!\n");
2132 switch (event.type - event_base) {
2133 case RRScreenChangeNotify:
2134 sce = (XRRScreenChangeNotifyEvent *) &event;
2136 printf("Got a screen change notify event!\n");
2137 printf(" window = %d\n root = %d\n size_index = %d\n rotation %d\n",
2138 (int) sce->window, (int) sce->root,
2139 sce->size_index, sce->rotation);
2140 printf(" timestamp = %ld, config_timestamp = %ld\n",
2141 sce->timestamp, sce->config_timestamp);
2142 printf(" Rotation = %x\n", sce->rotation);
2143 printf(" %d X %d pixels, %d X %d mm\n",
2144 sce->width, sce->height, sce->mwidth, sce->mheight);
2145 printf("Display width %d, height %d\n",
2146 DisplayWidth(dpy, screen), DisplayHeight(dpy, screen));
2147 printf("Display widthmm %d, heightmm %d\n",
2148 DisplayWidthMM(dpy, screen), DisplayHeightMM(dpy, screen));
2149 spo = sce->subpixel_order;
2150 if ((spo < 0) || (spo > 5))
2151 printf ("Unknown subpixel order, value = %d\n", spo);
2152 else printf ("new Subpixel rendering model is %s\n", order[spo]);
2155 if (event.type != ConfigureNotify)
2156 printf("unknown event received, type = %d!\n", event.type);
2161 XRRFreeScreenConfigInfo(sc);