Wed Jun 12 07:50:29 2013 UTC ()
revert revision 1.8; no longer necessary.


(mrg)
diff -r1.8 -r1.9 xsrc/external/mit/xrandr/dist/xrandr.c

cvs diff -r1.8 -r1.9 xsrc/external/mit/xrandr/dist/xrandr.c (switch to unified diff)

--- xsrc/external/mit/xrandr/dist/xrandr.c 2013/05/31 08:59:45 1.8
+++ xsrc/external/mit/xrandr/dist/xrandr.c 2013/06/12 07:50:29 1.9
@@ -528,1999 +528,1999 @@ mode_geometry (XRRModeInfo *mode_info, R @@ -528,1999 +528,1999 @@ mode_geometry (XRRModeInfo *mode_info, R
528 int height = mode_height (mode_info, rotation); 528 int height = mode_height (mode_info, rotation);
529 529
530 rect[0].x = 0; 530 rect[0].x = 0;
531 rect[0].y = 0; 531 rect[0].y = 0;
532 rect[1].x = width; 532 rect[1].x = width;
533 rect[1].y = 0; 533 rect[1].y = 0;
534 rect[2].x = width; 534 rect[2].x = width;
535 rect[2].y = height; 535 rect[2].y = height;
536 rect[3].x = 0; 536 rect[3].x = 0;
537 rect[3].y = height; 537 rect[3].y = height;
538 path_bounds (transform, rect, 4, bounds); 538 path_bounds (transform, rect, 4, bounds);
539} 539}
540 540
541/* v refresh frequency in Hz */ 541/* v refresh frequency in Hz */
542static double 542static double
543mode_refresh (XRRModeInfo *mode_info) 543mode_refresh (XRRModeInfo *mode_info)
544{ 544{
545 double rate; 545 double rate;
546 unsigned int vTotal = mode_info->vTotal; 546 unsigned int vTotal = mode_info->vTotal;
547 547
548 if (mode_info->modeFlags & RR_DoubleScan) { 548 if (mode_info->modeFlags & RR_DoubleScan) {
549 /* doublescan doubles the number of lines */ 549 /* doublescan doubles the number of lines */
550 vTotal *= 2; 550 vTotal *= 2;
551 } 551 }
552 552
553 if (mode_info->modeFlags & RR_Interlace) { 553 if (mode_info->modeFlags & RR_Interlace) {
554 /* interlace splits the frame into two fields */ 554 /* interlace splits the frame into two fields */
555 /* the field rate is what is typically reported by monitors */ 555 /* the field rate is what is typically reported by monitors */
556 vTotal /= 2; 556 vTotal /= 2;
557 } 557 }
558  558
559 if (mode_info->hTotal && vTotal) 559 if (mode_info->hTotal && vTotal)
560 rate = ((double) mode_info->dotClock / 560 rate = ((double) mode_info->dotClock /
561 ((double) mode_info->hTotal * (double) vTotal)); 561 ((double) mode_info->hTotal * (double) vTotal));
562 else 562 else
563 rate = 0; 563 rate = 0;
564 return rate; 564 return rate;
565} 565}
566 566
567/* h sync frequency in Hz */ 567/* h sync frequency in Hz */
568static double 568static double
569mode_hsync (XRRModeInfo *mode_info) 569mode_hsync (XRRModeInfo *mode_info)
570{ 570{
571 double rate; 571 double rate;
572  572
573 if (mode_info->hTotal) 573 if (mode_info->hTotal)
574 rate = (double) mode_info->dotClock / (double) mode_info->hTotal; 574 rate = (double) mode_info->dotClock / (double) mode_info->hTotal;
575 else 575 else
576 rate = 0; 576 rate = 0;
577 return rate; 577 return rate;
578} 578}
579 579
580static void 580static void
581init_name (name_t *name) 581init_name (name_t *name)
582{ 582{
583 name->kind = name_none; 583 name->kind = name_none;
584} 584}
585 585
586static void 586static void
587set_name_string (name_t *name, char *string) 587set_name_string (name_t *name, char *string)
588{ 588{
589 name->kind |= name_string; 589 name->kind |= name_string;
590 name->string = string; 590 name->string = string;
591} 591}
592 592
593static void 593static void
594set_name_xid (name_t *name, XID xid) 594set_name_xid (name_t *name, XID xid)
595{ 595{
596 name->kind |= name_xid; 596 name->kind |= name_xid;
597 name->xid = xid; 597 name->xid = xid;
598} 598}
599 599
600static void 600static void
601set_name_index (name_t *name, int idx) 601set_name_index (name_t *name, int idx)
602{ 602{
603 name->kind |= name_index; 603 name->kind |= name_index;
604 name->index = idx; 604 name->index = idx;
605} 605}
606 606
607static void 607static void
608set_name_preferred (name_t *name) 608set_name_preferred (name_t *name)
609{ 609{
610 name->kind |= name_preferred; 610 name->kind |= name_preferred;
611} 611}
612 612
613static void 613static void
614set_name_all (name_t *name, name_t *old) 614set_name_all (name_t *name, name_t *old)
615{ 615{
616 if (old->kind & name_xid) 616 if (old->kind & name_xid)
617 name->xid = old->xid; 617 name->xid = old->xid;
618 if (old->kind & name_string) 618 if (old->kind & name_string)
619 name->string = old->string; 619 name->string = old->string;
620 if (old->kind & name_index) 620 if (old->kind & name_index)
621 name->index = old->index; 621 name->index = old->index;
622 name->kind |= old->kind; 622 name->kind |= old->kind;
623} 623}
624 624
625static void 625static void
626set_name (name_t *name, char *string, name_kind_t valid) 626set_name (name_t *name, char *string, name_kind_t valid)
627{ 627{
628 unsigned int xid; /* don't make it XID (which is unsigned long): 628 unsigned int xid; /* don't make it XID (which is unsigned long):
629 scanf() takes unsigned int */ 629 scanf() takes unsigned int */
630 int idx; 630 int idx;
631 631
632 if ((valid & name_xid) && sscanf (string, "0x%x", &xid) == 1) 632 if ((valid & name_xid) && sscanf (string, "0x%x", &xid) == 1)
633 set_name_xid (name, xid); 633 set_name_xid (name, xid);
634 else if ((valid & name_index) && sscanf (string, "%d", &idx) == 1) 634 else if ((valid & name_index) && sscanf (string, "%d", &idx) == 1)
635 set_name_index (name, idx); 635 set_name_index (name, idx);
636 else if (valid & name_string) 636 else if (valid & name_string)
637 set_name_string (name, string); 637 set_name_string (name, string);
638 else 638 else
639 argerr ("invalid name '%s'\n", string); 639 argerr ("invalid name '%s'\n", string);
640} 640}
641 641
642static int 642static int
643print_name (const name_t *name) 643print_name (const name_t *name)
644{ 644{
645 name_kind_t kind = name->kind; 645 name_kind_t kind = name->kind;
646 646
647 if ((kind & name_xid)) return printf("XID 0x%x", (unsigned int)name->xid); 647 if ((kind & name_xid)) return printf("XID 0x%x", (unsigned int)name->xid);
648 else if ((kind & name_string)) return printf("name %s", name->string); 648 else if ((kind & name_string)) return printf("name %s", name->string);
649 else if ((kind & name_index)) return printf("index %d", name->index); 649 else if ((kind & name_index)) return printf("index %d", name->index);
650 else return printf("unknown name"); 650 else return printf("unknown name");
651} 651}
652 652
653static void 653static void
654init_transform (transform_t *transform) 654init_transform (transform_t *transform)
655{ 655{
656 int x; 656 int x;
657 memset (&transform->transform, '\0', sizeof (transform->transform)); 657 memset (&transform->transform, '\0', sizeof (transform->transform));
658 for (x = 0; x < 3; x++) 658 for (x = 0; x < 3; x++)
659 transform->transform.matrix[x][x] = XDoubleToFixed (1.0); 659 transform->transform.matrix[x][x] = XDoubleToFixed (1.0);
660 transform->filter = ""; 660 transform->filter = "";
661 transform->nparams = 0; 661 transform->nparams = 0;
662 transform->params = NULL; 662 transform->params = NULL;
663} 663}
664 664
665static void 665static void
666set_transform (transform_t *dest, 666set_transform (transform_t *dest,
667 XTransform *transform, 667 XTransform *transform,
668 const char *filter, 668 const char *filter,
669 XFixed *params, 669 XFixed *params,
670 int nparams) 670 int nparams)
671{ 671{
672 dest->transform = *transform; 672 dest->transform = *transform;
673 /* note: this string is leaked */ 673 /* note: this string is leaked */
674 dest->filter = strdup (filter); 674 dest->filter = strdup (filter);
675 dest->nparams = nparams; 675 dest->nparams = nparams;
676 dest->params = malloc (nparams * sizeof (XFixed)); 676 dest->params = malloc (nparams * sizeof (XFixed));
677 memcpy (dest->params, params, nparams * sizeof (XFixed)); 677 memcpy (dest->params, params, nparams * sizeof (XFixed));
678} 678}
679 679
680static void 680static void
681copy_transform (transform_t *dest, transform_t *src) 681copy_transform (transform_t *dest, transform_t *src)
682{ 682{
683 set_transform (dest, &src->transform, 683 set_transform (dest, &src->transform,
684 src->filter, src->params, src->nparams); 684 src->filter, src->params, src->nparams);
685} 685}
686 686
687static Bool 687static Bool
688equal_transform (transform_t *a, transform_t *b) 688equal_transform (transform_t *a, transform_t *b)
689{ 689{
690 if (memcmp (&a->transform, &b->transform, sizeof (XTransform)) != 0) 690 if (memcmp (&a->transform, &b->transform, sizeof (XTransform)) != 0)
691 return False; 691 return False;
692 if (strcmp (a->filter, b->filter) != 0) 692 if (strcmp (a->filter, b->filter) != 0)
693 return False; 693 return False;
694 if (a->nparams != b->nparams) 694 if (a->nparams != b->nparams)
695 return False; 695 return False;
696 if (memcmp (a->params, b->params, a->nparams * sizeof (XFixed)) != 0) 696 if (memcmp (a->params, b->params, a->nparams * sizeof (XFixed)) != 0)
697 return False; 697 return False;
698 return True; 698 return True;
699} 699}
700 700
701static output_t * 701static output_t *
702add_output (void) 702add_output (void)
703{ 703{
704 output_t *output = calloc (1, sizeof (output_t)); 704 output_t *output = calloc (1, sizeof (output_t));
705 705
706 if (!output) 706 if (!output)
707 fatal ("out of memory\n"); 707 fatal ("out of memory\n");
708 output->next = NULL; 708 output->next = NULL;
709 output->found = False; 709 output->found = False;
710 output->brightness = 1.0; 710 output->brightness = 1.0;
711 *all_outputs_tail = output; 711 *all_outputs_tail = output;
712 all_outputs_tail = &output->next; 712 all_outputs_tail = &output->next;
713 return output; 713 return output;
714} 714}
715 715
716static output_t * 716static output_t *
717find_output (name_t *name) 717find_output (name_t *name)
718{ 718{
719 output_t *output; 719 output_t *output;
720 720
721 for (output = all_outputs; output; output = output->next) 721 for (output = all_outputs; output; output = output->next)
722 { 722 {
723 name_kind_t common = name->kind & output->output.kind; 723 name_kind_t common = name->kind & output->output.kind;
724  724
725 if ((common & name_xid) && name->xid == output->output.xid) 725 if ((common & name_xid) && name->xid == output->output.xid)
726 break; 726 break;
727 if ((common & name_string) && !strcmp (name->string, output->output.string)) 727 if ((common & name_string) && !strcmp (name->string, output->output.string))
728 break; 728 break;
729 if ((common & name_index) && name->index == output->output.index) 729 if ((common & name_index) && name->index == output->output.index)
730 break; 730 break;
731 } 731 }
732 return output; 732 return output;
733} 733}
734 734
735static output_t * 735static output_t *
736find_output_by_xid (RROutput output) 736find_output_by_xid (RROutput output)
737{ 737{
738 name_t output_name; 738 name_t output_name;
739 739
740 init_name (&output_name); 740 init_name (&output_name);
741 set_name_xid (&output_name, output); 741 set_name_xid (&output_name, output);
742 return find_output (&output_name); 742 return find_output (&output_name);
743} 743}
744 744
745static output_t * 745static output_t *
746find_output_by_name (char *name) 746find_output_by_name (char *name)
747{ 747{
748 name_t output_name; 748 name_t output_name;
749 749
750 init_name (&output_name); 750 init_name (&output_name);
751 set_name_string (&output_name, name); 751 set_name_string (&output_name, name);
752 return find_output (&output_name); 752 return find_output (&output_name);
753} 753}
754 754
755static crtc_t * 755static crtc_t *
756find_crtc (name_t *name) 756find_crtc (name_t *name)
757{ 757{
758 int c; 758 int c;
759 crtc_t *crtc = NULL; 759 crtc_t *crtc = NULL;
760 760
761 for (c = 0; c < num_crtcs; c++) 761 for (c = 0; c < num_crtcs; c++)
762 { 762 {
763 name_kind_t common; 763 name_kind_t common;
764  764
765 crtc = &crtcs[c]; 765 crtc = &crtcs[c];
766 common = name->kind & crtc->crtc.kind; 766 common = name->kind & crtc->crtc.kind;
767  767
768 if ((common & name_xid) && name->xid == crtc->crtc.xid) 768 if ((common & name_xid) && name->xid == crtc->crtc.xid)
769 break; 769 break;
770 if ((common & name_string) && !strcmp (name->string, crtc->crtc.string)) 770 if ((common & name_string) && !strcmp (name->string, crtc->crtc.string))
771 break; 771 break;
772 if ((common & name_index) && name->index == crtc->crtc.index) 772 if ((common & name_index) && name->index == crtc->crtc.index)
773 break; 773 break;
774 crtc = NULL; 774 crtc = NULL;
775 } 775 }
776 return crtc; 776 return crtc;
777} 777}
778 778
779static crtc_t * 779static crtc_t *
780find_crtc_by_xid (RRCrtc crtc) 780find_crtc_by_xid (RRCrtc crtc)
781{ 781{
782 name_t crtc_name; 782 name_t crtc_name;
783 783
784 init_name (&crtc_name); 784 init_name (&crtc_name);
785 set_name_xid (&crtc_name, crtc); 785 set_name_xid (&crtc_name, crtc);
786 return find_crtc (&crtc_name); 786 return find_crtc (&crtc_name);
787} 787}
788 788
789static XRRModeInfo * 789static XRRModeInfo *
790find_mode (name_t *name, double refresh) 790find_mode (name_t *name, double refresh)
791{ 791{
792 int m; 792 int m;
793 XRRModeInfo *best = NULL; 793 XRRModeInfo *best = NULL;
794 double bestDist = 0; 794 double bestDist = 0;
795 795
796 for (m = 0; m < res->nmode; m++) 796 for (m = 0; m < res->nmode; m++)
797 { 797 {
798 XRRModeInfo *mode = &res->modes[m]; 798 XRRModeInfo *mode = &res->modes[m];
799 if ((name->kind & name_xid) && name->xid == mode->id) 799 if ((name->kind & name_xid) && name->xid == mode->id)
800 { 800 {
801 best = mode; 801 best = mode;
802 break; 802 break;
803 } 803 }
804 if ((name->kind & name_string) && !strcmp (name->string, mode->name)) 804 if ((name->kind & name_string) && !strcmp (name->string, mode->name))
805 { 805 {
806 double dist; 806 double dist;
807  807
808 if (refresh) 808 if (refresh)
809 dist = fabs (mode_refresh (mode) - refresh); 809 dist = fabs (mode_refresh (mode) - refresh);
810 else 810 else
811 dist = 0; 811 dist = 0;
812 if (!best || dist < bestDist) 812 if (!best || dist < bestDist)
813 { 813 {
814 bestDist = dist; 814 bestDist = dist;
815 best = mode; 815 best = mode;
816 } 816 }
817 } 817 }
818 } 818 }
819 return best; 819 return best;
820} 820}
821 821
822static XRRModeInfo * 822static XRRModeInfo *
823find_mode_by_xid (RRMode mode) 823find_mode_by_xid (RRMode mode)
824{ 824{
825 name_t mode_name; 825 name_t mode_name;
826 826
827 init_name (&mode_name); 827 init_name (&mode_name);
828 set_name_xid (&mode_name, mode); 828 set_name_xid (&mode_name, mode);
829 return find_mode (&mode_name, 0); 829 return find_mode (&mode_name, 0);
830} 830}
831 831
832#if 0 832#if 0
833static XRRModeInfo * 833static XRRModeInfo *
834find_mode_by_name (char *name) 834find_mode_by_name (char *name)
835{ 835{
836 name_t mode_name; 836 name_t mode_name;
837 init_name (&mode_name); 837 init_name (&mode_name);
838 set_name_string (&mode_name, name); 838 set_name_string (&mode_name, name);
839 return find_mode (&mode_name, 0); 839 return find_mode (&mode_name, 0);
840} 840}
841#endif 841#endif
842 842
843static 843static
844XRRModeInfo * 844XRRModeInfo *
845find_mode_for_output (output_t *output, name_t *name) 845find_mode_for_output (output_t *output, name_t *name)
846{ 846{
847 XRROutputInfo *output_info = output->output_info; 847 XRROutputInfo *output_info = output->output_info;
848 int m; 848 int m;
849 XRRModeInfo *best = NULL; 849 XRRModeInfo *best = NULL;
850 double bestDist = 0; 850 double bestDist = 0;
851 851
852 for (m = 0; m < output_info->nmode; m++) 852 for (m = 0; m < output_info->nmode; m++)
853 { 853 {
854 XRRModeInfo *mode; 854 XRRModeInfo *mode;
855 855
856 mode = find_mode_by_xid (output_info->modes[m]); 856 mode = find_mode_by_xid (output_info->modes[m]);
857 if (!mode) continue; 857 if (!mode) continue;
858 if ((name->kind & name_xid) && name->xid == mode->id) 858 if ((name->kind & name_xid) && name->xid == mode->id)
859 { 859 {
860 best = mode; 860 best = mode;
861 break; 861 break;
862 } 862 }
863 if ((name->kind & name_string) && !strcmp (name->string, mode->name)) 863 if ((name->kind & name_string) && !strcmp (name->string, mode->name))
864 { 864 {
865 double dist; 865 double dist;
866 866
867 /* Stay away from doublescan modes unless refresh rate is specified. */ 867 /* Stay away from doublescan modes unless refresh rate is specified. */
868 if (!output->refresh && (mode->modeFlags & RR_DoubleScan)) 868 if (!output->refresh && (mode->modeFlags & RR_DoubleScan))
869 continue; 869 continue;
870 870
871 if (output->refresh) 871 if (output->refresh)
872 dist = fabs (mode_refresh (mode) - output->refresh); 872 dist = fabs (mode_refresh (mode) - output->refresh);
873 else 873 else
874 dist = 0; 874 dist = 0;
875 if (!best || dist < bestDist) 875 if (!best || dist < bestDist)
876 { 876 {
877 bestDist = dist; 877 bestDist = dist;
878 best = mode; 878 best = mode;
879 } 879 }
880 } 880 }
881 } 881 }
882 return best; 882 return best;
883} 883}
884 884
885static XRRModeInfo * 885static XRRModeInfo *
886preferred_mode (output_t *output) 886preferred_mode (output_t *output)
887{ 887{
888 XRROutputInfo *output_info = output->output_info; 888 XRROutputInfo *output_info = output->output_info;
889 int m; 889 int m;
890 XRRModeInfo *best; 890 XRRModeInfo *best;
891 int bestDist; 891 int bestDist;
892  892
893 best = NULL; 893 best = NULL;
894 bestDist = 0; 894 bestDist = 0;
895 for (m = 0; m < output_info->nmode; m++) 895 for (m = 0; m < output_info->nmode; m++)
896 { 896 {
897 XRRModeInfo *mode_info = find_mode_by_xid (output_info->modes[m]); 897 XRRModeInfo *mode_info = find_mode_by_xid (output_info->modes[m]);
898 int dist; 898 int dist;
899  899
900 if (m < output_info->npreferred) 900 if (m < output_info->npreferred)
901 dist = 0; 901 dist = 0;
902 else if (output_info->mm_height) 902 else if (output_info->mm_height)
903 dist = (1000 * DisplayHeight(dpy, screen) / DisplayHeightMM(dpy, screen) - 903 dist = (1000 * DisplayHeight(dpy, screen) / DisplayHeightMM(dpy, screen) -
904 1000 * mode_info->height / output_info->mm_height); 904 1000 * mode_info->height / output_info->mm_height);
905 else 905 else
906 dist = DisplayHeight(dpy, screen) - mode_info->height; 906 dist = DisplayHeight(dpy, screen) - mode_info->height;
907 907
908 if (dist < 0) dist = -dist; 908 if (dist < 0) dist = -dist;
909 if (!best || dist < bestDist) 909 if (!best || dist < bestDist)
910 { 910 {
911 best = mode_info; 911 best = mode_info;
912 bestDist = dist; 912 bestDist = dist;
913 } 913 }
914 } 914 }
915 return best; 915 return best;
916} 916}
917 917
918static Bool 918static Bool
919output_can_use_crtc (output_t *output, crtc_t *crtc) 919output_can_use_crtc (output_t *output, crtc_t *crtc)
920{ 920{
921 XRROutputInfo *output_info = output->output_info; 921 XRROutputInfo *output_info = output->output_info;
922 int c; 922 int c;
923 923
924 for (c = 0; c < output_info->ncrtc; c++) 924 for (c = 0; c < output_info->ncrtc; c++)
925 if (output_info->crtcs[c] == crtc->crtc.xid) 925 if (output_info->crtcs[c] == crtc->crtc.xid)
926 return True; 926 return True;
927 return False; 927 return False;
928} 928}
929 929
930static Bool 930static Bool
931output_can_use_mode (output_t *output, XRRModeInfo *mode) 931output_can_use_mode (output_t *output, XRRModeInfo *mode)
932{ 932{
933 XRROutputInfo *output_info = output->output_info; 933 XRROutputInfo *output_info = output->output_info;
934 int m; 934 int m;
935 935
936 for (m = 0; m < output_info->nmode; m++) 936 for (m = 0; m < output_info->nmode; m++)
937 if (output_info->modes[m] == mode->id) 937 if (output_info->modes[m] == mode->id)
938 return True; 938 return True;
939 return False; 939 return False;
940} 940}
941 941
942static Bool 942static Bool
943crtc_can_use_rotation (crtc_t *crtc, Rotation rotation) 943crtc_can_use_rotation (crtc_t *crtc, Rotation rotation)
944{ 944{
945 Rotation rotations = crtc->crtc_info->rotations; 945 Rotation rotations = crtc->crtc_info->rotations;
946 Rotation dir = rotation & (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270); 946 Rotation dir = rotation & (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270);
947 Rotation reflect = rotation & (RR_Reflect_X|RR_Reflect_Y); 947 Rotation reflect = rotation & (RR_Reflect_X|RR_Reflect_Y);
948 if (((rotations & dir) != 0) && ((rotations & reflect) == reflect)) 948 if (((rotations & dir) != 0) && ((rotations & reflect) == reflect))
949 return True; 949 return True;
950 return False; 950 return False;
951} 951}
952 952
953#if 0 953#if 0
954static Bool 954static Bool
955crtc_can_use_transform (crtc_t *crtc, XTransform *transform) 955crtc_can_use_transform (crtc_t *crtc, XTransform *transform)
956{ 956{
957 int major, minor; 957 int major, minor;
958 958
959 XRRQueryVersion (dpy, &major, &minor); 959 XRRQueryVersion (dpy, &major, &minor);
960 if (major > 1 || (major == 1 && minor >= 3)) 960 if (major > 1 || (major == 1 && minor >= 3))
961 return True; 961 return True;
962 return False; 962 return False;
963} 963}
964#endif 964#endif
965 965
966/* 966/*
967 * Report only rotations that are supported by all crtcs 967 * Report only rotations that are supported by all crtcs
968 */ 968 */
969static Rotation 969static Rotation
970output_rotations (output_t *output) 970output_rotations (output_t *output)
971{ 971{
972 Bool found = False; 972 Bool found = False;
973 Rotation rotation = RR_Rotate_0; 973 Rotation rotation = RR_Rotate_0;
974 XRROutputInfo *output_info = output->output_info; 974 XRROutputInfo *output_info = output->output_info;
975 int c; 975 int c;
976  976
977 for (c = 0; c < output_info->ncrtc; c++) 977 for (c = 0; c < output_info->ncrtc; c++)
978 { 978 {
979 crtc_t *crtc = find_crtc_by_xid (output_info->crtcs[c]); 979 crtc_t *crtc = find_crtc_by_xid (output_info->crtcs[c]);
980 if (crtc) 980 if (crtc)
981 { 981 {
982 if (!found) { 982 if (!found) {
983 rotation = crtc->crtc_info->rotations; 983 rotation = crtc->crtc_info->rotations;
984 found = True; 984 found = True;
985 } else 985 } else
986 rotation &= crtc->crtc_info->rotations; 986 rotation &= crtc->crtc_info->rotations;
987 } 987 }
988 } 988 }
989 return rotation; 989 return rotation;
990} 990}
991 991
992static Bool 992static Bool
993output_can_use_rotation (output_t *output, Rotation rotation) 993output_can_use_rotation (output_t *output, Rotation rotation)
994{ 994{
995 XRROutputInfo *output_info = output->output_info; 995 XRROutputInfo *output_info = output->output_info;
996 int c; 996 int c;
997 997
998 /* make sure all of the crtcs can use this rotation. 998 /* make sure all of the crtcs can use this rotation.
999 * yes, this is not strictly necessary, but it is  999 * yes, this is not strictly necessary, but it is
1000 * simpler,and we expect most drivers to either 1000 * simpler,and we expect most drivers to either
1001 * support rotation everywhere or nowhere 1001 * support rotation everywhere or nowhere
1002 */ 1002 */
1003 for (c = 0; c < output_info->ncrtc; c++) 1003 for (c = 0; c < output_info->ncrtc; c++)
1004 { 1004 {
1005 crtc_t *crtc = find_crtc_by_xid (output_info->crtcs[c]); 1005 crtc_t *crtc = find_crtc_by_xid (output_info->crtcs[c]);
1006 if (crtc && !crtc_can_use_rotation (crtc, rotation)) 1006 if (crtc && !crtc_can_use_rotation (crtc, rotation))
1007 return False; 1007 return False;
1008 } 1008 }
1009 return True; 1009 return True;
1010} 1010}
1011 1011
1012static Bool 1012static Bool
1013output_is_primary(output_t *output) 1013output_is_primary(output_t *output)
1014{ 1014{
1015 if (has_1_3) 1015 if (has_1_3)
1016 return XRRGetOutputPrimary(dpy, root) == output->output.xid; 1016 return XRRGetOutputPrimary(dpy, root) == output->output.xid;
1017 return False; 1017 return False;
1018} 1018}
1019 1019
1020/* Returns the index of the last value in an array < 0xffff */ 1020/* Returns the index of the last value in an array < 0xffff */
1021static int 1021static int
1022find_last_non_clamped(CARD16 array[], int size) { 1022find_last_non_clamped(CARD16 array[], int size) {
1023 int i; 1023 int i;
1024 for (i = size - 1; i > 0; i--) { 1024 for (i = size - 1; i > 0; i--) {
1025 if (array[i] < 0xffff) 1025 if (array[i] < 0xffff)
1026 return i; 1026 return i;
1027 } 1027 }
1028 return 0; 1028 return 0;
1029} 1029}
1030 1030
1031static void 1031static void
1032set_gamma_info(output_t *output) 1032set_gamma_info(output_t *output)
1033{ 1033{
1034 XRRCrtcGamma *crtc_gamma; 1034 XRRCrtcGamma *crtc_gamma;
1035 double i1, v1, i2, v2; 1035 double i1, v1, i2, v2;
1036 int size, middle, last_best, last_red, last_green, last_blue; 1036 int size, middle, last_best, last_red, last_green, last_blue;
1037 CARD16 *best_array; 1037 CARD16 *best_array;
1038 1038
1039 if (!output->crtc_info) 1039 if (!output->crtc_info)
1040 return; 1040 return;
1041 1041
1042 size = XRRGetCrtcGammaSize(dpy, output->crtc_info->crtc.xid); 1042 size = XRRGetCrtcGammaSize(dpy, output->crtc_info->crtc.xid);
1043 if (!size) { 1043 if (!size) {
1044 warning("Failed to get size of gamma for output %s\n", output->output.string); 1044 warning("Failed to get size of gamma for output %s\n", output->output.string);
1045 return; 1045 return;
1046 } 1046 }
1047 1047
1048 crtc_gamma = XRRGetCrtcGamma(dpy, output->crtc_info->crtc.xid); 1048 crtc_gamma = XRRGetCrtcGamma(dpy, output->crtc_info->crtc.xid);
1049 if (!crtc_gamma) { 1049 if (!crtc_gamma) {
1050 warning("Failed to get gamma for output %s\n", output->output.string); 1050 warning("Failed to get gamma for output %s\n", output->output.string);
1051 return; 1051 return;
1052 } 1052 }
1053 1053
1054 /* 1054 /*
1055 * Here is a bit tricky because gamma is a whole curve for each 1055 * Here is a bit tricky because gamma is a whole curve for each
1056 * color. So, typically, we need to represent 3 * 256 values as 3 + 1 1056 * color. So, typically, we need to represent 3 * 256 values as 3 + 1
1057 * values. Therefore, we approximate the gamma curve (v) by supposing 1057 * values. Therefore, we approximate the gamma curve (v) by supposing
1058 * it always follows the way we set it: a power function (i^g) 1058 * it always follows the way we set it: a power function (i^g)
1059 * multiplied by a brightness (b). 1059 * multiplied by a brightness (b).
1060 * v = i^g * b 1060 * v = i^g * b
1061 * so g = (ln(v) - ln(b))/ln(i) 1061 * so g = (ln(v) - ln(b))/ln(i)
1062 * and b can be found using two points (v1,i1) and (v2, i2): 1062 * and b can be found using two points (v1,i1) and (v2, i2):
1063 * b = e^((ln(v2)*ln(i1) - ln(v1)*ln(i2))/ln(i1/i2)) 1063 * b = e^((ln(v2)*ln(i1) - ln(v1)*ln(i2))/ln(i1/i2))
1064 * For the best resolution, we select i2 at the highest place not 1064 * For the best resolution, we select i2 at the highest place not
1065 * clamped and i1 at i2/2. Note that if i2 = 1 (as in most normal 1065 * clamped and i1 at i2/2. Note that if i2 = 1 (as in most normal
1066 * cases), then b = v2. 1066 * cases), then b = v2.
1067 */ 1067 */
1068 last_red = find_last_non_clamped(crtc_gamma->red, size); 1068 last_red = find_last_non_clamped(crtc_gamma->red, size);
1069 last_green = find_last_non_clamped(crtc_gamma->green, size); 1069 last_green = find_last_non_clamped(crtc_gamma->green, size);
1070 last_blue = find_last_non_clamped(crtc_gamma->blue, size); 1070 last_blue = find_last_non_clamped(crtc_gamma->blue, size);
1071 best_array = crtc_gamma->red; 1071 best_array = crtc_gamma->red;
1072 last_best = last_red; 1072 last_best = last_red;
1073 if (last_green > last_best) { 1073 if (last_green > last_best) {
1074 last_best = last_green; 1074 last_best = last_green;
1075 best_array = crtc_gamma->green; 1075 best_array = crtc_gamma->green;
1076 } 1076 }
1077 if (last_blue > last_best) { 1077 if (last_blue > last_best) {
1078 last_best = last_blue; 1078 last_best = last_blue;
1079 best_array = crtc_gamma->blue; 1079 best_array = crtc_gamma->blue;
1080 } 1080 }
1081 if (last_best == 0) 1081 if (last_best == 0)
1082 last_best = 1; 1082 last_best = 1;
1083 1083
1084 middle = last_best / 2; 1084 middle = last_best / 2;
1085 i1 = (double)(middle + 1) / size; 1085 i1 = (double)(middle + 1) / size;
1086 v1 = (double)(best_array[middle]) / 65535; 1086 v1 = (double)(best_array[middle]) / 65535;
1087 i2 = (double)(last_best + 1) / size; 1087 i2 = (double)(last_best + 1) / size;
1088 v2 = (double)(best_array[last_best]) / 65535; 1088 v2 = (double)(best_array[last_best]) / 65535;
1089 if (v2 < 0.0001) { /* The screen is black */ 1089 if (v2 < 0.0001) { /* The screen is black */
1090 output->brightness = 0; 1090 output->brightness = 0;
1091 output->gamma.red = 1; 1091 output->gamma.red = 1;
1092 output->gamma.green = 1; 1092 output->gamma.green = 1;
1093 output->gamma.blue = 1; 1093 output->gamma.blue = 1;
1094 } else { 1094 } else {
1095 if ((last_best + 1) == size) 1095 if ((last_best + 1) == size)
1096 output->brightness = v2; 1096 output->brightness = v2;
1097 else 1097 else
1098 output->brightness = exp((log(v2)*log(i1) - log(v1)*log(i2))/log(i1/i2)); 1098 output->brightness = exp((log(v2)*log(i1) - log(v1)*log(i2))/log(i1/i2));
1099 output->gamma.red = log((double)(crtc_gamma->red[last_red / 2]) / output->brightness 1099 output->gamma.red = log((double)(crtc_gamma->red[last_red / 2]) / output->brightness
1100 / 65535) / log((double)((last_red / 2) + 1) / size); 1100 / 65535) / log((double)((last_red / 2) + 1) / size);
1101 output->gamma.green = log((double)(crtc_gamma->green[last_green / 2]) / output->brightness 1101 output->gamma.green = log((double)(crtc_gamma->green[last_green / 2]) / output->brightness
1102 / 65535) / log((double)((last_green / 2) + 1) / size); 1102 / 65535) / log((double)((last_green / 2) + 1) / size);
1103 output->gamma.blue = log((double)(crtc_gamma->blue[last_blue / 2]) / output->brightness 1103 output->gamma.blue = log((double)(crtc_gamma->blue[last_blue / 2]) / output->brightness
1104 / 65535) / log((double)((last_blue / 2) + 1) / size); 1104 / 65535) / log((double)((last_blue / 2) + 1) / size);
1105 } 1105 }
1106 1106
1107 XRRFreeGamma(crtc_gamma); 1107 XRRFreeGamma(crtc_gamma);
1108} 1108}
1109 1109
1110static void 1110static void
1111set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info) 1111set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
1112{ 1112{
1113 /* sanity check output info */ 1113 /* sanity check output info */
1114 if (output_info->connection != RR_Disconnected && !output_info->nmode) 1114 if (output_info->connection != RR_Disconnected && !output_info->nmode)
1115 warning ("Output %s is not disconnected but has no modes\n", 1115 warning ("Output %s is not disconnected but has no modes\n",
1116 output_info->name); 1116 output_info->name);
1117  1117
1118 /* set output name and info */ 1118 /* set output name and info */
1119 if (!(output->output.kind & name_xid)) 1119 if (!(output->output.kind & name_xid))
1120 set_name_xid (&output->output, xid); 1120 set_name_xid (&output->output, xid);
1121 if (!(output->output.kind & name_string)) 1121 if (!(output->output.kind & name_string))
1122 set_name_string (&output->output, output_info->name); 1122 set_name_string (&output->output, output_info->name);
1123 output->output_info = output_info; 1123 output->output_info = output_info;
1124  1124
1125 /* set crtc name and info */ 1125 /* set crtc name and info */
1126 if (!(output->changes & changes_crtc)) 1126 if (!(output->changes & changes_crtc))
1127 set_name_xid (&output->crtc, output_info->crtc); 1127 set_name_xid (&output->crtc, output_info->crtc);
1128  1128
1129 if (output->crtc.kind == name_xid && output->crtc.xid == None) 1129 if (output->crtc.kind == name_xid && output->crtc.xid == None)
1130 output->crtc_info = NULL; 1130 output->crtc_info = NULL;
1131 else 1131 else
1132 { 1132 {
1133 output->crtc_info = find_crtc (&output->crtc); 1133 output->crtc_info = find_crtc (&output->crtc);
1134 if (!output->crtc_info) 1134 if (!output->crtc_info)
1135 { 1135 {
1136 if (output->crtc.kind & name_xid) 1136 if (output->crtc.kind & name_xid)
1137 fatal ("cannot find crtc 0x%lx\n", output->crtc.xid); 1137 fatal ("cannot find crtc 0x%lx\n", output->crtc.xid);
1138 if (output->crtc.kind & name_index) 1138 if (output->crtc.kind & name_index)
1139 fatal ("cannot find crtc %d\n", output->crtc.index); 1139 fatal ("cannot find crtc %d\n", output->crtc.index);
1140 } 1140 }
1141 if (!output_can_use_crtc (output, output->crtc_info)) 1141 if (!output_can_use_crtc (output, output->crtc_info))
1142 fatal ("output %s cannot use crtc 0x%lx\n", output->output.string, 1142 fatal ("output %s cannot use crtc 0x%lx\n", output->output.string,
1143 output->crtc_info->crtc.xid); 1143 output->crtc_info->crtc.xid);
1144 } 1144 }
1145 1145
1146 /* set mode name and info */ 1146 /* set mode name and info */
1147 if (!(output->changes & changes_mode)) 1147 if (!(output->changes & changes_mode))
1148 { 1148 {
1149 crtc_t *crtc = NULL; 1149 crtc_t *crtc = NULL;
1150  1150
1151 if (output_info->crtc) 1151 if (output_info->crtc)
1152 crtc = find_crtc_by_xid(output_info->crtc); 1152 crtc = find_crtc_by_xid(output_info->crtc);
1153 if (crtc && crtc->crtc_info) 1153 if (crtc && crtc->crtc_info)
1154 set_name_xid (&output->mode, crtc->crtc_info->mode); 1154 set_name_xid (&output->mode, crtc->crtc_info->mode);
1155 else if (output->crtc_info) 1155 else if (output->crtc_info)
1156 set_name_xid (&output->mode, output->crtc_info->crtc_info->mode); 1156 set_name_xid (&output->mode, output->crtc_info->crtc_info->mode);
1157 else 1157 else
1158 set_name_xid (&output->mode, None); 1158 set_name_xid (&output->mode, None);
1159 if (output->mode.xid) 1159 if (output->mode.xid)
1160 { 1160 {
1161 output->mode_info = find_mode_by_xid (output->mode.xid); 1161 output->mode_info = find_mode_by_xid (output->mode.xid);
1162 if (!output->mode_info) 1162 if (!output->mode_info)
1163 fatal ("server did not report mode 0x%lx for output %s\n", 1163 fatal ("server did not report mode 0x%lx for output %s\n",
1164 output->mode.xid, output->output.string); 1164 output->mode.xid, output->output.string);
1165 } 1165 }
1166 else 1166 else
1167 output->mode_info = NULL; 1167 output->mode_info = NULL;
1168 } 1168 }
1169 else if (output->mode.kind == name_xid && output->mode.xid == None) 1169 else if (output->mode.kind == name_xid && output->mode.xid == None)
1170 output->mode_info = NULL; 1170 output->mode_info = NULL;
1171 else 1171 else
1172 { 1172 {
1173 if (output->mode.kind == name_preferred) 1173 if (output->mode.kind == name_preferred)
1174 output->mode_info = preferred_mode (output); 1174 output->mode_info = preferred_mode (output);
1175 else 1175 else
1176 output->mode_info = find_mode_for_output (output, &output->mode); 1176 output->mode_info = find_mode_for_output (output, &output->mode);
1177 if (!output->mode_info) 1177 if (!output->mode_info)
1178 { 1178 {
1179 if (output->mode.kind & name_preferred) 1179 if (output->mode.kind & name_preferred)
1180 fatal ("cannot find preferred mode\n"); 1180 fatal ("cannot find preferred mode\n");
1181 if (output->mode.kind & name_string) 1181 if (output->mode.kind & name_string)
1182 fatal ("cannot find mode %s\n", output->mode.string); 1182 fatal ("cannot find mode %s\n", output->mode.string);
1183 if (output->mode.kind & name_xid) 1183 if (output->mode.kind & name_xid)
1184 fatal ("cannot find mode 0x%lx\n", output->mode.xid); 1184 fatal ("cannot find mode 0x%lx\n", output->mode.xid);
1185 } 1185 }
1186 if (!output_can_use_mode (output, output->mode_info)) 1186 if (!output_can_use_mode (output, output->mode_info))
1187 fatal ("output %s cannot use mode %s\n", output->output.string, 1187 fatal ("output %s cannot use mode %s\n", output->output.string,
1188 output->mode_info->name); 1188 output->mode_info->name);
1189 } 1189 }
1190 1190
1191 /* set position */ 1191 /* set position */
1192 if (!(output->changes & changes_position)) 1192 if (!(output->changes & changes_position))
1193 { 1193 {
1194 if (output->crtc_info) 1194 if (output->crtc_info)
1195 { 1195 {
1196 output->x = output->crtc_info->crtc_info->x; 1196 output->x = output->crtc_info->crtc_info->x;
1197 output->y = output->crtc_info->crtc_info->y; 1197 output->y = output->crtc_info->crtc_info->y;
1198 } 1198 }
1199 else 1199 else
1200 { 1200 {
1201 output->x = 0; 1201 output->x = 0;
1202 output->y = 0; 1202 output->y = 0;
1203 } 1203 }
1204 } 1204 }
1205 1205
1206 /* set rotation */ 1206 /* set rotation */
1207 if (!(output->changes & changes_rotation)) 1207 if (!(output->changes & changes_rotation))
1208 { 1208 {
1209 output->rotation &= ~0xf; 1209 output->rotation &= ~0xf;
1210 if (output->crtc_info) 1210 if (output->crtc_info)
1211 output->rotation |= (output->crtc_info->crtc_info->rotation & 0xf); 1211 output->rotation |= (output->crtc_info->crtc_info->rotation & 0xf);
1212 else 1212 else
1213 output->rotation = RR_Rotate_0; 1213 output->rotation = RR_Rotate_0;
1214 } 1214 }
1215 if (!(output->changes & changes_reflection)) 1215 if (!(output->changes & changes_reflection))
1216 { 1216 {
1217 output->rotation &= ~(RR_Reflect_X|RR_Reflect_Y); 1217 output->rotation &= ~(RR_Reflect_X|RR_Reflect_Y);
1218 if (output->crtc_info) 1218 if (output->crtc_info)
1219 output->rotation |= (output->crtc_info->crtc_info->rotation & 1219 output->rotation |= (output->crtc_info->crtc_info->rotation &
1220 (RR_Reflect_X|RR_Reflect_Y)); 1220 (RR_Reflect_X|RR_Reflect_Y));
1221 } 1221 }
1222 if (!output_can_use_rotation (output, output->rotation)) 1222 if (!output_can_use_rotation (output, output->rotation))
1223 fatal ("output %s cannot use rotation \"%s\" reflection \"%s\"\n", 1223 fatal ("output %s cannot use rotation \"%s\" reflection \"%s\"\n",
1224 output->output.string, 1224 output->output.string,
1225 rotation_name (output->rotation), 1225 rotation_name (output->rotation),
1226 reflection_name (output->rotation)); 1226 reflection_name (output->rotation));
1227 1227
1228 /* set gamma */ 1228 /* set gamma */
1229 if (!(output->changes & changes_gamma)) 1229 if (!(output->changes & changes_gamma))
1230 set_gamma_info(output); 1230 set_gamma_info(output);
1231 1231
1232 /* set transformation */ 1232 /* set transformation */
1233 if (!(output->changes & changes_transform)) 1233 if (!(output->changes & changes_transform))
1234 { 1234 {
1235 if (output->crtc_info) 1235 if (output->crtc_info)
1236 copy_transform (&output->transform, &output->crtc_info->current_transform); 1236 copy_transform (&output->transform, &output->crtc_info->current_transform);
1237 else 1237 else
1238 init_transform (&output->transform); 1238 init_transform (&output->transform);
1239 } else { 1239 } else {
1240 /* transform was already set for --scale or --transform */ 1240 /* transform was already set for --scale or --transform */
1241 1241
1242 /* for --scale-from, figure out the mode size and compute the transform 1242 /* for --scale-from, figure out the mode size and compute the transform
1243 * for the target framebuffer area */ 1243 * for the target framebuffer area */
1244 if (output->scale_from_w > 0 && output->mode_info) { 1244 if (output->scale_from_w > 0 && output->mode_info) {
1245 double sx = (double)output->scale_from_w / 1245 double sx = (double)output->scale_from_w /
1246 output->mode_info->width; 1246 output->mode_info->width;
1247 double sy = (double)output->scale_from_h / 1247 double sy = (double)output->scale_from_h /
1248 output->mode_info->height; 1248 output->mode_info->height;
1249 if (verbose) 1249 if (verbose)
1250 printf("scaling %s by %lfx%lf\n", output->output.string, sx, 1250 printf("scaling %s by %lfx%lf\n", output->output.string, sx,
1251 sy); 1251 sy);
1252 init_transform (&output->transform); 1252 init_transform (&output->transform);
1253 output->transform.transform.matrix[0][0] = XDoubleToFixed (sx); 1253 output->transform.transform.matrix[0][0] = XDoubleToFixed (sx);
1254 output->transform.transform.matrix[1][1] = XDoubleToFixed (sy); 1254 output->transform.transform.matrix[1][1] = XDoubleToFixed (sy);
1255 output->transform.transform.matrix[2][2] = XDoubleToFixed (1.0); 1255 output->transform.transform.matrix[2][2] = XDoubleToFixed (1.0);
1256 if (sx != 1 || sy != 1) 1256 if (sx != 1 || sy != 1)
1257 output->transform.filter = "bilinear"; 1257 output->transform.filter = "bilinear";
1258 else 1258 else
1259 output->transform.filter = "nearest"; 1259 output->transform.filter = "nearest";
1260 output->transform.nparams = 0; 1260 output->transform.nparams = 0;
1261 output->transform.params = NULL; 1261 output->transform.params = NULL;
1262 } 1262 }
1263 } 1263 }
1264 1264
1265 /* set primary */ 1265 /* set primary */
1266 if (!(output->changes & changes_primary)) 1266 if (!(output->changes & changes_primary))
1267 output->primary = output_is_primary(output); 1267 output->primary = output_is_primary(output);
1268} 1268}
1269  1269
1270static void 1270static void
1271get_screen (Bool current) 1271get_screen (Bool current)
1272{ 1272{
1273 if (!has_1_2) 1273 if (!has_1_2)
1274 fatal ("Server RandR version before 1.2\n"); 1274 fatal ("Server RandR version before 1.2\n");
1275 1275
1276 if (res) 1276 if (res)
1277 return; 1277 return;
1278 1278
1279 XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight, 1279 XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight,
1280 &maxWidth, &maxHeight); 1280 &maxWidth, &maxHeight);
1281  1281
1282 if (current) 1282 if (current)
1283 res = XRRGetScreenResourcesCurrent (dpy, root); 1283 res = XRRGetScreenResourcesCurrent (dpy, root);
1284 else 1284 else
1285 res = XRRGetScreenResources (dpy, root); 1285 res = XRRGetScreenResources (dpy, root);
1286 if (!res) fatal ("could not get screen resources"); 1286 if (!res) fatal ("could not get screen resources");
1287} 1287}
1288 1288
1289static void 1289static void
1290get_crtcs (void) 1290get_crtcs (void)
1291{ 1291{
1292 int c; 1292 int c;
1293 1293
1294 num_crtcs = res->ncrtc; 1294 num_crtcs = res->ncrtc;
1295 crtcs = calloc (num_crtcs, sizeof (crtc_t)); 1295 crtcs = calloc (num_crtcs, sizeof (crtc_t));
1296 if (!crtcs) fatal ("out of memory\n"); 1296 if (!crtcs) fatal ("out of memory\n");
1297  1297
1298 for (c = 0; c < res->ncrtc; c++) 1298 for (c = 0; c < res->ncrtc; c++)
1299 { 1299 {
1300 XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]); 1300 XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]);
1301 XRRCrtcTransformAttributes *attr; 1301 XRRCrtcTransformAttributes *attr;
1302 XRRPanning *panning_info = NULL; 1302 XRRPanning *panning_info = NULL;
1303 1303
1304 if (has_1_3) { 1304 if (has_1_3) {
1305 XRRPanning zero; 1305 XRRPanning zero;
1306 memset(&zero, 0, sizeof(zero)); 1306 memset(&zero, 0, sizeof(zero));
1307 panning_info = XRRGetPanning (dpy, res, res->crtcs[c]); 1307 panning_info = XRRGetPanning (dpy, res, res->crtcs[c]);
1308 zero.timestamp = panning_info->timestamp; 1308 zero.timestamp = panning_info->timestamp;
1309 if (!memcmp(panning_info, &zero, sizeof(zero))) { 1309 if (!memcmp(panning_info, &zero, sizeof(zero))) {
1310 Xfree(panning_info); 1310 Xfree(panning_info);
1311 panning_info = NULL; 1311 panning_info = NULL;
1312 } 1312 }
1313 } 1313 }
1314 1314
1315 set_name_xid (&crtcs[c].crtc, res->crtcs[c]); 1315 set_name_xid (&crtcs[c].crtc, res->crtcs[c]);
1316 set_name_index (&crtcs[c].crtc, c); 1316 set_name_index (&crtcs[c].crtc, c);
1317 if (!crtc_info) fatal ("could not get crtc 0x%lx information\n", res->crtcs[c]); 1317 if (!crtc_info) fatal ("could not get crtc 0x%lx information\n", res->crtcs[c]);
1318 crtcs[c].crtc_info = crtc_info; 1318 crtcs[c].crtc_info = crtc_info;
1319 crtcs[c].panning_info = panning_info; 1319 crtcs[c].panning_info = panning_info;
1320 if (crtc_info->mode == None) 1320 if (crtc_info->mode == None)
1321 { 1321 {
1322 crtcs[c].mode_info = NULL; 1322 crtcs[c].mode_info = NULL;
1323 crtcs[c].x = 0; 1323 crtcs[c].x = 0;
1324 crtcs[c].y = 0; 1324 crtcs[c].y = 0;
1325 crtcs[c].rotation = RR_Rotate_0; 1325 crtcs[c].rotation = RR_Rotate_0;
1326 } 1326 }
1327 if (XRRGetCrtcTransform (dpy, res->crtcs[c], &attr) && attr) { 1327 if (XRRGetCrtcTransform (dpy, res->crtcs[c], &attr) && attr) {
1328 set_transform (&crtcs[c].current_transform, 1328 set_transform (&crtcs[c].current_transform,
1329 &attr->currentTransform, 1329 &attr->currentTransform,
1330 attr->currentFilter, 1330 attr->currentFilter,
1331 attr->currentParams, 1331 attr->currentParams,
1332 attr->currentNparams); 1332 attr->currentNparams);
1333 XFree (attr); 1333 XFree (attr);
1334 } 1334 }
1335 else 1335 else
1336 { 1336 {
1337 init_transform (&crtcs[c].current_transform); 1337 init_transform (&crtcs[c].current_transform);
1338 } 1338 }
1339 copy_transform (&crtcs[c].pending_transform, &crtcs[c].current_transform); 1339 copy_transform (&crtcs[c].pending_transform, &crtcs[c].current_transform);
1340 } 1340 }
1341} 1341}
1342 1342
1343static void 1343static void
1344crtc_add_output (crtc_t *crtc, output_t *output) 1344crtc_add_output (crtc_t *crtc, output_t *output)
1345{ 1345{
1346 if (crtc->outputs) 1346 if (crtc->outputs)
1347 crtc->outputs = realloc (crtc->outputs, (crtc->noutput + 1) * sizeof (output_t *)); 1347 crtc->outputs = realloc (crtc->outputs, (crtc->noutput + 1) * sizeof (output_t *));
1348 else 1348 else
1349 { 1349 {
1350 crtc->outputs = malloc (sizeof (output_t *)); 1350 crtc->outputs = malloc (sizeof (output_t *));
1351 crtc->x = output->x; 1351 crtc->x = output->x;
1352 crtc->y = output->y; 1352 crtc->y = output->y;
1353 crtc->rotation = output->rotation; 1353 crtc->rotation = output->rotation;
1354 crtc->mode_info = output->mode_info; 1354 crtc->mode_info = output->mode_info;
1355 copy_transform (&crtc->pending_transform, &output->transform); 1355 copy_transform (&crtc->pending_transform, &output->transform);
1356 } 1356 }
1357 if (!crtc->outputs) fatal ("out of memory\n"); 1357 if (!crtc->outputs) fatal ("out of memory\n");
1358 crtc->outputs[crtc->noutput++] = output; 1358 crtc->outputs[crtc->noutput++] = output;
1359} 1359}
1360 1360
1361static void 1361static void
1362set_crtcs (void) 1362set_crtcs (void)
1363{ 1363{
1364 output_t *output; 1364 output_t *output;
1365 1365
1366 for (output = all_outputs; output; output = output->next) 1366 for (output = all_outputs; output; output = output->next)
1367 { 1367 {
1368 if (!output->mode_info) continue; 1368 if (!output->mode_info) continue;
1369 crtc_add_output (output->crtc_info, output); 1369 crtc_add_output (output->crtc_info, output);
1370 } 1370 }
1371} 1371}
1372 1372
1373static void 1373static void
1374set_panning (void) 1374set_panning (void)
1375{ 1375{
1376 output_t *output; 1376 output_t *output;
1377 1377
1378 for (output = all_outputs; output; output = output->next) 1378 for (output = all_outputs; output; output = output->next)
1379 { 1379 {
1380 if (! output->crtc_info) 1380 if (! output->crtc_info)
1381 continue; 1381 continue;
1382 if (! (output->changes & changes_panning)) 1382 if (! (output->changes & changes_panning))
1383 continue; 1383 continue;
1384 if (! output->crtc_info->panning_info) 1384 if (! output->crtc_info->panning_info)
1385 output->crtc_info->panning_info = malloc (sizeof(XRRPanning)); 1385 output->crtc_info->panning_info = malloc (sizeof(XRRPanning));
1386 memcpy (output->crtc_info->panning_info, &output->panning, sizeof(XRRPanning)); 1386 memcpy (output->crtc_info->panning_info, &output->panning, sizeof(XRRPanning));
1387 output->crtc_info->changing = 1; 1387 output->crtc_info->changing = 1;
1388 } 1388 }
1389} 1389}
1390 1390
1391static void 1391static void
1392set_gamma(void) 1392set_gamma(void)
1393{ 1393{
1394 output_t *output; 1394 output_t *output;
1395 1395
1396 for (output = all_outputs; output; output = output->next) { 1396 for (output = all_outputs; output; output = output->next) {
1397 int i, size, shift; 1397 int i, size, shift;
1398 crtc_t *crtc; 1398 crtc_t *crtc;
1399 XRRCrtcGamma *crtc_gamma; 1399 XRRCrtcGamma *crtc_gamma;
1400 float gammaRed; 1400 float gammaRed;
1401 float gammaGreen; 1401 float gammaGreen;
1402 float gammaBlue; 1402 float gammaBlue;
1403 1403
1404 if (!(output->changes & changes_gamma)) 1404 if (!(output->changes & changes_gamma))
1405 continue; 1405 continue;
1406 1406
1407 if (!output->crtc_info) { 1407 if (!output->crtc_info) {
1408 fatal("Need crtc to set gamma on.\n"); 1408 fatal("Need crtc to set gamma on.\n");
1409 continue; 1409 continue;
1410 } 1410 }
1411 1411
1412 crtc = output->crtc_info; 1412 crtc = output->crtc_info;
1413 1413
1414 size = XRRGetCrtcGammaSize(dpy, crtc->crtc.xid); 1414 size = XRRGetCrtcGammaSize(dpy, crtc->crtc.xid);
1415 1415
1416 if (!size) { 1416 if (!size) {
1417 fatal("Gamma size is 0.\n"); 1417 fatal("Gamma size is 0.\n");
1418 continue; 1418 continue;
1419 } 1419 }
1420 1420
1421 /* 1421 /*
1422 * The gamma-correction lookup table managed through XRR[GS]etCrtcGamma 1422 * The gamma-correction lookup table managed through XRR[GS]etCrtcGamma
1423 * is 2^n in size, where 'n' is the number of significant bits in 1423 * is 2^n in size, where 'n' is the number of significant bits in
1424 * the X Color. Because an X Color is 16 bits, size cannot be larger 1424 * the X Color. Because an X Color is 16 bits, size cannot be larger
1425 * than 2^16. 1425 * than 2^16.
1426 */ 1426 */
1427 if (size > 65536) { 1427 if (size > 65536) {
1428 fatal("Gamma correction table is impossibly large.\n"); 1428 fatal("Gamma correction table is impossibly large.\n");
1429 continue; 1429 continue;
1430 } 1430 }
1431 1431
1432 /* 1432 /*
1433 * The hardware color lookup table has a number of significant 1433 * The hardware color lookup table has a number of significant
1434 * bits equal to ffs(size) - 1; compute all values so that 1434 * bits equal to ffs(size) - 1; compute all values so that
1435 * they are in the range [0,size) then shift the values so 1435 * they are in the range [0,size) then shift the values so
1436 * that they occupy the MSBs of the 16-bit X Color. 1436 * that they occupy the MSBs of the 16-bit X Color.
1437 */ 1437 */
1438 shift = 16 - (ffs(size) - 1); 1438 shift = 16 - (ffs(size) - 1);
1439 1439
1440 crtc_gamma = XRRAllocGamma(size); 1440 crtc_gamma = XRRAllocGamma(size);
1441 if (!crtc_gamma) { 1441 if (!crtc_gamma) {
1442 fatal("Gamma allocation failed.\n"); 1442 fatal("Gamma allocation failed.\n");
1443 continue; 1443 continue;
1444 } 1444 }
1445 1445
1446 if (output->gamma.red == 0.0) 1446 if (output->gamma.red == 0.0)
1447 output->gamma.red = 1.0; 1447 output->gamma.red = 1.0;
1448 if (output->gamma.green == 0.0) 1448 if (output->gamma.green == 0.0)
1449 output->gamma.green = 1.0; 1449 output->gamma.green = 1.0;
1450 if (output->gamma.blue == 0.0) 1450 if (output->gamma.blue == 0.0)
1451 output->gamma.blue = 1.0; 1451 output->gamma.blue = 1.0;
1452 1452
1453 gammaRed = 1.0 / output->gamma.red; 1453 gammaRed = 1.0 / output->gamma.red;
1454 gammaGreen = 1.0 / output->gamma.green; 1454 gammaGreen = 1.0 / output->gamma.green;
1455 gammaBlue = 1.0 / output->gamma.blue; 1455 gammaBlue = 1.0 / output->gamma.blue;
1456 1456
1457 for (i = 0; i < size; i++) { 1457 for (i = 0; i < size; i++) {
1458 if (gammaRed == 1.0 && output->brightness == 1.0) 1458 if (gammaRed == 1.0 && output->brightness == 1.0)
1459 crtc_gamma->red[i] = i; 1459 crtc_gamma->red[i] = i;
1460 else 1460 else
1461 crtc_gamma->red[i] = dmin(pow((double)i/(double)(size - 1), 1461 crtc_gamma->red[i] = dmin(pow((double)i/(double)(size - 1),
1462 gammaRed) * output->brightness, 1462 gammaRed) * output->brightness,
1463 1.0) * (double)(size - 1); 1463 1.0) * (double)(size - 1);
1464 crtc_gamma->red[i] <<= shift; 1464 crtc_gamma->red[i] <<= shift;
1465 1465
1466 if (gammaGreen == 1.0 && output->brightness == 1.0) 1466 if (gammaGreen == 1.0 && output->brightness == 1.0)
1467 crtc_gamma->green[i] = i; 1467 crtc_gamma->green[i] = i;
1468 else 1468 else
1469 crtc_gamma->green[i] = dmin(pow((double)i/(double)(size - 1), 1469 crtc_gamma->green[i] = dmin(pow((double)i/(double)(size - 1),
1470 gammaGreen) * output->brightness, 1470 gammaGreen) * output->brightness,
1471 1.0) * (double)(size - 1); 1471 1.0) * (double)(size - 1);
1472 crtc_gamma->green[i] <<= shift; 1472 crtc_gamma->green[i] <<= shift;
1473 1473
1474 if (gammaBlue == 1.0 && output->brightness == 1.0) 1474 if (gammaBlue == 1.0 && output->brightness == 1.0)
1475 crtc_gamma->blue[i] = i; 1475 crtc_gamma->blue[i] = i;
1476 else 1476 else
1477 crtc_gamma->blue[i] = dmin(pow((double)i/(double)(size - 1), 1477 crtc_gamma->blue[i] = dmin(pow((double)i/(double)(size - 1),
1478 gammaBlue) * output->brightness, 1478 gammaBlue) * output->brightness,
1479 1.0) * (double)(size - 1); 1479 1.0) * (double)(size - 1);
1480 crtc_gamma->blue[i] <<= shift; 1480 crtc_gamma->blue[i] <<= shift;
1481 } 1481 }
1482 1482
1483 XRRSetCrtcGamma(dpy, crtc->crtc.xid, crtc_gamma); 1483 XRRSetCrtcGamma(dpy, crtc->crtc.xid, crtc_gamma);
1484 1484
1485 free(crtc_gamma); 1485 free(crtc_gamma);
1486 } 1486 }
1487} 1487}
1488 1488
1489static void 1489static void
1490set_primary(void) 1490set_primary(void)
1491{ 1491{
1492 output_t *output; 1492 output_t *output;
1493 1493
1494 if (no_primary) { 1494 if (no_primary) {
1495 XRRSetOutputPrimary(dpy, root, None); 1495 XRRSetOutputPrimary(dpy, root, None);
1496 } else { 1496 } else {
1497 for (output = all_outputs; output; output = output->next) { 1497 for (output = all_outputs; output; output = output->next) {
1498 if (!(output->changes & changes_primary)) 1498 if (!(output->changes & changes_primary))
1499 continue; 1499 continue;
1500 if (output->primary) 1500 if (output->primary)
1501 XRRSetOutputPrimary(dpy, root, output->output.xid); 1501 XRRSetOutputPrimary(dpy, root, output->output.xid);
1502 } 1502 }
1503 } 1503 }
1504} 1504}
1505 1505
1506static Status 1506static Status
1507crtc_disable (crtc_t *crtc) 1507crtc_disable (crtc_t *crtc)
1508{ 1508{
1509 if (verbose) 1509 if (verbose)
1510 printf ("crtc %d: disable\n", crtc->crtc.index); 1510 printf ("crtc %d: disable\n", crtc->crtc.index);
1511  1511
1512 if (dryrun) 1512 if (dryrun)
1513 return RRSetConfigSuccess; 1513 return RRSetConfigSuccess;
1514 return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime, 1514 return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
1515 0, 0, None, RR_Rotate_0, NULL, 0); 1515 0, 0, None, RR_Rotate_0, NULL, 0);
1516} 1516}
1517 1517
1518static void 1518static void
1519crtc_set_transform (crtc_t *crtc, transform_t *transform) 1519crtc_set_transform (crtc_t *crtc, transform_t *transform)
1520{ 1520{
1521 int major, minor; 1521 int major, minor;
1522 1522
1523 XRRQueryVersion (dpy, &major, &minor); 1523 XRRQueryVersion (dpy, &major, &minor);
1524 if (major > 1 || (major == 1 && minor >= 3)) 1524 if (major > 1 || (major == 1 && minor >= 3))
1525 XRRSetCrtcTransform (dpy, crtc->crtc.xid, 1525 XRRSetCrtcTransform (dpy, crtc->crtc.xid,
1526 &transform->transform, 1526 &transform->transform,
1527 __UNCONST(transform->filter), 1527 transform->filter,
1528 transform->params, 1528 transform->params,
1529 transform->nparams); 1529 transform->nparams);
1530} 1530}
1531 1531
1532static Status 1532static Status
1533crtc_revert (crtc_t *crtc) 1533crtc_revert (crtc_t *crtc)
1534{ 1534{
1535 XRRCrtcInfo *crtc_info = crtc->crtc_info; 1535 XRRCrtcInfo *crtc_info = crtc->crtc_info;
1536  1536
1537 if (verbose) 1537 if (verbose)
1538 printf ("crtc %d: revert\n", crtc->crtc.index); 1538 printf ("crtc %d: revert\n", crtc->crtc.index);
1539  1539
1540 if (dryrun) 1540 if (dryrun)
1541 return RRSetConfigSuccess; 1541 return RRSetConfigSuccess;
1542 1542
1543 if (!equal_transform (&crtc->current_transform, &crtc->pending_transform)) 1543 if (!equal_transform (&crtc->current_transform, &crtc->pending_transform))
1544 crtc_set_transform (crtc, &crtc->current_transform); 1544 crtc_set_transform (crtc, &crtc->current_transform);
1545 return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime, 1545 return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
1546 crtc_info->x, crtc_info->y, 1546 crtc_info->x, crtc_info->y,
1547 crtc_info->mode, crtc_info->rotation, 1547 crtc_info->mode, crtc_info->rotation,
1548 crtc_info->outputs, crtc_info->noutput); 1548 crtc_info->outputs, crtc_info->noutput);
1549} 1549}
1550 1550
1551static Status 1551static Status
1552crtc_apply (crtc_t *crtc) 1552crtc_apply (crtc_t *crtc)
1553{ 1553{
1554 RROutput *rr_outputs; 1554 RROutput *rr_outputs;
1555 int o; 1555 int o;
1556 Status s; 1556 Status s;
1557 RRMode mode = None; 1557 RRMode mode = None;
1558 1558
1559 if (!crtc->changing || !crtc->mode_info) 1559 if (!crtc->changing || !crtc->mode_info)
1560 return RRSetConfigSuccess; 1560 return RRSetConfigSuccess;
1561 1561
1562 rr_outputs = calloc (crtc->noutput, sizeof (RROutput)); 1562 rr_outputs = calloc (crtc->noutput, sizeof (RROutput));
1563 if (!rr_outputs) 1563 if (!rr_outputs)
1564 return BadAlloc; 1564 return BadAlloc;
1565 for (o = 0; o < crtc->noutput; o++) 1565 for (o = 0; o < crtc->noutput; o++)
1566 rr_outputs[o] = crtc->outputs[o]->output.xid; 1566 rr_outputs[o] = crtc->outputs[o]->output.xid;
1567 mode = crtc->mode_info->id; 1567 mode = crtc->mode_info->id;
1568 if (verbose) { 1568 if (verbose) {
1569 printf ("crtc %d: %12s %6.1f +%d+%d", crtc->crtc.index, 1569 printf ("crtc %d: %12s %6.1f +%d+%d", crtc->crtc.index,
1570 crtc->mode_info->name, mode_refresh (crtc->mode_info), 1570 crtc->mode_info->name, mode_refresh (crtc->mode_info),
1571 crtc->x, crtc->y); 1571 crtc->x, crtc->y);
1572 for (o = 0; o < crtc->noutput; o++) 1572 for (o = 0; o < crtc->noutput; o++)
1573 printf (" \"%s\"", crtc->outputs[o]->output.string); 1573 printf (" \"%s\"", crtc->outputs[o]->output.string);
1574 printf ("\n"); 1574 printf ("\n");
1575 } 1575 }
1576  1576
1577 if (dryrun) 1577 if (dryrun)
1578 s = RRSetConfigSuccess; 1578 s = RRSetConfigSuccess;
1579 else 1579 else
1580 { 1580 {
1581 if (!equal_transform (&crtc->current_transform, &crtc->pending_transform)) 1581 if (!equal_transform (&crtc->current_transform, &crtc->pending_transform))
1582 crtc_set_transform (crtc, &crtc->pending_transform); 1582 crtc_set_transform (crtc, &crtc->pending_transform);
1583 s = XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime, 1583 s = XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
1584 crtc->x, crtc->y, mode, crtc->rotation, 1584 crtc->x, crtc->y, mode, crtc->rotation,
1585 rr_outputs, crtc->noutput); 1585 rr_outputs, crtc->noutput);
1586 if (s == RRSetConfigSuccess && crtc->panning_info) { 1586 if (s == RRSetConfigSuccess && crtc->panning_info) {
1587 if (has_1_3) 1587 if (has_1_3)
1588 s = XRRSetPanning (dpy, res, crtc->crtc.xid, crtc->panning_info); 1588 s = XRRSetPanning (dpy, res, crtc->crtc.xid, crtc->panning_info);
1589 else 1589 else
1590 fatal ("panning needs RandR 1.3\n"); 1590 fatal ("panning needs RandR 1.3\n");
1591 } 1591 }
1592 } 1592 }
1593 free (rr_outputs); 1593 free (rr_outputs);
1594 return s; 1594 return s;
1595} 1595}
1596 1596
1597static void 1597static void
1598screen_revert (void) 1598screen_revert (void)
1599{ 1599{
1600 if (verbose) 1600 if (verbose)
1601 printf ("screen %d: revert\n", screen); 1601 printf ("screen %d: revert\n", screen);
1602 1602
1603 if (dryrun) 1603 if (dryrun)
1604 return; 1604 return;
1605 XRRSetScreenSize (dpy, root, 1605 XRRSetScreenSize (dpy, root,
1606 DisplayWidth (dpy, screen), 1606 DisplayWidth (dpy, screen),
1607 DisplayHeight (dpy, screen), 1607 DisplayHeight (dpy, screen),
1608 DisplayWidthMM (dpy, screen), 1608 DisplayWidthMM (dpy, screen),
1609 DisplayHeightMM (dpy, screen)); 1609 DisplayHeightMM (dpy, screen));
1610} 1610}
1611 1611
1612static void 1612static void
1613screen_apply (void) 1613screen_apply (void)
1614{ 1614{
1615 if (fb_width == DisplayWidth (dpy, screen) && 1615 if (fb_width == DisplayWidth (dpy, screen) &&
1616 fb_height == DisplayHeight (dpy, screen) && 1616 fb_height == DisplayHeight (dpy, screen) &&
1617 fb_width_mm == DisplayWidthMM (dpy, screen) && 1617 fb_width_mm == DisplayWidthMM (dpy, screen) &&
1618 fb_height_mm == DisplayHeightMM (dpy, screen)) 1618 fb_height_mm == DisplayHeightMM (dpy, screen))
1619 { 1619 {
1620 return; 1620 return;
1621 } 1621 }
1622 if (verbose) 1622 if (verbose)
1623 printf ("screen %d: %dx%d %dx%d mm %6.2fdpi\n", screen, 1623 printf ("screen %d: %dx%d %dx%d mm %6.2fdpi\n", screen,
1624 fb_width, fb_height, fb_width_mm, fb_height_mm, dpi); 1624 fb_width, fb_height, fb_width_mm, fb_height_mm, dpi);
1625 if (dryrun) 1625 if (dryrun)
1626 return; 1626 return;
1627 XRRSetScreenSize (dpy, root, fb_width, fb_height, 1627 XRRSetScreenSize (dpy, root, fb_width, fb_height,
1628 fb_width_mm, fb_height_mm); 1628 fb_width_mm, fb_height_mm);
1629} 1629}
1630 1630
1631static void 1631static void
1632revert (void) 1632revert (void)
1633{ 1633{
1634 int c; 1634 int c;
1635 1635
1636 /* first disable all crtcs */ 1636 /* first disable all crtcs */
1637 for (c = 0; c < res->ncrtc; c++) 1637 for (c = 0; c < res->ncrtc; c++)
1638 crtc_disable (&crtcs[c]); 1638 crtc_disable (&crtcs[c]);
1639 /* next reset screen size */ 1639 /* next reset screen size */
1640 screen_revert (); 1640 screen_revert ();
1641 /* now restore all crtcs */ 1641 /* now restore all crtcs */
1642 for (c = 0; c < res->ncrtc; c++) 1642 for (c = 0; c < res->ncrtc; c++)
1643 crtc_revert (&crtcs[c]); 1643 crtc_revert (&crtcs[c]);
1644} 1644}
1645 1645
1646/* 1646/*
1647 * uh-oh, something bad happened in the middle of changing 1647 * uh-oh, something bad happened in the middle of changing
1648 * the configuration. Revert to the previous configuration 1648 * the configuration. Revert to the previous configuration
1649 * and bail 1649 * and bail
1650 */ 1650 */
1651static void _X_NORETURN 1651static void _X_NORETURN
1652panic (Status s, crtc_t *crtc) 1652panic (Status s, crtc_t *crtc)
1653{ 1653{
1654 int c = crtc->crtc.index; 1654 int c = crtc->crtc.index;
1655 const char *message; 1655 const char *message;
1656  1656
1657 switch (s) { 1657 switch (s) {
1658 case RRSetConfigSuccess: message = "succeeded"; break; 1658 case RRSetConfigSuccess: message = "succeeded"; break;
1659 case BadAlloc: message = "out of memory"; break; 1659 case BadAlloc: message = "out of memory"; break;
1660 case RRSetConfigFailed: message = "failed"; break; 1660 case RRSetConfigFailed: message = "failed"; break;
1661 case RRSetConfigInvalidConfigTime: message = "invalid config time"; break; 1661 case RRSetConfigInvalidConfigTime: message = "invalid config time"; break;
1662 case RRSetConfigInvalidTime: message = "invalid time"; break; 1662 case RRSetConfigInvalidTime: message = "invalid time"; break;
1663 default: message = "unknown failure"; break; 1663 default: message = "unknown failure"; break;
1664 } 1664 }
1665  1665
1666 fprintf (stderr, "%s: Configure crtc %d %s\n", program_name, c, message); 1666 fprintf (stderr, "%s: Configure crtc %d %s\n", program_name, c, message);
1667 revert (); 1667 revert ();
1668 exit (1); 1668 exit (1);
1669} 1669}
1670 1670
1671static void 1671static void
1672apply (void) 1672apply (void)
1673{ 1673{
1674 Status s; 1674 Status s;
1675 int c; 1675 int c;
1676  1676
1677 /* 1677 /*
1678 * Hold the server grabbed while messing with 1678 * Hold the server grabbed while messing with
1679 * the screen so that apps which notice the resize 1679 * the screen so that apps which notice the resize
1680 * event and ask for xinerama information from the server 1680 * event and ask for xinerama information from the server
1681 * receive up-to-date information 1681 * receive up-to-date information
1682 */ 1682 */
1683 if (grab_server) 1683 if (grab_server)
1684 XGrabServer (dpy); 1684 XGrabServer (dpy);
1685  1685
1686 /* 1686 /*
1687 * Turn off any crtcs which are to be disabled or which are 1687 * Turn off any crtcs which are to be disabled or which are
1688 * larger than the target size 1688 * larger than the target size
1689 */ 1689 */
1690 for (c = 0; c < res->ncrtc; c++) 1690 for (c = 0; c < res->ncrtc; c++)
1691 { 1691 {
1692 crtc_t *crtc = &crtcs[c]; 1692 crtc_t *crtc = &crtcs[c];
1693 XRRCrtcInfo *crtc_info = crtc->crtc_info; 1693 XRRCrtcInfo *crtc_info = crtc->crtc_info;
1694 1694
1695 /* if this crtc is already disabled, skip it */ 1695 /* if this crtc is already disabled, skip it */
1696 if (crtc_info->mode == None)  1696 if (crtc_info->mode == None)
1697 continue; 1697 continue;
1698  1698
1699 /*  1699 /*
1700 * If this crtc is to be left enabled, make 1700 * If this crtc is to be left enabled, make
1701 * sure the old size fits then new screen 1701 * sure the old size fits then new screen
1702 */ 1702 */
1703 if (crtc->mode_info)  1703 if (crtc->mode_info)
1704 { 1704 {
1705 XRRModeInfo *old_mode = find_mode_by_xid (crtc_info->mode); 1705 XRRModeInfo *old_mode = find_mode_by_xid (crtc_info->mode);
1706 int x, y, w, h; 1706 int x, y, w, h;
1707 box_t bounds; 1707 box_t bounds;
1708 1708
1709 if (!old_mode)  1709 if (!old_mode)
1710 panic (RRSetConfigFailed, crtc); 1710 panic (RRSetConfigFailed, crtc);
1711  1711
1712 /* old position and size information */ 1712 /* old position and size information */
1713 mode_geometry (old_mode, crtc_info->rotation, 1713 mode_geometry (old_mode, crtc_info->rotation,
1714 &crtc->current_transform.transform, 1714 &crtc->current_transform.transform,
1715 &bounds); 1715 &bounds);
1716 1716
1717 x = crtc_info->x + bounds.x1; 1717 x = crtc_info->x + bounds.x1;
1718 y = crtc_info->y + bounds.y1; 1718 y = crtc_info->y + bounds.y1;
1719 w = bounds.x2 - bounds.x1; 1719 w = bounds.x2 - bounds.x1;
1720 h = bounds.y2 - bounds.y1; 1720 h = bounds.y2 - bounds.y1;
1721 1721
1722 /* if it fits, skip it */ 1722 /* if it fits, skip it */
1723 if (x + w <= fb_width && y + h <= fb_height)  1723 if (x + w <= fb_width && y + h <= fb_height)
1724 continue; 1724 continue;
1725 crtc->changing = True; 1725 crtc->changing = True;
1726 } 1726 }
1727 s = crtc_disable (crtc); 1727 s = crtc_disable (crtc);
1728 if (s != RRSetConfigSuccess) 1728 if (s != RRSetConfigSuccess)
1729 panic (s, crtc); 1729 panic (s, crtc);
1730 } 1730 }
1731 1731
1732 /* 1732 /*
1733 * Set the screen size 1733 * Set the screen size
1734 */ 1734 */
1735 screen_apply (); 1735 screen_apply ();
1736  1736
1737 /* 1737 /*
1738 * Set crtcs 1738 * Set crtcs
1739 */ 1739 */
1740 1740
1741 for (c = 0; c < res->ncrtc; c++) 1741 for (c = 0; c < res->ncrtc; c++)
1742 { 1742 {
1743 crtc_t *crtc = &crtcs[c]; 1743 crtc_t *crtc = &crtcs[c];
1744  1744
1745 s = crtc_apply (crtc); 1745 s = crtc_apply (crtc);
1746 if (s != RRSetConfigSuccess) 1746 if (s != RRSetConfigSuccess)
1747 panic (s, crtc); 1747 panic (s, crtc);
1748 } 1748 }
1749 1749
1750 set_primary (); 1750 set_primary ();
1751 1751
1752 /* 1752 /*
1753 * Release the server grab and let all clients 1753 * Release the server grab and let all clients
1754 * respond to the updated state 1754 * respond to the updated state
1755 */ 1755 */
1756 if (grab_server) 1756 if (grab_server)
1757 XUngrabServer (dpy); 1757 XUngrabServer (dpy);
1758} 1758}
1759 1759
1760/* 1760/*
1761 * Use current output state to complete the output list 1761 * Use current output state to complete the output list
1762 */ 1762 */
1763static void 1763static void
1764get_outputs (void) 1764get_outputs (void)
1765{ 1765{
1766 int o; 1766 int o;
1767 output_t *q; 1767 output_t *q;
1768  1768
1769 for (o = 0; o < res->noutput; o++) 1769 for (o = 0; o < res->noutput; o++)
1770 { 1770 {
1771 XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]); 1771 XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]);
1772 output_t *output; 1772 output_t *output;
1773 name_t output_name; 1773 name_t output_name;
1774 if (!output_info) fatal ("could not get output 0x%lx information\n", res->outputs[o]); 1774 if (!output_info) fatal ("could not get output 0x%lx information\n", res->outputs[o]);
1775 set_name_xid (&output_name, res->outputs[o]); 1775 set_name_xid (&output_name, res->outputs[o]);
1776 set_name_index (&output_name, o); 1776 set_name_index (&output_name, o);
1777 set_name_string (&output_name, output_info->name); 1777 set_name_string (&output_name, output_info->name);
1778 output = find_output (&output_name); 1778 output = find_output (&output_name);
1779 if (!output) 1779 if (!output)
1780 { 1780 {
1781 output = add_output (); 1781 output = add_output ();
1782 set_name_all (&output->output, &output_name); 1782 set_name_all (&output->output, &output_name);
1783 /* 1783 /*
1784 * When global --automatic mode is set, turn on connected but off 1784 * When global --automatic mode is set, turn on connected but off
1785 * outputs, turn off disconnected but on outputs 1785 * outputs, turn off disconnected but on outputs
1786 */ 1786 */
1787 if (automatic) 1787 if (automatic)
1788 { 1788 {
1789 switch (output_info->connection) { 1789 switch (output_info->connection) {
1790 case RR_Connected: 1790 case RR_Connected:
1791 if (!output_info->crtc) { 1791 if (!output_info->crtc) {
1792 output->changes |= changes_automatic; 1792 output->changes |= changes_automatic;
1793 output->automatic = True; 1793 output->automatic = True;
1794 } 1794 }
1795 break; 1795 break;
1796 case RR_Disconnected: 1796 case RR_Disconnected:
1797 if (output_info->crtc) 1797 if (output_info->crtc)
1798 { 1798 {
1799 output->changes |= changes_automatic; 1799 output->changes |= changes_automatic;
1800 output->automatic = True; 1800 output->automatic = True;
1801 } 1801 }
1802 break; 1802 break;
1803 } 1803 }
1804 } 1804 }
1805 } 1805 }
1806 output->found = True; 1806 output->found = True;
1807 1807
1808 /* 1808 /*
1809 * Automatic mode -- track connection state and enable/disable outputs 1809 * Automatic mode -- track connection state and enable/disable outputs
1810 * as necessary 1810 * as necessary
1811 */ 1811 */
1812 if (output->automatic) 1812 if (output->automatic)
1813 { 1813 {
1814 switch (output_info->connection) { 1814 switch (output_info->connection) {
1815 case RR_Connected: 1815 case RR_Connected:
1816 case RR_UnknownConnection: 1816 case RR_UnknownConnection:
1817 if ((!(output->changes & changes_mode))) 1817 if ((!(output->changes & changes_mode)))
1818 { 1818 {
1819 set_name_preferred (&output->mode); 1819 set_name_preferred (&output->mode);
1820 output->changes |= changes_mode; 1820 output->changes |= changes_mode;
1821 } 1821 }
1822 break; 1822 break;
1823 case RR_Disconnected: 1823 case RR_Disconnected:
1824 if ((!(output->changes & changes_mode))) 1824 if ((!(output->changes & changes_mode)))
1825 { 1825 {
1826 set_name_xid (&output->mode, None); 1826 set_name_xid (&output->mode, None);
1827 set_name_xid (&output->crtc, None); 1827 set_name_xid (&output->crtc, None);
1828 output->changes |= changes_mode; 1828 output->changes |= changes_mode;
1829 output->changes |= changes_crtc; 1829 output->changes |= changes_crtc;
1830 } 1830 }
1831 break; 1831 break;
1832 } 1832 }
1833 } 1833 }
1834 1834
1835 set_output_info (output, res->outputs[o], output_info); 1835 set_output_info (output, res->outputs[o], output_info);
1836 } 1836 }
1837 for (q = all_outputs; q; q = q->next) 1837 for (q = all_outputs; q; q = q->next)
1838 { 1838 {
1839 if (!q->found) 1839 if (!q->found)
1840 { 1840 {
1841 fprintf(stderr, "warning: output %s not found; ignoring\n", 1841 fprintf(stderr, "warning: output %s not found; ignoring\n",
1842 q->output.string); 1842 q->output.string);
1843 } 1843 }
1844 } 1844 }
1845} 1845}
1846 1846
1847static void 1847static void
1848mark_changing_crtcs (void) 1848mark_changing_crtcs (void)
1849{ 1849{
1850 int c; 1850 int c;
1851 1851
1852 for (c = 0; c < num_crtcs; c++) 1852 for (c = 0; c < num_crtcs; c++)
1853 { 1853 {
1854 crtc_t *crtc = &crtcs[c]; 1854 crtc_t *crtc = &crtcs[c];
1855 int o; 1855 int o;
1856 output_t *output; 1856 output_t *output;
1857 1857
1858 /* walk old output list (to catch disables) */ 1858 /* walk old output list (to catch disables) */
1859 for (o = 0; o < crtc->crtc_info->noutput; o++) 1859 for (o = 0; o < crtc->crtc_info->noutput; o++)
1860 { 1860 {
1861 output = find_output_by_xid (crtc->crtc_info->outputs[o]); 1861 output = find_output_by_xid (crtc->crtc_info->outputs[o]);
1862 if (!output) fatal ("cannot find output 0x%lx\n", 1862 if (!output) fatal ("cannot find output 0x%lx\n",
1863 crtc->crtc_info->outputs[o]); 1863 crtc->crtc_info->outputs[o]);
1864 if (output->changes) 1864 if (output->changes)
1865 crtc->changing = True; 1865 crtc->changing = True;
1866 } 1866 }
1867 /* walk new output list */ 1867 /* walk new output list */
1868 for (o = 0; o < crtc->noutput; o++) 1868 for (o = 0; o < crtc->noutput; o++)
1869 { 1869 {
1870 output = crtc->outputs[o]; 1870 output = crtc->outputs[o];
1871 if (output->changes) 1871 if (output->changes)
1872 crtc->changing = True; 1872 crtc->changing = True;
1873 } 1873 }
1874 } 1874 }
1875} 1875}
1876 1876
1877/* 1877/*
1878 * Test whether 'crtc' can be used for 'output' 1878 * Test whether 'crtc' can be used for 'output'
1879 */ 1879 */
1880static Bool 1880static Bool
1881check_crtc_for_output (crtc_t *crtc, output_t *output) 1881check_crtc_for_output (crtc_t *crtc, output_t *output)
1882{ 1882{
1883 int c; 1883 int c;
1884 int l; 1884 int l;
1885 output_t *other; 1885 output_t *other;
1886  1886
1887 for (c = 0; c < output->output_info->ncrtc; c++) 1887 for (c = 0; c < output->output_info->ncrtc; c++)
1888 if (output->output_info->crtcs[c] == crtc->crtc.xid) 1888 if (output->output_info->crtcs[c] == crtc->crtc.xid)
1889 break; 1889 break;
1890 if (c == output->output_info->ncrtc) 1890 if (c == output->output_info->ncrtc)
1891 return False; 1891 return False;
1892 for (other = all_outputs; other; other = other->next) 1892 for (other = all_outputs; other; other = other->next)
1893 { 1893 {
1894 if (other == output) 1894 if (other == output)
1895 continue; 1895 continue;
1896 1896
1897 if (other->mode_info == NULL) 1897 if (other->mode_info == NULL)
1898 continue; 1898 continue;
1899 1899
1900 if (other->crtc_info != crtc) 1900 if (other->crtc_info != crtc)
1901 continue; 1901 continue;
1902 1902
1903 /* see if the output connected to the crtc can clone to this output */ 1903 /* see if the output connected to the crtc can clone to this output */
1904 for (l = 0; l < output->output_info->nclone; l++) 1904 for (l = 0; l < output->output_info->nclone; l++)
1905 if (output->output_info->clones[l] == other->output.xid) 1905 if (output->output_info->clones[l] == other->output.xid)
1906 break; 1906 break;
1907 /* not on the list, can't clone */ 1907 /* not on the list, can't clone */
1908 if (l == output->output_info->nclone)  1908 if (l == output->output_info->nclone)
1909 return False; 1909 return False;
1910 } 1910 }
1911 1911
1912 if (crtc->noutput) 1912 if (crtc->noutput)
1913 { 1913 {
1914 /* make sure the state matches */ 1914 /* make sure the state matches */
1915 if (crtc->mode_info != output->mode_info) 1915 if (crtc->mode_info != output->mode_info)
1916 return False; 1916 return False;
1917 if (crtc->x != output->x) 1917 if (crtc->x != output->x)
1918 return False; 1918 return False;
1919 if (crtc->y != output->y) 1919 if (crtc->y != output->y)
1920 return False; 1920 return False;
1921 if (crtc->rotation != output->rotation) 1921 if (crtc->rotation != output->rotation)
1922 return False; 1922 return False;
1923 if (!equal_transform (&crtc->current_transform, &output->transform)) 1923 if (!equal_transform (&crtc->current_transform, &output->transform))
1924 return False; 1924 return False;
1925 } 1925 }
1926 else if (crtc->crtc_info->noutput) 1926 else if (crtc->crtc_info->noutput)
1927 { 1927 {
1928 /* make sure the state matches the already used state */ 1928 /* make sure the state matches the already used state */
1929 XRRModeInfo *mode = find_mode_by_xid (crtc->crtc_info->mode); 1929 XRRModeInfo *mode = find_mode_by_xid (crtc->crtc_info->mode);
1930 1930
1931 if (mode != output->mode_info) 1931 if (mode != output->mode_info)
1932 return False; 1932 return False;
1933 if (crtc->crtc_info->x != output->x) 1933 if (crtc->crtc_info->x != output->x)
1934 return False; 1934 return False;
1935 if (crtc->crtc_info->y != output->y) 1935 if (crtc->crtc_info->y != output->y)
1936 return False; 1936 return False;
1937 if (crtc->crtc_info->rotation != output->rotation) 1937 if (crtc->crtc_info->rotation != output->rotation)
1938 return False; 1938 return False;
1939 } 1939 }
1940 return True; 1940 return True;
1941} 1941}
1942 1942
1943static crtc_t * 1943static crtc_t *
1944find_crtc_for_output (output_t *output) 1944find_crtc_for_output (output_t *output)
1945{ 1945{
1946 int c; 1946 int c;
1947 1947
1948 for (c = 0; c < output->output_info->ncrtc; c++) 1948 for (c = 0; c < output->output_info->ncrtc; c++)
1949 { 1949 {
1950 crtc_t *crtc; 1950 crtc_t *crtc;
1951 1951
1952 crtc = find_crtc_by_xid (output->output_info->crtcs[c]); 1952 crtc = find_crtc_by_xid (output->output_info->crtcs[c]);
1953 if (!crtc) fatal ("cannot find crtc 0x%lx\n", output->output_info->crtcs[c]); 1953 if (!crtc) fatal ("cannot find crtc 0x%lx\n", output->output_info->crtcs[c]);
1954 1954
1955 if (check_crtc_for_output (crtc, output)) 1955 if (check_crtc_for_output (crtc, output))
1956 return crtc; 1956 return crtc;
1957 } 1957 }
1958 return NULL; 1958 return NULL;
1959} 1959}
1960 1960
1961static void 1961static void
1962set_positions (void) 1962set_positions (void)
1963{ 1963{
1964 output_t *output; 1964 output_t *output;
1965 Bool keep_going; 1965 Bool keep_going;
1966 Bool any_set; 1966 Bool any_set;
1967 int min_x, min_y; 1967 int min_x, min_y;
1968 1968
1969 for (;;) 1969 for (;;)
1970 { 1970 {
1971 any_set = False; 1971 any_set = False;
1972 keep_going = False; 1972 keep_going = False;
1973 for (output = all_outputs; output; output = output->next) 1973 for (output = all_outputs; output; output = output->next)
1974 { 1974 {
1975 output_t *relation; 1975 output_t *relation;
1976 name_t relation_name; 1976 name_t relation_name;
1977 1977
1978 if (!(output->changes & changes_relation)) continue; 1978 if (!(output->changes & changes_relation)) continue;
1979  1979
1980 if (output->mode_info == NULL) continue; 1980 if (output->mode_info == NULL) continue;
1981 1981
1982 init_name (&relation_name); 1982 init_name (&relation_name);
1983 set_name_string (&relation_name, output->relative_to); 1983 set_name_string (&relation_name, output->relative_to);
1984 relation = find_output (&relation_name); 1984 relation = find_output (&relation_name);
1985 if (!relation) fatal ("cannot find output \"%s\"\n", output->relative_to); 1985 if (!relation) fatal ("cannot find output \"%s\"\n", output->relative_to);
1986  1986
1987 if (relation->mode_info == NULL)  1987 if (relation->mode_info == NULL)
1988 { 1988 {
1989 output->x = 0; 1989 output->x = 0;
1990 output->y = 0; 1990 output->y = 0;
1991 output->changes |= changes_position; 1991 output->changes |= changes_position;
1992 any_set = True; 1992 any_set = True;
1993 continue; 1993 continue;
1994 } 1994 }
1995 /* 1995 /*
1996 * Make sure the dependent object has been set in place 1996 * Make sure the dependent object has been set in place
1997 */ 1997 */
1998 if ((relation->changes & changes_relation) &&  1998 if ((relation->changes & changes_relation) &&
1999 !(relation->changes & changes_position)) 1999 !(relation->changes & changes_position))
2000 { 2000 {
2001 keep_going = True; 2001 keep_going = True;
2002 continue; 2002 continue;
2003 } 2003 }
2004  2004
2005 switch (output->relation) { 2005 switch (output->relation) {
2006 case relation_left_of: 2006 case relation_left_of:
2007 output->y = relation->y; 2007 output->y = relation->y;
2008 output->x = relation->x - mode_width (output->mode_info, output->rotation); 2008 output->x = relation->x - mode_width (output->mode_info, output->rotation);
2009 break; 2009 break;
2010 case relation_right_of: 2010 case relation_right_of:
2011 output->y = relation->y; 2011 output->y = relation->y;
2012 output->x = relation->x + mode_width (relation->mode_info, relation->rotation); 2012 output->x = relation->x + mode_width (relation->mode_info, relation->rotation);
2013 break; 2013 break;
2014 case relation_above: 2014 case relation_above:
2015 output->x = relation->x; 2015 output->x = relation->x;
2016 output->y = relation->y - mode_height (output->mode_info, output->rotation); 2016 output->y = relation->y - mode_height (output->mode_info, output->rotation);
2017 break; 2017 break;
2018 case relation_below: 2018 case relation_below:
2019 output->x = relation->x; 2019 output->x = relation->x;
2020 output->y = relation->y + mode_height (relation->mode_info, relation->rotation); 2020 output->y = relation->y + mode_height (relation->mode_info, relation->rotation);
2021 break; 2021 break;
2022 case relation_same_as: 2022 case relation_same_as:
2023 output->x = relation->x; 2023 output->x = relation->x;
2024 output->y = relation->y; 2024 output->y = relation->y;
2025 } 2025 }
2026 output->changes |= changes_position; 2026 output->changes |= changes_position;
2027 any_set = True; 2027 any_set = True;
2028 } 2028 }
2029 if (!keep_going) 2029 if (!keep_going)
2030 break; 2030 break;
2031 if (!any_set) 2031 if (!any_set)
2032 fatal ("loop in relative position specifications\n"); 2032 fatal ("loop in relative position specifications\n");
2033 } 2033 }
2034 2034
2035 /* 2035 /*
2036 * Now normalize positions so the upper left corner of all outputs is at 0,0 2036 * Now normalize positions so the upper left corner of all outputs is at 0,0
2037 */ 2037 */
2038 min_x = 32768; 2038 min_x = 32768;
2039 min_y = 32768; 2039 min_y = 32768;
2040 for (output = all_outputs; output; output = output->next) 2040 for (output = all_outputs; output; output = output->next)
2041 { 2041 {
2042 if (output->mode_info == NULL) continue; 2042 if (output->mode_info == NULL) continue;
2043  2043
2044 if (output->x < min_x) min_x = output->x; 2044 if (output->x < min_x) min_x = output->x;
2045 if (output->y < min_y) min_y = output->y; 2045 if (output->y < min_y) min_y = output->y;
2046 } 2046 }
2047 if (min_x || min_y) 2047 if (min_x || min_y)
2048 { 2048 {
2049 /* move all outputs */ 2049 /* move all outputs */
2050 for (output = all_outputs; output; output = output->next) 2050 for (output = all_outputs; output; output = output->next)
2051 { 2051 {
2052 if (output->mode_info == NULL) continue; 2052 if (output->mode_info == NULL) continue;
2053 2053
2054 output->x -= min_x; 2054 output->x -= min_x;
2055 output->y -= min_y; 2055 output->y -= min_y;
2056 output->changes |= changes_position; 2056 output->changes |= changes_position;
2057 } 2057 }
2058 } 2058 }
2059} 2059}
2060 2060
2061static void 2061static void
2062set_screen_size (void) 2062set_screen_size (void)
2063{ 2063{
2064 output_t *output; 2064 output_t *output;
2065 Bool fb_specified = fb_width != 0 && fb_height != 0; 2065 Bool fb_specified = fb_width != 0 && fb_height != 0;
2066  2066
2067 for (output = all_outputs; output; output = output->next) 2067 for (output = all_outputs; output; output = output->next)
2068 { 2068 {
2069 XRRModeInfo *mode_info = output->mode_info; 2069 XRRModeInfo *mode_info = output->mode_info;
2070 int x, y, w, h; 2070 int x, y, w, h;
2071 box_t bounds; 2071 box_t bounds;
2072  2072
2073 if (!mode_info) continue; 2073 if (!mode_info) continue;
2074  2074
2075 mode_geometry (mode_info, output->rotation, 2075 mode_geometry (mode_info, output->rotation,
2076 &output->transform.transform, 2076 &output->transform.transform,
2077 &bounds); 2077 &bounds);
2078 x = output->x + bounds.x1; 2078 x = output->x + bounds.x1;
2079 y = output->y + bounds.y1; 2079 y = output->y + bounds.y1;
2080 w = bounds.x2 - bounds.x1; 2080 w = bounds.x2 - bounds.x1;
2081 h = bounds.y2 - bounds.y1; 2081 h = bounds.y2 - bounds.y1;
2082 /* make sure output fits in specified size */ 2082 /* make sure output fits in specified size */
2083 if (fb_specified) 2083 if (fb_specified)
2084 { 2084 {
2085 if (x + w > fb_width || y + h > fb_height) 2085 if (x + w > fb_width || y + h > fb_height)
2086 warning ("specified screen %dx%d not large enough for output %s (%dx%d+%d+%d)\n", 2086 warning ("specified screen %dx%d not large enough for output %s (%dx%d+%d+%d)\n",
2087 fb_width, fb_height, output->output.string, w, h, x, y); 2087 fb_width, fb_height, output->output.string, w, h, x, y);
2088 } 2088 }
2089 /* fit fb to output */ 2089 /* fit fb to output */
2090 else 2090 else
2091 { 2091 {
2092 XRRPanning *pan; 2092 XRRPanning *pan;
2093 if (x + w > fb_width) 2093 if (x + w > fb_width)
2094 fb_width = x + w; 2094 fb_width = x + w;
2095 if (y + h > fb_height) 2095 if (y + h > fb_height)
2096 fb_height = y + h; 2096 fb_height = y + h;
2097 if (output->changes & changes_panning) 2097 if (output->changes & changes_panning)
2098 pan = &output->panning; 2098 pan = &output->panning;
2099 else 2099 else
2100 pan = output->crtc_info ? output->crtc_info->panning_info : NULL; 2100 pan = output->crtc_info ? output->crtc_info->panning_info : NULL;
2101 if (pan && pan->left + pan->width > fb_width) 2101 if (pan && pan->left + pan->width > fb_width)
2102 fb_width = pan->left + pan->width; 2102 fb_width = pan->left + pan->width;
2103 if (pan && pan->top + pan->height > fb_height) 2103 if (pan && pan->top + pan->height > fb_height)
2104 fb_height = pan->top + pan->height; 2104 fb_height = pan->top + pan->height;
2105 } 2105 }
2106 }  2106 }
2107 2107
2108 if (fb_width > maxWidth || fb_height > maxHeight) 2108 if (fb_width > maxWidth || fb_height > maxHeight)
2109 fatal ("screen cannot be larger than %dx%d (desired size %dx%d)\n", 2109 fatal ("screen cannot be larger than %dx%d (desired size %dx%d)\n",
2110 maxWidth, maxHeight, fb_width, fb_height); 2110 maxWidth, maxHeight, fb_width, fb_height);
2111 if (fb_specified) 2111 if (fb_specified)
2112 { 2112 {
2113 if (fb_width < minWidth || fb_height < minHeight) 2113 if (fb_width < minWidth || fb_height < minHeight)
2114 fatal ("screen must be at least %dx%d\n", minWidth, minHeight); 2114 fatal ("screen must be at least %dx%d\n", minWidth, minHeight);
2115 } 2115 }
2116 else 2116 else
2117 { 2117 {
2118 if (fb_width < minWidth) fb_width = minWidth; 2118 if (fb_width < minWidth) fb_width = minWidth;
2119 if (fb_height < minHeight) fb_height = minHeight; 2119 if (fb_height < minHeight) fb_height = minHeight;
2120 } 2120 }
2121} 2121}
2122  2122
2123 2123
2124static void 2124static void
2125disable_outputs (output_t *outputs) 2125disable_outputs (output_t *outputs)
2126{ 2126{
2127 while (outputs) 2127 while (outputs)
2128 { 2128 {
2129 outputs->crtc_info = NULL; 2129 outputs->crtc_info = NULL;
2130 outputs = outputs->next; 2130 outputs = outputs->next;
2131 } 2131 }
2132} 2132}
2133 2133
2134/* 2134/*
2135 * find the best mapping from output to crtc available 2135 * find the best mapping from output to crtc available
2136 */ 2136 */
2137static int 2137static int
2138pick_crtcs_score (output_t *outputs) 2138pick_crtcs_score (output_t *outputs)
2139{ 2139{
2140 output_t *output; 2140 output_t *output;
2141 int best_score; 2141 int best_score;
2142 int my_score; 2142 int my_score;
2143 int score; 2143 int score;
2144 crtc_t *best_crtc; 2144 crtc_t *best_crtc;
2145 int c; 2145 int c;
2146  2146
2147 if (!outputs) 2147 if (!outputs)
2148 return 0; 2148 return 0;
2149  2149
2150 output = outputs; 2150 output = outputs;
2151 outputs = outputs->next; 2151 outputs = outputs->next;
2152 /* 2152 /*
2153 * Score with this output disabled 2153 * Score with this output disabled
2154 */ 2154 */
2155 output->crtc_info = NULL; 2155 output->crtc_info = NULL;
2156 best_score = pick_crtcs_score (outputs); 2156 best_score = pick_crtcs_score (outputs);
2157 if (output->mode_info == NULL) 2157 if (output->mode_info == NULL)
2158 return best_score; 2158 return best_score;
2159 2159
2160 best_crtc = NULL; 2160 best_crtc = NULL;
2161 /*  2161 /*
2162 * Now score with this output any valid crtc 2162 * Now score with this output any valid crtc
2163 */ 2163 */
2164 for (c = 0; c < output->output_info->ncrtc; c++) 2164 for (c = 0; c < output->output_info->ncrtc; c++)
2165 { 2165 {
2166 crtc_t *crtc; 2166 crtc_t *crtc;
2167 2167
2168 crtc = find_crtc_by_xid (output->output_info->crtcs[c]); 2168 crtc = find_crtc_by_xid (output->output_info->crtcs[c]);
2169 if (!crtc) 2169 if (!crtc)
2170 fatal ("cannot find crtc 0x%lx\n", output->output_info->crtcs[c]); 2170 fatal ("cannot find crtc 0x%lx\n", output->output_info->crtcs[c]);
2171  2171
2172 /* reset crtc allocation for following outputs */ 2172 /* reset crtc allocation for following outputs */
2173 disable_outputs (outputs); 2173 disable_outputs (outputs);
2174 if (!check_crtc_for_output (crtc, output)) 2174 if (!check_crtc_for_output (crtc, output))
2175 continue; 2175 continue;
2176  2176
2177 my_score = 1000; 2177 my_score = 1000;
2178 /* slight preference for existing connections */ 2178 /* slight preference for existing connections */
2179 if (crtc == output->current_crtc_info) 2179 if (crtc == output->current_crtc_info)
2180 my_score++; 2180 my_score++;
2181 2181
2182 output->crtc_info = crtc; 2182 output->crtc_info = crtc;
2183 score = my_score + pick_crtcs_score (outputs); 2183 score = my_score + pick_crtcs_score (outputs);
2184 if (score > best_score) 2184 if (score > best_score)
2185 { 2185 {
2186 best_crtc = crtc; 2186 best_crtc = crtc;
2187 best_score = score; 2187 best_score = score;
2188 } 2188 }
2189 } 2189 }
2190 if (output->crtc_info != best_crtc) 2190 if (output->crtc_info != best_crtc)
2191 output->crtc_info = best_crtc; 2191 output->crtc_info = best_crtc;
2192 /* 2192 /*
2193 * Reset other outputs based on this one using the best crtc 2193 * Reset other outputs based on this one using the best crtc
2194 */ 2194 */
2195 (void) pick_crtcs_score (outputs); 2195 (void) pick_crtcs_score (outputs);
2196 2196
2197 return best_score; 2197 return best_score;
2198} 2198}
2199 2199
2200/* 2200/*
2201 * Pick crtcs for any changing outputs that don't have one 2201 * Pick crtcs for any changing outputs that don't have one
2202 */ 2202 */
2203static void 2203static void
2204pick_crtcs (void) 2204pick_crtcs (void)
2205{ 2205{
2206 output_t *output; 2206 output_t *output;
2207 2207
2208 /* 2208 /*
2209 * First try to match up newly enabled outputs with spare crtcs 2209 * First try to match up newly enabled outputs with spare crtcs
2210 */ 2210 */
2211 for (output = all_outputs; output; output = output->next) 2211 for (output = all_outputs; output; output = output->next)
2212 { 2212 {
2213 if (output->changes && output->mode_info) 2213 if (output->changes && output->mode_info)
2214 { 2214 {
2215 if (output->crtc_info) { 2215 if (output->crtc_info) {
2216 if (output->crtc_info->crtc_info->noutput > 0 && 2216 if (output->crtc_info->crtc_info->noutput > 0 &&
2217 (output->crtc_info->crtc_info->noutput > 1 || 2217 (output->crtc_info->crtc_info->noutput > 1 ||
2218 output != find_output_by_xid (output->crtc_info->crtc_info->outputs[0]))) 2218 output != find_output_by_xid (output->crtc_info->crtc_info->outputs[0])))
2219 break; 2219 break;
2220 } else { 2220 } else {
2221 output->crtc_info = find_crtc_for_output (output); 2221 output->crtc_info = find_crtc_for_output (output);
2222 if (!output->crtc_info) 2222 if (!output->crtc_info)
2223 break; 2223 break;
2224 } 2224 }
2225 } 2225 }
2226 } 2226 }
2227 /* 2227 /*
2228 * Everyone is happy 2228 * Everyone is happy
2229 */ 2229 */
2230 if (!output) 2230 if (!output)
2231 return; 2231 return;
2232 /* 2232 /*
2233 * When the simple way fails, see if there is a way 2233 * When the simple way fails, see if there is a way
2234 * to swap crtcs around and make things work 2234 * to swap crtcs around and make things work
2235 */ 2235 */
2236 for (output = all_outputs; output; output = output->next) 2236 for (output = all_outputs; output; output = output->next)
2237 output->current_crtc_info = output->crtc_info; 2237 output->current_crtc_info = output->crtc_info;
2238 pick_crtcs_score (all_outputs); 2238 pick_crtcs_score (all_outputs);
2239 for (output = all_outputs; output; output = output->next) 2239 for (output = all_outputs; output; output = output->next)
2240 { 2240 {
2241 if (output->mode_info && !output->crtc_info) 2241 if (output->mode_info && !output->crtc_info)
2242 fatal ("cannot find crtc for output %s\n", output->output.string); 2242 fatal ("cannot find crtc for output %s\n", output->output.string);
2243 if (!output->changes && output->crtc_info != output->current_crtc_info) 2243 if (!output->changes && output->crtc_info != output->current_crtc_info)
2244 output->changes |= changes_crtc; 2244 output->changes |= changes_crtc;
2245 } 2245 }
2246} 2246}
2247 2247
2248static int 2248static int
2249check_strtol(char *s) 2249check_strtol(char *s)
2250{ 2250{
2251 char *endptr; 2251 char *endptr;
2252 int result = strtol(s, &endptr, 10); 2252 int result = strtol(s, &endptr, 10);
2253 if (s == endptr) 2253 if (s == endptr)
2254 argerr ("failed to parse '%s' as a number\n", s); 2254 argerr ("failed to parse '%s' as a number\n", s);
2255 return result; 2255 return result;
2256} 2256}
2257 2257
2258static double 2258static double
2259check_strtod(char *s) 2259check_strtod(char *s)
2260{ 2260{
2261 char *endptr; 2261 char *endptr;
2262 double result = strtod(s, &endptr); 2262 double result = strtod(s, &endptr);
2263 if (s == endptr) 2263 if (s == endptr)
2264 argerr ("failed to parse '%s' as a number\n", s); 2264 argerr ("failed to parse '%s' as a number\n", s);
2265 return result; 2265 return result;
2266} 2266}
2267 2267
2268 2268
2269static void * 2269static void *
2270property_values_from_string(const char *str, const Atom type, const int format, 2270property_values_from_string(const char *str, const Atom type, const int format,
2271 int *returned_nitems) 2271 int *returned_nitems)
2272{ 2272{
2273 char *token, *tmp; 2273 char *token, *tmp;
2274 void *returned_bytes = NULL; 2274 void *returned_bytes = NULL;
2275 int nitems = 0, bytes_per_item = format / 8; 2275 int nitems = 0, bytes_per_item = format / 8;
2276 2276
2277 if ((type != XA_INTEGER && type != XA_CARDINAL) || 2277 if ((type != XA_INTEGER && type != XA_CARDINAL) ||
2278 (format != 8 && format != 16 && format != 32)) 2278 (format != 8 && format != 16 && format != 32))
2279 { 2279 {
2280 return NULL; 2280 return NULL;
2281 } 2281 }
2282 2282
2283 tmp = strdup (str); 2283 tmp = strdup (str);
2284 2284
2285 for (token = strtok (tmp, ","); token; token = strtok (NULL, ",")) 2285 for (token = strtok (tmp, ","); token; token = strtok (NULL, ","))
2286 { 2286 {
2287 char *endptr; 2287 char *endptr;
2288 long int val = strtol (token, &endptr, 0); 2288 long int val = strtol (token, &endptr, 0);
2289 2289
2290 if (token == endptr || *endptr != '\0') 2290 if (token == endptr || *endptr != '\0')
2291 { 2291 {
2292 argerr ("failed to parse '%s' as a number\n", token); 2292 argerr ("failed to parse '%s' as a number\n", token);
2293 } 2293 }
2294 2294
2295 returned_bytes = realloc (returned_bytes, (nitems + 1) * bytes_per_item); 2295 returned_bytes = realloc (returned_bytes, (nitems + 1) * bytes_per_item);
2296 2296
2297 if (type == XA_INTEGER && format == 8) 2297 if (type == XA_INTEGER && format == 8)
2298 { 2298 {
2299 int8_t *ptr = returned_bytes; 2299 int8_t *ptr = returned_bytes;
2300 ptr[nitems] = (int8_t) val; 2300 ptr[nitems] = (int8_t) val;
2301 } 2301 }
2302 else if (type == XA_INTEGER && format == 16) 2302 else if (type == XA_INTEGER && format == 16)
2303 { 2303 {
2304 int16_t *ptr = returned_bytes; 2304 int16_t *ptr = returned_bytes;
2305 ptr[nitems] = (int16_t) val; 2305 ptr[nitems] = (int16_t) val;
2306 } 2306 }
2307 else if (type == XA_INTEGER && format == 32) 2307 else if (type == XA_INTEGER && format == 32)
2308 { 2308 {
2309 int32_t *ptr = returned_bytes; 2309 int32_t *ptr = returned_bytes;
2310 ptr[nitems] = (int32_t) val; 2310 ptr[nitems] = (int32_t) val;
2311 } 2311 }
2312 else if (type == XA_CARDINAL && format == 8) 2312 else if (type == XA_CARDINAL && format == 8)
2313 { 2313 {
2314 uint8_t *ptr = returned_bytes; 2314 uint8_t *ptr = returned_bytes;
2315 ptr[nitems] = (uint8_t) val; 2315 ptr[nitems] = (uint8_t) val;
2316 } 2316 }
2317 else if (type == XA_CARDINAL && format == 16) 2317 else if (type == XA_CARDINAL && format == 16)
2318 { 2318 {
2319 uint16_t *ptr = returned_bytes; 2319 uint16_t *ptr = returned_bytes;
2320 ptr[nitems] = (uint16_t) val; 2320 ptr[nitems] = (uint16_t) val;
2321 } 2321 }
2322 else if (type == XA_CARDINAL && format == 32) 2322 else if (type == XA_CARDINAL && format == 32)
2323 { 2323 {
2324 uint32_t *ptr = returned_bytes; 2324 uint32_t *ptr = returned_bytes;
2325 ptr[nitems] = (uint32_t) val; 2325 ptr[nitems] = (uint32_t) val;
2326 } 2326 }
2327 else 2327 else
2328 { 2328 {
2329 free (tmp); 2329 free (tmp);
2330 free (returned_bytes); 2330 free (returned_bytes);
2331 return NULL; 2331 return NULL;
2332 } 2332 }
2333 2333
2334 nitems++; 2334 nitems++;
2335 } 2335 }
2336 2336
2337 free (tmp); 2337 free (tmp);
2338 2338
2339 *returned_nitems = nitems; 2339 *returned_nitems = nitems;
2340 return returned_bytes; 2340 return returned_bytes;
2341} 2341}
2342 2342
2343 2343
2344static void 2344static void
2345print_output_property_value(Bool is_edid, 2345print_output_property_value(Bool is_edid,
2346 int value_format, /* 8, 16, 32 */ 2346 int value_format, /* 8, 16, 32 */
2347 Atom value_type, /* XA_{ATOM,INTEGER,CARDINAL} */ 2347 Atom value_type, /* XA_{ATOM,INTEGER,CARDINAL} */
2348 const void *value_bytes) 2348 const void *value_bytes)
2349{ 2349{
2350 /* special-case the EDID */ 2350 /* special-case the EDID */
2351 if (is_edid && value_format == 8) 2351 if (is_edid && value_format == 8)
2352 { 2352 {
2353 const uint8_t *val = value_bytes; 2353 const uint8_t *val = value_bytes;
2354 printf ("%02" PRIx8, *val); 2354 printf ("%02" PRIx8, *val);
2355 return; 2355 return;
2356 } 2356 }
2357 2357
2358 if (value_type == XA_ATOM && value_format == 32) 2358 if (value_type == XA_ATOM && value_format == 32)
2359 { 2359 {
2360 const Atom *val = value_bytes; 2360 const Atom *val = value_bytes;
2361 char *str = XGetAtomName (dpy, *val); 2361 char *str = XGetAtomName (dpy, *val);
2362 if (str != NULL) 2362 if (str != NULL)
2363 { 2363 {
2364 printf ("%s", str); 2364 printf ("%s", str);
2365 XFree (str); 2365 XFree (str);
2366 return; 2366 return;
2367 } 2367 }
2368 } 2368 }
2369 2369
2370 if (value_type == XA_INTEGER) 2370 if (value_type == XA_INTEGER)
2371 { 2371 {
2372 if (value_format == 8) 2372 if (value_format == 8)
2373 { 2373 {
2374 const int8_t *val = value_bytes; 2374 const int8_t *val = value_bytes;
2375 printf ("%" PRId8, *val); 2375 printf ("%" PRId8, *val);
2376 return; 2376 return;
2377 } 2377 }
2378 if (value_format == 16) 2378 if (value_format == 16)
2379 { 2379 {
2380 const int16_t *val = value_bytes; 2380 const int16_t *val = value_bytes;
2381 printf ("%" PRId16, *val); 2381 printf ("%" PRId16, *val);
2382 return; 2382 return;
2383 } 2383 }
2384 if (value_format == 32) 2384 if (value_format == 32)
2385 { 2385 {
2386 const int32_t *val = value_bytes; 2386 const int32_t *val = value_bytes;
2387 printf ("%" PRId32, *val); 2387 printf ("%" PRId32, *val);
2388 return; 2388 return;
2389 } 2389 }
2390 } 2390 }
2391 2391
2392 if (value_type == XA_CARDINAL) 2392 if (value_type == XA_CARDINAL)
2393 { 2393 {
2394 if (value_format == 8) 2394 if (value_format == 8)
2395 { 2395 {
2396 const uint8_t *val = value_bytes; 2396 const uint8_t *val = value_bytes;
2397 printf ("%" PRIu8, *val); 2397 printf ("%" PRIu8, *val);
2398 return; 2398 return;
2399 } 2399 }
2400 if (value_format == 16) 2400 if (value_format == 16)
2401 { 2401 {
2402 const uint16_t *val = value_bytes; 2402 const uint16_t *val = value_bytes;
2403 printf ("%" PRIu16, *val); 2403 printf ("%" PRIu16, *val);
2404 return; 2404 return;
2405 } 2405 }
2406 if (value_format == 32) 2406 if (value_format == 32)
2407 { 2407 {
2408 const uint32_t *val = value_bytes; 2408 const uint32_t *val = value_bytes;
2409 printf ("%" PRIu32, *val); 2409 printf ("%" PRIu32, *val);
2410 return; 2410 return;
2411 } 2411 }
2412 } 2412 }
2413 2413
2414 printf ("?"); 2414 printf ("?");
2415} 2415}
2416 2416
2417static void 2417static void
2418get_providers (void) 2418get_providers (void)
2419{ 2419{
2420 XRRProviderResources *pr; 2420 XRRProviderResources *pr;
2421 int i; 2421 int i;
2422 2422
2423 if (!has_1_4 || providers) 2423 if (!has_1_4 || providers)
2424 return; 2424 return;
2425 2425
2426 pr = XRRGetProviderResources(dpy, root); 2426 pr = XRRGetProviderResources(dpy, root);
2427 num_providers = pr->nproviders; 2427 num_providers = pr->nproviders;
2428 providers = calloc (num_providers, sizeof (provider_t)); 2428 providers = calloc (num_providers, sizeof (provider_t));
2429 if (!providers) 2429 if (!providers)
2430 fatal ("out of memory\n"); 2430 fatal ("out of memory\n");
2431 2431
2432 for (i = 0; i < num_providers; i++) { 2432 for (i = 0; i < num_providers; i++) {
2433 provider_t *provider = &providers[i]; 2433 provider_t *provider = &providers[i];
2434 name_t *name = &provider->provider; 2434 name_t *name = &provider->provider;
2435 XRRProviderInfo *info = XRRGetProviderInfo(dpy, res, pr->providers[i]); 2435 XRRProviderInfo *info = XRRGetProviderInfo(dpy, res, pr->providers[i]);
2436 2436
2437 provider->info = info; 2437 provider->info = info;
2438 set_name_xid (name, pr->providers[i]); 2438 set_name_xid (name, pr->providers[i]);
2439 set_name_index (name, i); 2439 set_name_index (name, i);
2440 set_name_string (name, info->name); 2440 set_name_string (name, info->name);
2441 } 2441 }
2442 2442
2443 XRRFreeProviderResources(pr); 2443 XRRFreeProviderResources(pr);
2444} 2444}
2445 2445
2446static provider_t * 2446static provider_t *
2447find_provider (name_t *name) 2447find_provider (name_t *name)
2448{ 2448{
2449 int i; 2449 int i;
2450 2450
2451 for (i = 0; i < num_providers; i++) { 2451 for (i = 0; i < num_providers; i++) {
2452 provider_t *p = &providers[i]; 2452 provider_t *p = &providers[i];
2453 name_kind_t common = name->kind & p->provider.kind; 2453 name_kind_t common = name->kind & p->provider.kind;
2454 2454
2455 if ((common & name_xid) && name->xid == p->provider.xid) 2455 if ((common & name_xid) && name->xid == p->provider.xid)
2456 return p; 2456 return p;
2457 if ((common & name_string) && !strcmp (name->string, p->provider.string)) 2457 if ((common & name_string) && !strcmp (name->string, p->provider.string))
2458 return p; 2458 return p;
2459 if ((common & name_index) && name->index == p->provider.index) 2459 if ((common & name_index) && name->index == p->provider.index)
2460 return p; 2460 return p;
2461 } 2461 }
2462 2462
2463 printf ("Could not find provider with "); 2463 printf ("Could not find provider with ");
2464 print_name (name); 2464 print_name (name);
2465 printf ("\n"); 2465 printf ("\n");
2466 exit (1); 2466 exit (1);
2467} 2467}
2468 2468
2469 2469
2470int 2470int
2471main (int argc, char **argv) 2471main (int argc, char **argv)
2472{ 2472{
2473 XRRScreenSize *sizes; 2473 XRRScreenSize *sizes;
2474 XRRScreenConfiguration *sc; 2474 XRRScreenConfiguration *sc;
2475 int nsize; 2475 int nsize;
2476 int nrate; 2476 int nrate;
2477 short *rates; 2477 short *rates;
2478 Status status = RRSetConfigFailed; 2478 Status status = RRSetConfigFailed;
2479 int rot = -1; 2479 int rot = -1;
2480 int query = False; 2480 int query = False;
2481 int action_requested = False; 2481 int action_requested = False;
2482 Rotation current_rotation; 2482 Rotation current_rotation;
2483 XEvent event; 2483 XEvent event;
2484 XRRScreenChangeNotifyEvent *sce;  2484 XRRScreenChangeNotifyEvent *sce;
2485 char *display_name = NULL; 2485 char *display_name = NULL;
2486 int i; 2486 int i;
2487 SizeID current_size; 2487 SizeID current_size;
2488 short current_rate; 2488 short current_rate;
2489 double rate = -1; 2489 double rate = -1;
2490 int size = -1; 2490 int size = -1;
2491 int dirind = 0; 2491 int dirind = 0;
2492 Bool setit = False; 2492 Bool setit = False;
2493 Bool version = False; 2493 Bool version = False;
2494 int event_base, error_base; 2494 int event_base, error_base;
2495 int reflection = 0; 2495 int reflection = 0;
2496 int width = 0, height = 0; 2496 int width = 0, height = 0;
2497 Bool have_pixel_size = False; 2497 Bool have_pixel_size = False;
2498 int ret = 0; 2498 int ret = 0;
2499 output_t *config_output = NULL; 2499 output_t *config_output = NULL;
2500 Bool setit_1_2 = False; 2500 Bool setit_1_2 = False;
2501 Bool query_1_2 = False; 2501 Bool query_1_2 = False;
2502 Bool modeit = False; 2502 Bool modeit = False;
2503 Bool propit = False; 2503 Bool propit = False;
2504 Bool query_1 = False; 2504 Bool query_1 = False;
2505 Bool list_providers = False; 2505 Bool list_providers = False;
2506 Bool provsetoutsource = False; 2506 Bool provsetoutsource = False;
2507 Bool provsetoffsink = False; 2507 Bool provsetoffsink = False;
2508 int major, minor; 2508 int major, minor;
2509 Bool current = False; 2509 Bool current = False;
2510 2510
2511 program_name = argv[0]; 2511 program_name = argv[0];
2512 for (i = 1; i < argc; i++) { 2512 for (i = 1; i < argc; i++) {
2513 if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) { 2513 if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
2514 if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]); 2514 if (++i >= argc) argerr ("%s requires an argument\n", argv[i-1]);
2515 display_name = argv[i]; 2515 display_name = argv[i];
2516 continue; 2516 continue;
2517 } 2517 }
2518 if (!strcmp("-help", argv[i]) || !strcmp("--help", argv[i])) { 2518 if (!strcmp("-help", argv[i]) || !strcmp("--help", argv[i])) {
2519 usage(); 2519 usage();
2520 exit(0); 2520 exit(0);
2521 } 2521 }
2522 if (!strcmp ("--verbose", argv[i])) { 2522 if (!strcmp ("--verbose", argv[i])) {
2523 verbose = True; 2523 verbose = True;
2524 continue; 2524 continue;
2525 } 2525 }
2526 if (!strcmp ("--dryrun", argv[i])) { 2526 if (!strcmp ("--dryrun", argv[i])) {