2 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * Except as contained in this notice, the name of Conectiva Linux shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from
27 * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
32 * Most of the code here is based on the xvidtune code.
36 #include <X11/Xaw/Command.h>
37 #include <X11/Xaw/Form.h>
38 #include <X11/Xaw/Label.h>
39 #include <X11/Xaw/MenuButton.h>
40 #include <X11/Xaw/Repeater.h>
41 #include <X11/Shell.h>
42 #include <X11/Xaw/AsciiText.h>
43 #include <X11/Xaw/Dialog.h>
44 #include <X11/Xaw/SimpleMenP.h>
45 #include <X11/Xaw/SmeBSB.h>
46 #include <X11/Xaw/Toggle.h>
47 #include "xf86config.h"
49 #define V_FLAG_MASK 0x1FF
50 #define V_PHSYNC 0x001
51 #define V_NHSYNC 0x002
52 #define V_PVSYNC 0x004
53 #define V_NVSYNC 0x008
54 #define V_INTERLACE 0x010
55 #define V_DBLSCAN 0x020
57 #define V_PCSYNC 0x080
58 #define V_NCSYNC 0x100
90 XF86VidModeModeInfo info
;
91 } xf86cfgVesaModeInfo
;
96 static Bool
GetModeLine(Bool
);
97 static void StartAdjustMonitorCallback(Widget
, XtPointer
, XtPointer
);
98 static void AdjustMonitorCallback(Widget
, XtPointer
, XtPointer
);
99 static void EndAdjustMonitorCallback(Widget
, XtPointer
, XtPointer
);
100 static void SetLabel(int, int);
101 static void UpdateSyncRates(Bool
);
102 static int VidmodeError(Display
*, XErrorEvent
*);
103 static void CleanUp(Display
*);
104 static void ApplyCallback(Widget
, XtPointer
, XtPointer
);
105 static void AutoCallback(Widget
, XtPointer
, XtPointer
);
106 static void RestoreCallback(Widget
, XtPointer
, XtPointer
);
107 static void SelectCallback(Widget
, XtPointer
, XtPointer
);
108 static void SelectMonitorCallback(Widget
, XtPointer
, XtPointer
);
109 static void SwitchCallback(Widget
, XtPointer
, XtPointer
);
110 static void SetLabels(void);
111 static void UpdateCallback(Widget
, XtPointer
, XtPointer
);
112 static void ChangeScreenCallback(Widget
, XtPointer
, XtPointer
);
113 static void SetLabelAndModeline(void);
114 static void AddVesaModeCallback(Widget
, XtPointer
, XtPointer
);
115 static void GetModes(void);
116 static void AddModeCallback(Widget
, XtPointer
, XtPointer
);
117 static void TestCallback(Widget
, XtPointer
, XtPointer
);
118 static void TestTimeout(XtPointer
, XtIntervalId
*);
119 static void StopTestCallback(Widget
, XtPointer
, XtPointer
);
120 static int ForceAddMode(void);
121 static int AddMode(void);
127 static Widget apply
, automatic
, restore
, mode
, menu
, screenb
, screenp
;
128 static Bool autoflag
;
129 static xf86cfgVidmode
*vidtune
;
130 static XF86VidModeModeLine modeline
, orig_modeline
;
131 static int dot_clock
, hsync_rate
, vsync_rate
, hitError
;
133 static int (*XtErrorFunc
)(Display
*, XErrorEvent
*);
134 static Widget values
[VSYNC
+ 1], repeater
, monitor
,
135 monitorb
, add
, text
, vesap
, forceshell
, testshell
, addshell
;
136 static int MajorVersion
, MinorVersion
, EventBase
, ErrorBase
;
137 static XtIntervalId timeout
;
139 /* The information bellow is extracted from
140 * xc/programs/Xserver/hw/xfree86/etc/vesamodes
141 * If that file is changed, please update the table bellow also. Or even
142 * better, write a script to generate the table.
144 static xf86cfgVesaModeInfo vesamodes
[] = {
146 "640x350 @ 85Hz (VESA) hsync: 37.9kHz",
148 31500, 640, 672, 736, 832, 0, 350, 382, 385, 445,
153 "640x400 @ 85Hz (VESA) hsync: 37.9kHz",
155 31500, 640, 672, 736, 832, 0, 400, 401, 404, 445,
160 "720x400 @ 85Hz (VESA) hsync: 37.9kHz",
162 35500, 720, 756, 828, 936, 0, 400, 401, 404, 446,
167 "640x480 @ 60Hz (Industry standard) hsync: 31.5kHz",
169 25200, 640, 656, 752, 800, 0, 480, 490, 492, 525,
174 "640x480 @ 72Hz (VESA) hsync: 37.9kHz",
176 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520,
181 "640x480 @ 75Hz (VESA) hsync: 37.5kHz",
183 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500,
188 "640x480 @ 85Hz (VESA) hsync: 43.3kHz",
190 36000, 640, 696, 752, 832, 0, 480, 481, 484, 509,
195 "800x600 @ 56Hz (VESA) hsync: 35.2kHz",
197 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625,
202 "800x600 @ 60Hz (VESA) hsync: 37.9kHz",
204 400000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
209 "800x600 @ 72Hz (VESA) hsync: 48.1kHz",
211 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666,
216 "800x600 @ 75Hz (VESA) hsync: 46.9kHz",
218 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625,
223 "800x600 @ 85Hz (VESA) hsync: 53.7kHz",
225 563000, 800, 832, 896, 1048, 0, 600, 601, 604, 631,
230 "1024x768i @ 43Hz (industry standard) hsync: 35.5kHz",
232 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817,
233 V_PHSYNC
| V_PVSYNC
| V_INTERLACE
237 "1024x768 @ 60Hz (VESA) hsync: 48.4kHz",
239 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806,
244 "1024x768 @ 70Hz (VESA) hsync: 56.5kHz",
246 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806,
251 "1024x768 @ 75Hz (VESA) hsync: 60.0kHz",
253 78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800,
258 "1024x768 @ 85Hz (VESA) hsync: 68.7kHz",
260 94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808,
265 "1152x864 @ 75Hz (VESA) hsync: 67.5kHz",
267 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900,
272 "1280x960 @ 60Hz (VESA) hsync: 60.0kHz",
274 108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000,
279 "1280x960 @ 85Hz (VESA) hsync: 85.9kHz",
281 148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011,
286 "1280x1024 @ 60Hz (VESA) hsync: 64.0kHz",
288 108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066,
293 "1280x1024 @ 75Hz (VESA) hsync: 80.0kHz",
295 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066,
300 "1280x1024 @ 85Hz (VESA) hsync: 91.1kHz",
302 157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072,
307 "1600x1200 @ 60Hz (VESA) hsync: 75.0kHz",
309 162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
314 "1600x1200 @ 65Hz (VESA) hsync: 81.3kHz",
316 175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
321 "1600x1200 @ 70Hz (VESA) hsync: 87.5kHz",
323 189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
328 "1600x1200 @ 75Hz (VESA) hsync: 93.8kHz",
330 202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
335 "1600x1200 @ 85Hz (VESA) hsync: 106.3kHz",
337 229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
342 "1792x1344 @ 60Hz (VESA) hsync: 83.6kHz",
344 204800, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394,
349 "1792x1344 @ 75Hz (VESA) hsync: 106.3kHz",
351 261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417,
356 "1856x1392 @ 60Hz (VESA) hsync: 86.3kHz",
358 218300, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439,
363 "1856x1392 @ 75Hz (VESA) hsync: 112.5kHz",
365 288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500,
370 "1920x1440 @ 60Hz (VESA) hsync: 90.0kHz",
372 234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500,
377 "1920x1440 @ 75Hz (VESA) hsync: 112.5kHz",
379 297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500,
389 VideoModeInitialize(void)
392 char dispstr
[128], *ptr
, *tmp
;
394 static char *names
[] = {
408 static char *vnames
[] = {
425 if (!XF86VidModeQueryVersion(XtDisplay(toplevel
),
426 &MajorVersion
, &MinorVersion
)) {
427 fprintf(stderr
, "Unable to query video extension version\n");
430 else if (!XF86VidModeQueryExtension(XtDisplay(toplevel
),
431 &EventBase
, &ErrorBase
)) {
432 fprintf(stderr
, "Unable to query video extension information\n");
435 else if (MajorVersion
< MINMAJOR
||
436 (MajorVersion
== MINMAJOR
&& MinorVersion
< MINMINOR
)) {
438 "Xserver is running an old XFree86-VidModeExtension version"
439 " (%d.%d)\n", MajorVersion
, MinorVersion
);
440 fprintf(stderr
, "Minimum required version is %d.%d\n",
445 InitializeVidmodes();
447 vtune
= XtCreateWidget("vidtune", formWidgetClass
,
450 (void) XtVaCreateManagedWidget("vesaB", menuButtonWidgetClass
, vtune
,
451 XtNmenuName
, "vesaP", NULL
);
452 vesap
= XtCreatePopupShell("vesaP", simpleMenuWidgetClass
, vtune
, NULL
, 0);
453 for (i
= 0; i
< sizeof(vesamodes
) / sizeof(vesamodes
[0]); i
++) {
454 rep
= XtCreateManagedWidget(vesamodes
[i
].ident
, smeBSBObjectClass
,
456 XtAddCallback(rep
, XtNcallback
, AddVesaModeCallback
,
457 (XtPointer
)&vesamodes
[i
]);
460 rep
= XtCreateManagedWidget("prev", commandWidgetClass
, vtune
, NULL
, 0);
461 XtAddCallback(rep
, XtNcallback
, SwitchCallback
, (XtPointer
)-1);
462 mode
= XtCreateManagedWidget("mode", menuButtonWidgetClass
, vtune
, NULL
, 0);
463 rep
= XtCreateManagedWidget("next", commandWidgetClass
, vtune
, NULL
, 0);
464 XtAddCallback(rep
, XtNcallback
, SwitchCallback
, (XtPointer
)1);
466 screenp
= XtCreatePopupShell("screenP", simpleMenuWidgetClass
, vtune
,
469 XmuSnprintf(dispstr
, sizeof(dispstr
), "%s",
470 DisplayString(XtDisplay(toplevel
)));
471 ptr
= strrchr(dispstr
, '.');
472 tmp
= strrchr(dispstr
, ':');
473 if (tmp
!= NULL
&& ptr
!= NULL
&& ptr
> tmp
)
476 for (i
= 0; i
< ScreenCount(XtDisplay(toplevel
)); i
++) {
479 XmuSnprintf(name
, sizeof(name
), "%s.%d", dispstr
, i
);
480 rep
= XtCreateManagedWidget(name
, smeBSBObjectClass
, screenp
,
482 XtAddCallback(rep
, XtNcallback
, ChangeScreenCallback
,
485 screenb
= XtVaCreateManagedWidget("screenB", menuButtonWidgetClass
,
487 XtNmenuName
, "screenP",
492 XtRealizeWidget(screenp
);
494 rep
= XtCreateManagedWidget("up", repeaterWidgetClass
,
496 XtAddCallback(rep
, XtNstartCallback
, StartAdjustMonitorCallback
, NULL
);
497 XtAddCallback(rep
, XtNcallback
,
498 AdjustMonitorCallback
, (XtPointer
)UP
);
499 XtAddCallback(rep
, XtNstopCallback
, EndAdjustMonitorCallback
, NULL
);
500 rep
= XtCreateManagedWidget("left", repeaterWidgetClass
,
502 XtAddCallback(rep
, XtNstartCallback
, StartAdjustMonitorCallback
, NULL
);
503 XtAddCallback(rep
, XtNcallback
,
504 AdjustMonitorCallback
, (XtPointer
)LEFT
);
505 XtAddCallback(rep
, XtNstopCallback
, EndAdjustMonitorCallback
, NULL
);
506 XtCreateManagedWidget("monitor", simpleWidgetClass
, vtune
, NULL
, 0);
507 rep
= XtCreateManagedWidget("right", repeaterWidgetClass
,
509 XtAddCallback(rep
, XtNstartCallback
, StartAdjustMonitorCallback
, NULL
);
510 XtAddCallback(rep
, XtNcallback
,
511 AdjustMonitorCallback
, (XtPointer
)RIGHT
);
512 XtAddCallback(rep
, XtNstopCallback
, EndAdjustMonitorCallback
, NULL
);
513 rep
= XtCreateManagedWidget("down", repeaterWidgetClass
,
515 XtAddCallback(rep
, XtNstartCallback
, StartAdjustMonitorCallback
, NULL
);
516 XtAddCallback(rep
, XtNcallback
,
517 AdjustMonitorCallback
, (XtPointer
)DOWN
);
518 XtAddCallback(rep
, XtNstopCallback
, EndAdjustMonitorCallback
, NULL
);
519 rep
= XtCreateManagedWidget("wider", repeaterWidgetClass
,
521 XtAddCallback(rep
, XtNstartCallback
, StartAdjustMonitorCallback
, NULL
);
522 XtAddCallback(rep
, XtNcallback
,
523 AdjustMonitorCallback
, (XtPointer
)WIDER
);
524 XtAddCallback(rep
, XtNstopCallback
, EndAdjustMonitorCallback
, NULL
);
525 rep
= XtCreateManagedWidget("narrower", repeaterWidgetClass
,
527 XtAddCallback(rep
, XtNstartCallback
, StartAdjustMonitorCallback
, NULL
);
528 XtAddCallback(rep
, XtNcallback
,
529 AdjustMonitorCallback
, (XtPointer
)NARROWER
);
530 XtAddCallback(rep
, XtNstopCallback
, EndAdjustMonitorCallback
, NULL
);
531 rep
= XtCreateManagedWidget("shorter", repeaterWidgetClass
,
533 XtAddCallback(rep
, XtNstartCallback
, StartAdjustMonitorCallback
, NULL
);
534 XtAddCallback(rep
, XtNcallback
,
535 AdjustMonitorCallback
, (XtPointer
)SHORTER
);
536 XtAddCallback(rep
, XtNstopCallback
, EndAdjustMonitorCallback
, NULL
);
537 rep
= XtCreateManagedWidget("taller", repeaterWidgetClass
,
539 XtAddCallback(rep
, XtNstartCallback
, StartAdjustMonitorCallback
, NULL
);
540 XtAddCallback(rep
, XtNcallback
,
541 AdjustMonitorCallback
, (XtPointer
)TALLER
);
542 XtAddCallback(rep
, XtNstopCallback
, EndAdjustMonitorCallback
, NULL
);
544 automatic
= XtCreateManagedWidget("auto", toggleWidgetClass
, vtune
, NULL
, 0);
545 XtAddCallback(automatic
, XtNcallback
, AutoCallback
, NULL
);
546 apply
= XtCreateManagedWidget("apply", commandWidgetClass
, vtune
, NULL
, 0);
547 XtAddCallback(apply
, XtNcallback
, ApplyCallback
, NULL
);
548 restore
= XtCreateManagedWidget("restore", commandWidgetClass
, vtune
, NULL
, 0);
549 XtAddCallback(restore
, XtNcallback
, RestoreCallback
, NULL
);
550 rep
= XtCreateManagedWidget("update", commandWidgetClass
, vtune
, NULL
, 0);
551 XtAddCallback(rep
, XtNcallback
, UpdateCallback
, NULL
);
552 rep
= XtCreateManagedWidget("test", commandWidgetClass
, vtune
, NULL
, 0);
553 XtAddCallback(rep
, XtNcallback
, TestCallback
, NULL
);
555 form
= XtCreateManagedWidget("form", formWidgetClass
, vtune
, NULL
, 0);
556 for (i
= 2; i
< VSYNC
+ 1; i
++) {
557 (void) XtCreateManagedWidget(names
[i
], labelWidgetClass
,
559 values
[i
] = XtCreateManagedWidget(vnames
[i
], labelWidgetClass
,
563 add
= XtCreateManagedWidget("add", commandWidgetClass
, vtune
, NULL
, 0);
564 XtAddCallback(add
, XtNcallback
, AddModeCallback
, NULL
);
565 XtCreateManagedWidget("addto", labelWidgetClass
, vtune
, NULL
, 0);
566 monitorb
= XtCreateManagedWidget("ident", menuButtonWidgetClass
, vtune
,
568 XtCreateManagedWidget("as", labelWidgetClass
, vtune
, NULL
, 0);
569 text
= XtVaCreateManagedWidget("text", asciiTextWidgetClass
, vtune
,
570 XtNeditType
, XawtextEdit
, NULL
);
572 XtRealizeWidget(vtune
);
578 InitializeVidmodes(void)
581 Display
*display
= XtDisplay(toplevel
);
583 computer
.num_vidmodes
= ScreenCount(display
);
584 computer
.vidmodes
= (xf86cfgVidmode
**)
585 XtMalloc(sizeof(xf86cfgVidmode
*) * computer
.num_vidmodes
);
586 for (i
= 0; i
< computer
.num_vidmodes
; i
++) {
588 computer
.vidmodes
[i
] = (xf86cfgVidmode
*)
589 XtCalloc(1, sizeof(xf86cfgVidmode
));
590 computer
.vidmodes
[i
]->screen
= i
;
595 VideoModeConfigureStart(void)
597 vidtune
= computer
.vidmodes
[screenno
];
599 XtSetSensitive(vtune
, vidtune
!= NULL
);
600 if (!XtIsManaged(vtune
))
601 XtManageChild(vtune
);
604 if (vidtune
!= NULL
) {
607 XF86ConfMonitorPtr mon
;
608 static char menuName
[16];
611 XtErrorFunc
= XSetErrorHandler(VidmodeError
);
612 XF86VidModeLockModeSwitch(XtDisplay(toplevel
), vidtune
->screen
, True
);
617 XtSetArg(args
[0], XtNstate
, &state
);
618 XtGetValues(automatic
, args
, 1);
619 XtSetSensitive(apply
, !state
);
623 XtDestroyWidget(monitor
);
624 XmuSnprintf(menuName
, sizeof(menuName
), "menuP%d", menuN
);
626 monitor
= XtCreatePopupShell(menuName
, simpleMenuWidgetClass
,
628 XtVaSetValues(monitorb
, XtNmenuName
, menuName
, NULL
);
630 mon
= XF86Config
->conf_monitor_lst
;
631 while (mon
!= NULL
) {
632 Widget sme
= XtCreateManagedWidget(mon
->mon_identifier
,
635 XtAddCallback(sme
, XtNcallback
,
636 SelectMonitorCallback
, (XtPointer
)mon
);
638 /* guess the monitor at a given screen and/or
639 * updates configuration if a monitor was removed from the
642 if (XF86Config
->conf_layout_lst
) {
643 XF86ConfAdjacencyPtr adj
= XF86Config
->conf_layout_lst
->
646 while (adj
!= NULL
) {
647 if (adj
->adj_screen
!= NULL
) {
648 if (adj
->adj_screen
->scrn_monitor
== mon
&&
649 adj
->adj_scrnum
>= 0 &&
650 adj
->adj_scrnum
< ScreenCount(XtDisplay(toplevel
))) {
651 if (computer
.vidmodes
[adj
->adj_scrnum
]->monitor
==
652 NULL
|| computer
.vidmodes
[adj
->adj_scrnum
]->
653 monitor
== adj
->adj_screen
->scrn_monitor
) {
654 computer
.vidmodes
[adj
->adj_scrnum
]->monitor
=
655 adj
->adj_screen
->scrn_monitor
;
659 computer
.vidmodes
[adj
->adj_scrnum
]->monitor
=
663 adj
= (XF86ConfAdjacencyPtr
)(adj
->list
.next
);
666 mon
= (XF86ConfMonitorPtr
)(mon
->list
.next
);
668 SetLabelAndModeline();
673 VideoModeConfigureEnd(void)
675 XtUnmapWidget(vtune
);
676 if (vidtune
!= NULL
) {
677 XF86VidModeLockModeSwitch(XtDisplay(toplevel
), vidtune
->screen
, False
);
678 XSetErrorHandler(XtErrorFunc
);
684 SetLabelAndModeline(void)
686 if (vidtune
->monitor
!= NULL
) {
689 XtVaSetValues(monitorb
, XtNlabel
,
690 vidtune
->monitor
->mon_identifier
, NULL
);
691 XtSetSensitive(add
, True
);
693 if (modeline
.htotal
&& modeline
.vtotal
)
694 XmuSnprintf(string
, sizeof(string
), "%dx%d@%d",
695 modeline
.hdisplay
, modeline
.vdisplay
,
696 (int)((double)dot_clock
/ (double)modeline
.htotal
* 1000.0 /
697 (double)modeline
.vtotal
));
699 XmuSnprintf(string
, sizeof(string
), "%dx%d",
700 modeline
.hdisplay
, modeline
.vdisplay
);
701 XtVaSetValues(text
, XtNstring
, string
, NULL
);
704 XtVaSetValues(monitorb
, XtNlabel
, "", NULL
);
705 XtSetSensitive(add
, False
);
706 XtVaSetValues(text
, XtNstring
, "", NULL
);
712 VidmodeRestoreAction(Widget w
, XEvent
*event
,
713 String
*params
, Cardinal
*num_params
)
715 if (vidtune
!= NULL
) {
717 StopTestCallback(w
, NULL
, NULL
);
719 RestoreCallback(w
, NULL
, NULL
);
724 UpdateSyncRates(Bool update
)
726 if (modeline
.htotal
&& modeline
.vtotal
) {
727 hsync_rate
= (dot_clock
* 1000) / modeline
.htotal
;
728 vsync_rate
= (hsync_rate
* 1000) / modeline
.vtotal
;
729 if (modeline
.flags
& V_INTERLACE
)
731 else if (modeline
.flags
& V_DBLSCAN
)
734 SetLabel(HSYNC
, hsync_rate
);
735 SetLabel(VSYNC
, vsync_rate
);
741 SetLabel(int ident
, int value
)
746 if (ident
== FLAGS
) {
750 if (value
& V_PHSYNC
)
751 len
+= XmuSnprintf(label
, sizeof(label
), "%s", "+hsync");
752 if (modeline
.flags
& V_NHSYNC
)
753 len
+= XmuSnprintf(label
+ len
, sizeof(label
), "%s%s",
754 len
? " " : "", "-hsync");
755 if (value
& V_PVSYNC
)
756 len
+= XmuSnprintf(label
+ len
, sizeof(label
), "%s%s",
757 len
? " " : "", "+vsync");
758 if (value
& V_NVSYNC
)
759 len
+= XmuSnprintf(label
+ len
, sizeof(label
), "%s%s",
760 len
? " " : "", "-vsync");
761 if (value
& V_INTERLACE
)
762 len
+= XmuSnprintf(label
+ len
, sizeof(label
), "%s%s",
763 len
? " " : "", "interlace");
765 len
+= XmuSnprintf(label
+ len
, sizeof(label
), "%s%s",
766 len
? " " : "", "composite");
767 if (value
& V_PCSYNC
)
768 len
+= XmuSnprintf(label
+ len
, sizeof(label
), "%s%s",
769 len
? " " : "", "+csync");
770 if (value
& V_NCSYNC
)
771 len
+= XmuSnprintf(label
+ len
, sizeof(label
), "%s%s",
772 len
? " " : "", "-csync");
773 if (value
& V_DBLSCAN
)
774 len
+= XmuSnprintf(label
+ len
, sizeof(label
), "%s%s",
775 len
? " " : "", "doublescan");
778 else if (ident
== CLOCK
|| ident
== HSYNC
|| ident
== VSYNC
)
779 XmuSnprintf(label
, sizeof(label
), "%6.2f", (float)value
/ 1000.0);
781 XmuSnprintf(label
, sizeof(label
), "%d", value
);
783 XtSetArg(args
[0], XtNlabel
, label
);
784 XtSetValues(values
[ident
], args
, 1);
789 StartAdjustMonitorCallback(Widget w
, XtPointer client_data
, XtPointer call_data
)
795 AdjustMonitorCallback(Widget w
, XtPointer client_data
, XtPointer call_data
)
799 switch ((long)client_data
) {
801 if (modeline
.hsyncend
+ 4 < modeline
.htotal
) {
802 modeline
.hsyncstart
+= 4;
803 modeline
.hsyncend
+= 4;
804 SetLabel(HSYNCSTART
, modeline
.hsyncstart
);
805 SetLabel(HSYNCEND
, modeline
.hsyncend
);
808 XBell(XtDisplay(w
), 80);
811 if (modeline
.hsyncstart
- 4 > modeline
.hdisplay
) {
812 modeline
.hsyncstart
-= 4;
813 modeline
.hsyncend
-= 4;
814 SetLabel(HSYNCSTART
, modeline
.hsyncstart
);
815 SetLabel(HSYNCEND
, modeline
.hsyncend
);
818 XBell(XtDisplay(w
), 80);
821 modeline
.htotal
+= 4;
822 SetLabel(HTOTAL
, modeline
.htotal
);
823 UpdateSyncRates(True
);
826 if (modeline
.htotal
- 4 > modeline
.hsyncend
) {
827 modeline
.htotal
-= 4;
828 SetLabel(HTOTAL
, modeline
.htotal
);
829 UpdateSyncRates(True
);
832 XBell(XtDisplay(w
), 80);
835 if (modeline
.vsyncend
+ 4 < modeline
.vtotal
) {
836 modeline
.vsyncstart
+= 4;
837 modeline
.vsyncend
+= 4;
838 SetLabel(VSYNCSTART
, modeline
.vsyncstart
);
839 SetLabel(VSYNCEND
, modeline
.vsyncend
);
842 XBell(XtDisplay(w
), 80);
845 if (modeline
.vsyncstart
- 4 > modeline
.vdisplay
) {
846 modeline
.vsyncstart
-= 4;
847 modeline
.vsyncend
-= 4;
848 SetLabel(VSYNCSTART
, modeline
.vsyncstart
);
849 SetLabel(VSYNCEND
, modeline
.vsyncend
);
852 XBell(XtDisplay(w
), 80);
855 modeline
.vtotal
+= 4;
856 SetLabel(VTOTAL
, modeline
.vtotal
);
857 UpdateSyncRates(True
);
860 if (modeline
.vtotal
- 4 > modeline
.vsyncend
) {
861 modeline
.vtotal
-= 4;
862 SetLabel(VTOTAL
, modeline
.vtotal
);
863 UpdateSyncRates(True
);
866 XBell(XtDisplay(w
), 80);
871 ApplyCallback(w
, call_data
, client_data
);
876 EndAdjustMonitorCallback(Widget w
, XtPointer client_data
, XtPointer call_data
)
882 GetModeLine(Bool save
)
884 if (XF86VidModeGetModeLine(XtDisplay(toplevel
), vidtune
->screen
,
885 &dot_clock
, &modeline
)) {
887 memcpy(&orig_modeline
, &modeline
, sizeof(XF86VidModeModeLine
));
888 UpdateSyncRates(False
);
896 CleanUp(Display
*display
)
898 /* Make sure mode switching is not locked out at exit */
899 XF86VidModeLockModeSwitch(display
, vidtune
->screen
, False
);
904 VidmodeError(Display
*display
, XErrorEvent
*error
)
906 if ((error
->error_code
>= ErrorBase
&&
907 error
->error_code
< ErrorBase
+ XF86VidModeNumberErrors
) ||
908 error
->error_code
== BadValue
) {
914 (*XtErrorFunc
)(display
, error
);
921 ApplyCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
924 XF86VidModeModModeLine(XtDisplay(w
), vidtune
->screen
, &modeline
);
925 XSync(XtDisplay(w
), False
);
927 if (repeater
!= NULL
) {
928 XtCallActionProc(repeater
, "unset", NULL
, NULL
, 0);
929 XtCallActionProc(repeater
, "stop", NULL
, NULL
, 0);
932 XBell(XtDisplay(w
), 80);
934 StopTestCallback(w
, NULL
, NULL
);
942 AutoCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
944 autoflag
= (Bool
)(long)client_data
;
945 XtSetSensitive(apply
, !autoflag
);
949 RestoreCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
951 memcpy(&modeline
, &orig_modeline
, sizeof(XF86VidModeModeLine
));
953 ApplyCallback(w
, call_data
, client_data
);
958 SelectCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
960 XF86VidModeModeInfo
*info
= (XF86VidModeModeInfo
*)call_data
;
964 XF86VidModeLockModeSwitch(XtDisplay(toplevel
), vidtune
->screen
, False
);
965 result
= XF86VidModeSwitchToMode(XtDisplay(toplevel
), vidtune
->screen
, info
);
966 XF86VidModeLockModeSwitch(XtDisplay(toplevel
), vidtune
->screen
, True
);
970 XtSetArg(args
[0], XtNlabel
, XtName(w
));
971 XtSetValues(mode
, args
, 1);
972 UpdateCallback(w
, call_data
, client_data
);
976 SwitchCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
978 int direction
= (long)call_data
;
983 XF86VidModeLockModeSwitch(XtDisplay(toplevel
), vidtune
->screen
, False
);
984 result
= XF86VidModeSwitchMode(XtDisplay(toplevel
), vidtune
->screen
,
986 XF86VidModeLockModeSwitch(XtDisplay(toplevel
), vidtune
->screen
, True
);
990 UpdateCallback(w
, call_data
, client_data
);
992 if (modeline
.htotal
&& modeline
.vtotal
)
993 XmuSnprintf(label
, sizeof(label
), "%dx%d @ %d Hz",
994 modeline
.hdisplay
, modeline
.vdisplay
,
995 (int)((double)dot_clock
/ (double)modeline
.htotal
* 1000.0 /
996 (double)modeline
.vtotal
));
998 XmuSnprintf(label
, sizeof(label
), "%dx%d",
999 modeline
.hdisplay
, modeline
.vdisplay
);
1000 XtSetArg(args
[0], XtNlabel
, label
);
1001 XtSetValues(mode
, args
, 1);
1006 UpdateCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
1010 SetLabelAndModeline();
1016 SetLabel(HSYNCSTART
, modeline
.hsyncstart
);
1017 SetLabel(VSYNCSTART
, modeline
.vsyncstart
);
1018 SetLabel(HSYNCEND
, modeline
.hsyncend
);
1019 SetLabel(VSYNCEND
, modeline
.vsyncend
);
1020 SetLabel(HTOTAL
, modeline
.htotal
);
1021 SetLabel(VTOTAL
, modeline
.vtotal
);
1022 SetLabel(FLAGS
, modeline
.flags
);
1023 SetLabel(CLOCK
, dot_clock
);
1024 UpdateSyncRates(True
);
1029 ChangeScreenCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
1033 screenno
= (long)call_data
;
1034 if (screenno
> computer
.num_vidmodes
|| screenno
< 0 ||
1035 vidtune
== computer
.vidmodes
[screenno
])
1038 XF86VidModeLockModeSwitch(XtDisplay(toplevel
), vidtune
->screen
, False
);
1039 vidtune
= computer
.vidmodes
[screenno
];
1040 XF86VidModeLockModeSwitch(XtDisplay(toplevel
), vidtune
->screen
, True
);
1041 UpdateCallback(w
, call_data
, client_data
);
1044 XtSetArg(args
[0], XtNlabel
, XtName(w
));
1045 XtSetValues(screenb
, args
, 1);
1047 SetLabelAndModeline();
1052 SelectMonitorCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
1054 vidtune
->monitor
= (XF86ConfMonitorPtr
)(call_data
);
1055 SetLabelAndModeline();
1060 AddVesaModeCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
1062 xf86cfgVesaModeInfo
*vesa
= (xf86cfgVesaModeInfo
*)call_data
;
1063 XF86VidModeModeInfo mode
;
1064 int num_infos
= vidtune
->num_infos
;
1066 memcpy(&mode
, &vesa
->info
, sizeof(XF86VidModeModeInfo
));
1067 if (XF86VidModeAddModeLine(XtDisplay(toplevel
), vidtune
->screen
,
1068 &vesa
->info
, &mode
)) {
1069 XSync(XtDisplay(toplevel
), False
);
1073 XBell(XtDisplayOfObject(w
), 80);
1077 if (vidtune
&& num_infos
== vidtune
->num_infos
) {
1078 /* XF86VidModeAddModeLine returned True, but no modeline was added */
1079 XBell(XtDisplayOfObject(w
), 80);
1080 if (vidtune
->monitor
&& AddMode()) {
1081 XF86ConfModeLinePtr mode
;
1082 char label
[256], *ptr
, *str
;
1084 XmuSnprintf(label
, sizeof(label
), "%s", vesa
->ident
);
1086 /* format mode name to not have spaces */
1087 ptr
= strchr(label
, ')');
1098 if (xf86findModeLine(label
, vidtune
->monitor
->mon_modeline_lst
)
1099 != NULL
&& !ForceAddMode())
1102 mode
= (XF86ConfModeLinePtr
)XtCalloc(1, sizeof(XF86ConfModeLineRec
));
1103 mode
->ml_identifier
= XtNewString(label
);
1104 mode
->ml_clock
= vesa
->info
.dotclock
;
1105 mode
->ml_hdisplay
= vesa
->info
.hdisplay
;
1106 mode
->ml_hsyncstart
= vesa
->info
.hsyncstart
;
1107 mode
->ml_hsyncend
= vesa
->info
.hsyncend
;
1108 mode
->ml_htotal
= vesa
->info
.htotal
;
1109 mode
->ml_vdisplay
= vesa
->info
.vdisplay
;
1110 mode
->ml_vsyncstart
= vesa
->info
.vsyncstart
;
1111 mode
->ml_vsyncend
= vesa
->info
.vsyncend
;
1112 mode
->ml_vtotal
= vesa
->info
.vtotal
;
1113 /* mode->ml_vscan = ???;*/
1114 mode
->ml_flags
= vesa
->info
.flags
;
1115 mode
->ml_hskew
= vesa
->info
.hskew
;
1116 vidtune
->monitor
->mon_modeline_lst
=
1117 xf86addModeLine(vidtune
->monitor
->mon_modeline_lst
, mode
);
1128 static char menuName
[16];
1131 XFree(vidtune
->infos
);
1132 XF86VidModeGetAllModeLines(XtDisplay(toplevel
), vidtune
->screen
,
1133 &vidtune
->num_infos
, &vidtune
->infos
);
1135 XmuSnprintf(menuName
, sizeof(menuName
), "menu%d", menuN
);
1138 XtDestroyWidget(menu
);
1139 menu
= XtCreatePopupShell(menuName
, simpleMenuWidgetClass
, vtune
, NULL
, 0);
1140 XtVaSetValues(mode
, XtNmenuName
, menuName
, NULL
);
1141 for (i
= 0; i
< vidtune
->num_infos
; i
++) {
1144 if ((double)vidtune
->infos
[i
]->htotal
&&
1145 (double)vidtune
->infos
[i
]->vtotal
)
1146 XmuSnprintf(label
, sizeof(label
), "%dx%d @ %d Hz",
1147 vidtune
->infos
[i
]->hdisplay
,
1148 vidtune
->infos
[i
]->vdisplay
,
1149 (int)((double)vidtune
->infos
[i
]->dotclock
/
1150 (double)vidtune
->infos
[i
]->htotal
* 1000.0 /
1151 (double)vidtune
->infos
[i
]->vtotal
));
1153 XmuSnprintf(label
, sizeof(label
), "%dx%d",
1154 vidtune
->infos
[i
]->hdisplay
,
1155 vidtune
->infos
[i
]->vdisplay
);
1156 sme
= XtCreateManagedWidget(label
, smeBSBObjectClass
, menu
, NULL
, 0);
1157 XtAddCallback(sme
, XtNcallback
, SelectCallback
,
1158 (XtPointer
)vidtune
->infos
[i
]);
1161 if (modeline
.htotal
&& modeline
.vtotal
)
1162 XmuSnprintf(label
, sizeof(label
), "%dx%d @ %d Hz",
1163 modeline
.hdisplay
, modeline
.vdisplay
,
1164 (int)((double)dot_clock
/ (double)modeline
.htotal
* 1000.0 /
1165 (double)modeline
.vtotal
));
1167 XmuSnprintf(label
, sizeof(label
), "%dx%d",
1168 modeline
.hdisplay
, modeline
.vdisplay
);
1169 XtSetArg(args
[0], XtNlabel
, label
);
1170 XtSetValues(mode
, args
, 1);
1173 static int do_force
, asking_force
;
1176 PopdownForce(Widget w
, XtPointer user_data
, XtPointer call_data
)
1179 XtPopdown(forceshell
);
1180 do_force
= (long)user_data
;
1186 if (forceshell
== NULL
) {
1189 forceshell
= XtCreatePopupShell("force", transientShellWidgetClass
,
1191 dialog
= XtVaCreateManagedWidget("dialog", dialogWidgetClass
,
1192 forceshell
, XtNvalue
, NULL
, NULL
);
1193 XawDialogAddButton(dialog
, "yes", PopdownForce
, (XtPointer
)True
);
1194 XawDialogAddButton(dialog
, "no", PopdownForce
, (XtPointer
)False
);
1195 XtRealizeWidget(forceshell
);
1196 XSetWMProtocols(DPY
, XtWindow(forceshell
), &wm_delete_window
, 1);
1201 XtPopup(forceshell
, XtGrabExclusive
);
1202 while (asking_force
)
1203 XtAppProcessEvent(XtWidgetToApplicationContext(forceshell
), XtIMAll
);
1208 static int do_add
, asking_add
;
1211 PopdownAdd(Widget w
, XtPointer user_data
, XtPointer call_data
)
1214 XtPopdown(addshell
);
1215 do_add
= (long)user_data
;
1219 CancelAddModeAction(Widget w
, XEvent
*event
,
1220 String
*params
, Cardinal
*num_params
)
1223 PopdownForce(w
, (XtPointer
)False
, NULL
);
1224 else if (asking_add
)
1225 PopdownAdd(w
, (XtPointer
)False
, NULL
);
1231 if (addshell
== NULL
) {
1234 addshell
= XtCreatePopupShell("addMode", transientShellWidgetClass
,
1236 dialog
= XtVaCreateManagedWidget("dialog", dialogWidgetClass
,
1237 addshell
, XtNvalue
, NULL
, NULL
);
1238 XawDialogAddButton(dialog
, "yes", PopdownAdd
, (XtPointer
)True
);
1239 XawDialogAddButton(dialog
, "no", PopdownAdd
, (XtPointer
)False
);
1240 XtRealizeWidget(addshell
);
1241 XSetWMProtocols(DPY
, XtWindow(addshell
), &wm_delete_window
, 1);
1246 XtPopup(addshell
, XtGrabExclusive
);
1248 XtAppProcessEvent(XtWidgetToApplicationContext(addshell
), XtIMAll
);
1255 AddModeCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
1257 if (vidtune
&& vidtune
->monitor
) {
1260 XF86ConfModeLinePtr mode
;
1262 XtSetArg(args
[0], XtNstring
, &label
);
1263 XtGetValues(text
, args
, 1);
1264 if (*label
== '\0') {
1265 XBell(XtDisplay(w
), 80);
1268 if (xf86findModeLine(label
, vidtune
->monitor
->mon_modeline_lst
)
1269 != NULL
&& !ForceAddMode())
1272 mode
= (XF86ConfModeLinePtr
)XtCalloc(1, sizeof(XF86ConfModeLineRec
));
1273 mode
->ml_identifier
= XtNewString(label
);
1274 mode
->ml_clock
= dot_clock
;
1275 mode
->ml_hdisplay
= modeline
.hdisplay
;
1276 mode
->ml_hsyncstart
= modeline
.hsyncstart
;
1277 mode
->ml_hsyncend
= modeline
.hsyncend
;
1278 mode
->ml_htotal
= modeline
.htotal
;
1279 mode
->ml_vdisplay
= modeline
.vdisplay
;
1280 mode
->ml_vsyncstart
= modeline
.vsyncstart
;
1281 mode
->ml_vsyncend
= modeline
.vsyncend
;
1282 mode
->ml_vtotal
= modeline
.vtotal
;
1283 /* mode->ml_vscan = ???;*/
1284 mode
->ml_flags
= modeline
.flags
;
1285 mode
->ml_hskew
= modeline
.hskew
;
1286 vidtune
->monitor
->mon_modeline_lst
=
1287 xf86addModeLine(vidtune
->monitor
->mon_modeline_lst
, mode
);
1290 XBell(XtDisplay(w
), 80);
1295 StopTestCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
1297 XtRemoveTimeOut(timeout
);
1298 TestTimeout((XtPointer
)w
, NULL
);
1303 CancelTestModeAction(Widget w
, XEvent
*event
,
1304 String
*params
, Cardinal
*num_params
)
1306 StopTestCallback(w
, NULL
, NULL
);
1310 TestTimeout(XtPointer client_data
, XtIntervalId
* id
)
1312 XF86VidModeModeLine mode
;
1314 XtPopdown(testshell
);
1316 memcpy(&mode
, &modeline
, sizeof(XF86VidModeModeLine
));
1317 memcpy(&modeline
, &orig_modeline
, sizeof(XF86VidModeModeLine
));
1318 ApplyCallback((Widget
)client_data
, NULL
, NULL
);
1319 /* if (hitError == 0)*/
1320 memcpy(&modeline
, &mode
, sizeof(XF86VidModeModeLine
));
1325 TestCallback(Widget w
, XtPointer call_data
, XtPointer client_data
)
1327 if (testshell
== NULL
) {
1330 testshell
= XtCreatePopupShell("test", transientShellWidgetClass
,
1332 dialog
= XtVaCreateManagedWidget("dialog", dialogWidgetClass
,
1333 testshell
, XtNvalue
, NULL
, NULL
);
1334 XawDialogAddButton(dialog
, "stop", StopTestCallback
, NULL
);
1335 XtRealizeWidget(testshell
);
1336 XSetWMProtocols(DPY
, XtWindow(testshell
), &wm_delete_window
, 1);
1339 XtPopup(testshell
, XtGrabExclusive
);
1341 XSync(XtDisplay(toplevel
), False
);
1342 timeout
= XtAppAddTimeOut(XtWidgetToApplicationContext(w
),
1343 /* the timeout probably shoud be converted to a resource */
1344 4000, TestTimeout
, (XtPointer
)w
);
1345 ApplyCallback(w
, call_data
, client_data
);