444
520
resInfoX->canUseVMwareCtrlTopologySet = FALSE;
448
523
return resInfoX->canUseVMwareCtrlTopologySet;
531
*-----------------------------------------------------------------------------
533
* RandR12_SetTopology --
535
* Employs the RandR 1.2 extension to set a new display topology.
538
* TRUE if operation succeeded, FALSE otherwise.
543
*-----------------------------------------------------------------------------
547
RandR12_SetTopology(unsigned int ndisplays,
548
// IN: number of elements in topology
549
xXineramaScreenInfo *displays,
550
// IN: array of display geometries
552
// IN: total width of topology
554
// IN: total height of topology
556
ResolutionInfoX11Type *resInfoX = &resolutionInfoX11;
557
int minWidth, minHeight, maxWidth, maxHeight;
558
XRRScreenResources* xrrRes = NULL;
559
XRROutputInfo** xrrOutputs;
560
unsigned int numOutputs;
561
unsigned int* outputMap;
562
XRRCrtcInfo** xrrCrtcs;
563
XRRScreenConfiguration* xrrConfig = NULL;
564
XRRScreenSize* xrrSizes;
565
Rotation xrrCurRotation;
568
XRRModeInfo xrrModes[ndisplays];
569
char name[RR12_MODE_MAXLEN];
572
Bool success = FALSE;
574
if (!XRRGetScreenSizeRange(resInfoX->display, resInfoX->rootWindow,
575
&minWidth, &minHeight, &maxWidth, &maxHeight) ||
576
width < minWidth || height < minHeight ||
577
width > maxWidth || height > maxHeight) {
581
/* Grab the server for two reasons:
582
* - Avoid race conditions with other clients changing RandR configuration.
583
* - Make our changes appear as atomic as possible to other clients.
585
XGrabServer(resInfoX->display);
587
xrrRes = XRRGetScreenResources(resInfoX->display, resInfoX->rootWindow);
592
xrrCrtcs = Util_SafeCalloc(sizeof *xrrCrtcs, xrrRes->ncrtc);
593
xrrOutputs = Util_SafeCalloc(sizeof *xrrOutputs, xrrRes->noutput);
594
outputMap = Util_SafeCalloc(sizeof *outputMap, xrrRes->noutput);
596
/* RandR may enumerate outputs differently from the host. Apply the nth
597
* topology rectangle to the output called LVDS<n>.
599
for (i = 0; i < xrrRes->noutput; i++) {
604
for (i = 0; i < xrrRes->noutput; i++) {
607
xrrOutputs[i] = XRRGetOutputInfo(resInfoX->display, xrrRes,
610
if (!xrrOutputs[i]) {
614
if (sscanf(xrrOutputs[i]->name, RR12_OUTPUT_FORMAT, &num) != 1 ||
619
outputMap[num - 1] = i;
621
if (num > numOutputs) {
626
/* Disable any CRTCs which won't be used or wont't fit in new screen size. */
627
for (i = 0; i < xrrRes->ncrtc; i++) {
628
xrrCrtcs[i] = XRRGetCrtcInfo(resInfoX->display, xrrRes,
635
for (j = 0; j < numOutputs; j++) {
636
if (xrrOutputs[outputMap[j]]->crtc == xrrRes->crtcs[i]) {
641
if (xrrCrtcs[i]->mode == None ||
643
(xrrCrtcs[i]->x + xrrCrtcs[i]->width) <= width &&
644
(xrrCrtcs[i]->y + xrrCrtcs[i]->height) <= height)) {
648
if (XRRSetCrtcConfig(resInfoX->display, xrrRes, xrrRes->crtcs[i],
649
xrrCrtcs[i]->timestamp, 0, 0, None, RR_Rotate_0, NULL, 0)
655
/* Set new screen size. */
656
xrrConfig = XRRGetScreenInfo(resInfoX->display, resInfoX->rootWindow);
657
xrrSizes = XRRConfigSizes(xrrConfig, &xrrNumSizes);
658
currentSize = XRRConfigCurrentConfiguration(xrrConfig, &xrrCurRotation);
660
if (xrrSizes[currentSize].mheight > 0) {
661
dpi = MILLIS_PER_INCH * xrrSizes[currentSize].height / xrrSizes[currentSize].mheight;
664
dpi = RR12_DEFAULT_DPI;
667
dpi = RR12_DEFAULT_DPI;
670
XRRSetScreenSize(resInfoX->display, resInfoX->rootWindow, width, height,
671
(MILLIS_PER_INCH * width) / dpi,
672
(MILLIS_PER_INCH * height) / dpi);
674
/* Set new topology. */
675
for (i = 0; i < numOutputs; i++) {
676
memset(xrrModes + i, 0, sizeof xrrModes[0]);
678
xrrModes[i].width = displays[i].width;
679
xrrModes[i].height = displays[i].height;
681
/* Look for existing matching autofit mode. */
682
for (j = 0; j < i && !xrrModes[i].id; j++) {
683
if (xrrModes[j].id &&
684
xrrModes[j].width == displays[i].width &&
685
xrrModes[j].height == displays[i].height) {
686
xrrModes[i].id = xrrModes[j].id;
691
for (j = 0; j < xrrRes->nmode && !xrrModes[i].id; j++) {
694
if (sscanf(xrrRes->modes[j].name, RR12_MODE_FORMAT, &w, &h) == 2 &&
695
w == displays[i].width && h == displays[i].height) {
696
xrrModes[i].id = xrrRes->modes[j].id;
701
/* If no luck, create new autofit mode. */
702
if (!xrrModes[i].id) {
703
sprintf(name, RR12_MODE_FORMAT, displays[i].width,
705
xrrModes[i].name = name;
706
xrrModes[i].nameLength = strlen(xrrModes[i].name);
707
xrrModes[i].id = XRRCreateMode(resInfoX->display, resInfoX->rootWindow,
711
if (xrrModes[i].id == None) {
715
/* Set autofit mode. */
716
if (xrrOutputs[outputMap[i]]->crtc == None) {
717
xrrOutputs[outputMap[i]]->crtc = xrrOutputs[outputMap[i]]->crtcs[0];
720
for (j = 0; j < xrrOutputs[outputMap[i]]->nmode; j++) {
721
if (xrrModes[i].id == xrrOutputs[outputMap[i]]->modes[j]) {
725
if (j == xrrOutputs[outputMap[i]]->nmode) {
726
XRRAddOutputMode(resInfoX->display, xrrRes->outputs[outputMap[i]],
729
if (XRRSetCrtcConfig(resInfoX->display, xrrRes,
730
xrrOutputs[outputMap[i]]->crtc, xrrCrtcs[i]->timestamp,
731
displays[i].x_org, displays[i].y_org, xrrModes[i].id,
732
RR_Rotate_0, xrrRes->outputs + outputMap[i], 1)
738
/* Delete unused autofit modes. */
739
for (i = 0; i < xrrRes->nmode; i++) {
743
if (sscanf(xrrRes->modes[i].name, RR12_MODE_FORMAT, &w, &h) != 2) {
747
for (j = 0; j < xrrRes->noutput; j++) {
748
if (j < numOutputs &&
749
w == displays[j].width && h == displays[j].height) {
754
for (k = 0; k < xrrOutputs[outputMap[j]]->nmode; k++) {
755
if (xrrOutputs[outputMap[j]]->modes[k] == xrrRes->modes[i].id) {
756
XRRDeleteOutputMode(resInfoX->display,
757
xrrRes->outputs[outputMap[j]],
758
xrrOutputs[outputMap[j]]->modes[k]);
765
XRRDestroyMode(resInfoX->display, xrrRes->modes[i].id);
769
resInfoX->topologyDisplays = ndisplays;
770
resInfoX->topologyWidth = width;
771
resInfoX->topologyHeight = height;
776
XUngrabServer(resInfoX->display);
779
XRRFreeScreenConfigInfo(xrrConfig);
782
for (i = 0; i < xrrRes->noutput; i++) {
784
XRRFreeOutputInfo(xrrOutputs[i]);
787
for (i = 0; i < xrrRes->ncrtc; i++) {
789
XRRFreeCrtcInfo(xrrCrtcs[i]);
795
XRRFreeScreenResources(xrrRes);
801
#endif // ifndef NO_MULTIMON
452
804
/*-----------------------------------------------------------------------------