464
469
resInfoX->canUseVMwareCtrlTopologySet = FALSE;
467
return resInfoX->canUseVMwareCtrlTopologySet;
472
return resInfoX->canUseVMwareCtrlTopologySet || resInfoX->canUseRandR12;
475
* Employs the RandR 1.2 extension to set a new display topology.
477
* @return TRUE if operation succeeded, FALSE otherwise.
481
RandR12_SetTopology(unsigned int ndisplays,
482
// IN: number of elements in topology
483
xXineramaScreenInfo *displays,
484
// IN: array of display geometries
486
// IN: total width of topology
488
// IN: total height of topology
490
ResolutionInfoX11Type *resInfoX = &resolutionInfoX11;
491
int minWidth, minHeight, maxWidth, maxHeight;
492
XRRScreenResources* xrrRes = NULL;
493
XRROutputInfo** xrrOutputs;
494
unsigned int numOutputs;
495
unsigned int* outputMap;
496
XRRCrtcInfo** xrrCrtcs;
497
XRRScreenConfiguration* xrrConfig = NULL;
498
XRRScreenSize* xrrSizes;
499
Rotation xrrCurRotation;
502
XRRModeInfo xrrModes[ndisplays];
503
char name[RR12_MODE_MAXLEN];
506
Bool success = FALSE;
508
if (!XRRGetScreenSizeRange(resInfoX->display, resInfoX->rootWindow,
509
&minWidth, &minHeight, &maxWidth, &maxHeight) ||
510
width < minWidth || height < minHeight ||
511
width > maxWidth || height > maxHeight) {
515
/* Grab the server for two reasons:
516
* - Avoid race conditions with other clients changing RandR configuration.
517
* - Make our changes appear as atomic as possible to other clients.
519
XGrabServer(resInfoX->display);
521
xrrRes = XRRGetScreenResources(resInfoX->display, resInfoX->rootWindow);
526
xrrCrtcs = Util_SafeCalloc(sizeof *xrrCrtcs, xrrRes->ncrtc);
527
xrrOutputs = Util_SafeCalloc(sizeof *xrrOutputs, xrrRes->noutput);
528
outputMap = Util_SafeCalloc(sizeof *outputMap, xrrRes->noutput);
530
/* RandR may enumerate outputs differently from the host. Apply the nth
531
* topology rectangle to the output called LVDS<n>.
533
for (i = 0; i < xrrRes->noutput; i++) {
538
for (i = 0; i < xrrRes->noutput; i++) {
541
xrrOutputs[i] = XRRGetOutputInfo(resInfoX->display, xrrRes,
544
if (!xrrOutputs[i]) {
548
if (sscanf(xrrOutputs[i]->name, RR12_OUTPUT_FORMAT, &num) != 1 ||
553
outputMap[num - 1] = i;
555
if (num > numOutputs) {
560
/* Disable any CRTCs which won't be used or wont't fit in new screen size. */
561
for (i = 0; i < xrrRes->ncrtc; i++) {
562
xrrCrtcs[i] = XRRGetCrtcInfo(resInfoX->display, xrrRes,
569
for (j = 0; j < numOutputs; j++) {
570
if (xrrOutputs[outputMap[j]]->crtc == xrrRes->crtcs[i]) {
575
if (xrrCrtcs[i]->mode == None ||
577
(xrrCrtcs[i]->x + xrrCrtcs[i]->width) <= width &&
578
(xrrCrtcs[i]->y + xrrCrtcs[i]->height) <= height)) {
582
if (XRRSetCrtcConfig(resInfoX->display, xrrRes, xrrRes->crtcs[i],
583
xrrCrtcs[i]->timestamp, 0, 0, None, RR_Rotate_0, NULL, 0)
589
/* Set new screen size. */
590
xrrConfig = XRRGetScreenInfo(resInfoX->display, resInfoX->rootWindow);
591
xrrSizes = XRRConfigSizes(xrrConfig, &xrrNumSizes);
592
currentSize = XRRConfigCurrentConfiguration(xrrConfig, &xrrCurRotation);
594
if (xrrSizes[currentSize].mheight > 0) {
595
dpi = MILLIS_PER_INCH * xrrSizes[currentSize].height / xrrSizes[currentSize].mheight;
598
dpi = RR12_DEFAULT_DPI;
601
dpi = RR12_DEFAULT_DPI;
604
XRRSetScreenSize(resInfoX->display, resInfoX->rootWindow, width, height,
605
(MILLIS_PER_INCH * width) / dpi,
606
(MILLIS_PER_INCH * height) / dpi);
608
/* Set new topology. */
609
for (i = 0; i < numOutputs; i++) {
610
memset(xrrModes + i, 0, sizeof xrrModes[0]);
612
xrrModes[i].width = displays[i].width;
613
xrrModes[i].height = displays[i].height;
615
/* Look for existing matching autofit mode. */
616
for (j = 0; j < i && !xrrModes[i].id; j++) {
617
if (xrrModes[j].id &&
618
xrrModes[j].width == displays[i].width &&
619
xrrModes[j].height == displays[i].height) {
620
xrrModes[i].id = xrrModes[j].id;
625
for (j = 0; j < xrrRes->nmode && !xrrModes[i].id; j++) {
628
if (sscanf(xrrRes->modes[j].name, RR12_MODE_FORMAT, &w, &h) == 2 &&
629
w == displays[i].width && h == displays[i].height) {
630
xrrModes[i].id = xrrRes->modes[j].id;
635
/* If no luck, create new autofit mode. */
636
if (!xrrModes[i].id) {
637
Str_Sprintf(name, sizeof name, RR12_MODE_FORMAT, displays[i].width,
639
xrrModes[i].name = name;
640
xrrModes[i].nameLength = strlen(xrrModes[i].name);
641
xrrModes[i].id = XRRCreateMode(resInfoX->display, resInfoX->rootWindow,
645
if (xrrModes[i].id == None) {
649
/* Set autofit mode. */
650
if (xrrOutputs[outputMap[i]]->crtc == None) {
651
xrrOutputs[outputMap[i]]->crtc = xrrOutputs[outputMap[i]]->crtcs[0];
654
for (j = 0; j < xrrOutputs[outputMap[i]]->nmode; j++) {
655
if (xrrModes[i].id == xrrOutputs[outputMap[i]]->modes[j]) {
659
if (j == xrrOutputs[outputMap[i]]->nmode) {
660
XRRAddOutputMode(resInfoX->display, xrrRes->outputs[outputMap[i]],
663
if (XRRSetCrtcConfig(resInfoX->display, xrrRes,
664
xrrOutputs[outputMap[i]]->crtc, xrrCrtcs[i]->timestamp,
665
displays[i].x_org, displays[i].y_org, xrrModes[i].id,
666
RR_Rotate_0, xrrRes->outputs + outputMap[i], 1)
672
/* Delete unused autofit modes. */
673
for (i = 0; i < xrrRes->nmode; i++) {
677
if (sscanf(xrrRes->modes[i].name, RR12_MODE_FORMAT, &w, &h) != 2) {
681
for (j = 0; j < xrrRes->noutput; j++) {
682
if (j < numOutputs &&
683
w == displays[j].width && h == displays[j].height) {
688
for (k = 0; k < xrrOutputs[outputMap[j]]->nmode; k++) {
689
if (xrrOutputs[outputMap[j]]->modes[k] == xrrRes->modes[i].id) {
690
XRRDeleteOutputMode(resInfoX->display,
691
xrrRes->outputs[outputMap[j]],
692
xrrOutputs[outputMap[j]]->modes[k]);
699
XRRDestroyMode(resInfoX->display, xrrRes->modes[i].id);
703
resInfoX->topologyDisplays = ndisplays;
704
resInfoX->topologyWidth = width;
705
resInfoX->topologyHeight = height;
710
XUngrabServer(resInfoX->display);
713
XRRFreeScreenConfigInfo(xrrConfig);
716
for (i = 0; i < xrrRes->noutput; i++) {
718
XRRFreeOutputInfo(xrrOutputs[i]);
721
for (i = 0; i < xrrRes->ncrtc; i++) {
723
XRRFreeCrtcInfo(xrrCrtcs[i]);
729
XRRFreeScreenResources(xrrRes);
735
#endif // ifndef NO_MULTIMON
739
477
* Given a width and height, find the biggest resolution that will "fit".
740
478
* This is called as a result of the resolution set request from the vmx.
743
481
* @param[in] height
744
483
* @return TRUE if we are able to set to the exact size requested, FALSE otherwise.