1347 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1347 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 | |
|  * 
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a
 | |
|  * copy of this software and associated documentation files (the "Software"),
 | |
|  * to deal in the Software without restriction, including without limitation
 | |
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | |
|  * and/or sell copies of the Software, and to permit persons to whom the
 | |
|  * Software is furnished to do so, subject to the following conditions:
 | |
|  * 
 | |
|  * The above copyright notice and this permission notice shall be included in
 | |
|  * all copies or substantial portions of the Software.
 | |
|  *  
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | |
|  * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | |
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 | |
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | |
|  * SOFTWARE.
 | |
|  * 
 | |
|  * Except as contained in this notice, the name of Conectiva Linux shall
 | |
|  * not be used in advertising or otherwise to promote the sale, use or other
 | |
|  * dealings in this Software without prior written authorization from
 | |
|  * Conectiva Linux.
 | |
|  *
 | |
|  * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * Most of the code here is based on the xvidtune code.
 | |
|  */
 | |
| 
 | |
| #include "vidmode.h"
 | |
| #include <X11/Xaw/Command.h>
 | |
| #include <X11/Xaw/Form.h>
 | |
| #include <X11/Xaw/Label.h>
 | |
| #include <X11/Xaw/MenuButton.h>
 | |
| #include <X11/Xaw/Repeater.h>
 | |
| #include <X11/Shell.h>
 | |
| #include <X11/Xaw/AsciiText.h>
 | |
| #include <X11/Xaw/Dialog.h>
 | |
| #include <X11/Xaw/SimpleMenP.h>
 | |
| #include <X11/Xaw/SmeBSB.h>
 | |
| #include <X11/Xaw/Toggle.h>
 | |
| #include "xf86config.h"
 | |
| 
 | |
| #define V_FLAG_MASK	0x1FF
 | |
| #define V_PHSYNC	0x001 
 | |
| #define V_NHSYNC	0x002
 | |
| #define V_PVSYNC	0x004
 | |
| #define V_NVSYNC	0x008
 | |
| #define V_INTERLACE	0x010 
 | |
| #define V_DBLSCAN	0x020
 | |
| #define V_CSYNC		0x040
 | |
| #define V_PCSYNC	0x080
 | |
| #define V_NCSYNC	0x100
 | |
| 
 | |
| #define	LEFT		0
 | |
| #define	RIGHT		1
 | |
| #define	UP		2
 | |
| #define	DOWN		3
 | |
| #define	WIDER		4
 | |
| #define	TALLER		5
 | |
| #define	NARROWER	6
 | |
| #define	SHORTER		7
 | |
| 
 | |
| #define	HDISPLAY	0
 | |
| #define VDISPLAY	1
 | |
| #define HSYNCSTART	2
 | |
| #define HSYNCEND	3
 | |
| #define HTOTAL		4
 | |
| #define VSYNCSTART	5
 | |
| #define VSYNCEND	6
 | |
| #define VTOTAL		7
 | |
| #define FLAGS		8
 | |
| #define CLOCK		9
 | |
| #define HSYNC		10
 | |
| #define VSYNC		11
 | |
| 
 | |
| #define MINMAJOR	 2
 | |
| #define MINMINOR	 0
 | |
| 
 | |
| /*
 | |
|  * Types
 | |
|  */
 | |
| typedef struct {
 | |
|     char *ident;
 | |
|     XF86VidModeModeInfo info;
 | |
| } xf86cfgVesaModeInfo;
 | |
| 
 | |
| /*
 | |
|  * Prototypes
 | |
|  */
 | |
| static Bool GetModeLine(Bool);
 | |
| static void StartAdjustMonitorCallback(Widget, XtPointer, XtPointer);
 | |
| static void AdjustMonitorCallback(Widget, XtPointer, XtPointer);
 | |
| static void EndAdjustMonitorCallback(Widget, XtPointer, XtPointer);
 | |
| static void SetLabel(int, int);
 | |
| static void UpdateSyncRates(Bool);
 | |
| static int VidmodeError(Display*, XErrorEvent*);
 | |
| static void CleanUp(Display*);
 | |
| static void ApplyCallback(Widget, XtPointer, XtPointer);
 | |
| static void AutoCallback(Widget, XtPointer, XtPointer);
 | |
| static void RestoreCallback(Widget, XtPointer, XtPointer);
 | |
| static void SelectCallback(Widget, XtPointer, XtPointer);
 | |
| static void SelectMonitorCallback(Widget, XtPointer, XtPointer);
 | |
| static void SwitchCallback(Widget, XtPointer, XtPointer);
 | |
| static void SetLabels(void);
 | |
| static void UpdateCallback(Widget, XtPointer, XtPointer);
 | |
| static void ChangeScreenCallback(Widget, XtPointer, XtPointer);
 | |
| static void SetLabelAndModeline(void);
 | |
| static void AddVesaModeCallback(Widget, XtPointer, XtPointer);
 | |
| static void GetModes(void);
 | |
| static void AddModeCallback(Widget, XtPointer, XtPointer);
 | |
| static void TestCallback(Widget, XtPointer, XtPointer);
 | |
| static void TestTimeout(XtPointer, XtIntervalId*);
 | |
| static void StopTestCallback(Widget, XtPointer, XtPointer);
 | |
| static int ForceAddMode(void);
 | |
| static int AddMode(void);
 | |
| /*
 | |
|  * Initialization
 | |
|  */
 | |
| extern Widget work;
 | |
| Widget vtune;
 | |
| static Widget apply, automatic, restore, mode, menu, screenb, screenp;
 | |
| static Bool autoflag;
 | |
| static xf86cfgVidmode *vidtune;
 | |
| static XF86VidModeModeLine modeline, orig_modeline;
 | |
| static int dot_clock, hsync_rate, vsync_rate, hitError;
 | |
| static int screenno;
 | |
| static int (*XtErrorFunc)(Display*, XErrorEvent*);
 | |
| static Widget values[VSYNC + 1], repeater, monitor,
 | |
| 	      monitorb, add, text, vesap, forceshell, testshell, addshell;
 | |
| static int MajorVersion, MinorVersion, EventBase, ErrorBase;
 | |
| static XtIntervalId timeout;
 | |
| 
 | |
| /* The information bellow is extracted from
 | |
|  * xc/programs/Xserver/hw/xfree86/etc/vesamodes
 | |
|  * If that file is changed, please update the table bellow also. Or even
 | |
|  * better, write a script to generate the table.
 | |
|  */
 | |
| static xf86cfgVesaModeInfo vesamodes[] = {
 | |
|     {
 | |
| 	"640x350 @ 85Hz (VESA) hsync: 37.9kHz",
 | |
| 	{
 | |
| 	    31500, 640, 672, 736, 832, 0, 350, 382, 385, 445,
 | |
| 	    V_PHSYNC | V_NVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"640x400 @ 85Hz (VESA) hsync: 37.9kHz",
 | |
| 	{
 | |
| 	    31500, 640, 672, 736, 832, 0, 400, 401, 404, 445,
 | |
| 	    V_NHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"720x400 @ 85Hz (VESA) hsync: 37.9kHz",
 | |
| 	{
 | |
| 	    35500, 720, 756, 828, 936, 0, 400, 401, 404, 446,
 | |
| 	    V_NHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"640x480 @ 60Hz (Industry standard) hsync: 31.5kHz",
 | |
| 	{
 | |
| 	    25200, 640, 656, 752, 800, 0, 480, 490, 492, 525,
 | |
| 	    V_NHSYNC | V_NVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"640x480 @ 72Hz (VESA) hsync: 37.9kHz",
 | |
| 	{
 | |
| 	    31500, 640, 664, 704, 832, 0, 480, 489, 491, 520,
 | |
| 	    V_NHSYNC | V_NVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"640x480 @ 75Hz (VESA) hsync: 37.5kHz",
 | |
| 	{
 | |
| 	    31500, 640, 656, 720, 840, 0, 480, 481, 484, 500,
 | |
| 	    V_NHSYNC | V_NVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"640x480 @ 85Hz (VESA) hsync: 43.3kHz",
 | |
| 	{
 | |
| 	    36000, 640, 696, 752, 832, 0, 480, 481, 484, 509,
 | |
| 	    V_NHSYNC | V_NVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"800x600 @ 56Hz (VESA) hsync: 35.2kHz",
 | |
| 	{
 | |
| 	    36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"800x600 @ 60Hz (VESA) hsync: 37.9kHz",
 | |
| 	{
 | |
| 	    400000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"800x600 @ 72Hz (VESA) hsync: 48.1kHz",
 | |
| 	{
 | |
| 	    50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"800x600 @ 75Hz (VESA) hsync: 46.9kHz",
 | |
| 	{
 | |
| 	    49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"800x600 @ 85Hz (VESA) hsync: 53.7kHz",
 | |
| 	{
 | |
| 	    563000, 800, 832, 896, 1048, 0, 600, 601, 604, 631,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1024x768i @ 43Hz (industry standard) hsync: 35.5kHz",
 | |
| 	{
 | |
| 	    44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817,
 | |
| 	    V_PHSYNC | V_PVSYNC | V_INTERLACE
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1024x768 @ 60Hz (VESA) hsync: 48.4kHz",
 | |
| 	{
 | |
| 	    65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806,
 | |
| 	    V_NHSYNC | V_NVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1024x768 @ 70Hz (VESA) hsync: 56.5kHz",
 | |
| 	{
 | |
| 	    75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806,
 | |
| 	    V_NHSYNC | V_NVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1024x768 @ 75Hz (VESA) hsync: 60.0kHz",
 | |
| 	{
 | |
| 	    78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1024x768 @ 85Hz (VESA) hsync: 68.7kHz",
 | |
| 	{
 | |
| 	    94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1152x864 @ 75Hz (VESA) hsync: 67.5kHz",
 | |
| 	{
 | |
| 	    108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1280x960 @ 60Hz (VESA) hsync: 60.0kHz",
 | |
| 	{
 | |
| 	    108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1280x960 @ 85Hz (VESA) hsync: 85.9kHz",
 | |
| 	{
 | |
| 	    148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1280x1024 @ 60Hz (VESA) hsync: 64.0kHz",
 | |
| 	{
 | |
| 	    108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1280x1024 @ 75Hz (VESA) hsync: 80.0kHz",
 | |
| 	{
 | |
| 	    135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1280x1024 @ 85Hz (VESA) hsync: 91.1kHz",
 | |
| 	{
 | |
| 	    157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1600x1200 @ 60Hz (VESA) hsync: 75.0kHz",
 | |
| 	{
 | |
| 	    162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1600x1200 @ 65Hz (VESA) hsync: 81.3kHz",
 | |
| 	{
 | |
| 	    175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1600x1200 @ 70Hz (VESA) hsync: 87.5kHz",
 | |
| 	{
 | |
| 	    189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1600x1200 @ 75Hz (VESA) hsync: 93.8kHz",
 | |
| 	{
 | |
| 	    202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1600x1200 @ 85Hz (VESA) hsync: 106.3kHz",
 | |
| 	{
 | |
| 	    229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 | |
| 	    V_PHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1792x1344 @ 60Hz (VESA) hsync: 83.6kHz",
 | |
| 	{
 | |
| 	    204800, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394,
 | |
| 	    V_NHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1792x1344 @ 75Hz (VESA) hsync: 106.3kHz",
 | |
| 	{
 | |
| 	    261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417,
 | |
| 	    V_NHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1856x1392 @ 60Hz (VESA) hsync: 86.3kHz",
 | |
| 	{
 | |
| 	    218300, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439,
 | |
| 	    V_NHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1856x1392 @ 75Hz (VESA) hsync: 112.5kHz",
 | |
| 	{
 | |
| 	    288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500,
 | |
| 	    V_NHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1920x1440 @ 60Hz (VESA) hsync: 90.0kHz",
 | |
| 	{
 | |
| 	    234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500,
 | |
| 	    V_NHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
|     {
 | |
| 	"1920x1440 @ 75Hz (VESA) hsync: 112.5kHz",
 | |
| 	{
 | |
| 	    297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500,
 | |
| 	    V_NHSYNC | V_PVSYNC
 | |
| 	}
 | |
|     },
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * Implementation
 | |
|  */
 | |
| Bool
 | |
| VideoModeInitialize(void)
 | |
| {
 | |
|     Widget form;
 | |
|     char dispstr[128], *ptr, *tmp;
 | |
| 
 | |
|     static char *names[] = {
 | |
| 	NULL,
 | |
| 	NULL,
 | |
| 	"hsyncstart",
 | |
| 	"hsyncend",
 | |
| 	"htotal",
 | |
| 	"vsyncstart",
 | |
| 	"vsyncend",
 | |
| 	"vtotal",
 | |
| 	"flags",
 | |
| 	"clock",
 | |
| 	"hsync",
 | |
| 	"vsync",
 | |
|     };
 | |
|     static char *vnames[] = {
 | |
| 	NULL,
 | |
| 	NULL,
 | |
| 	"v-hsyncstart",
 | |
| 	"v-hsyncend",
 | |
| 	"v-htotal",
 | |
| 	"v-vsyncstart",
 | |
| 	"v-vsyncend",
 | |
| 	"v-vtotal",
 | |
| 	"v-flags",
 | |
| 	"v-clock",
 | |
| 	"v-hsync",
 | |
| 	"v-vsync",
 | |
|     };
 | |
|     Widget rep;
 | |
|     int i;
 | |
| 
 | |
|     if (!XF86VidModeQueryVersion(XtDisplay(toplevel),
 | |
| 				 &MajorVersion, &MinorVersion)) {
 | |
| 	fprintf(stderr, "Unable to query video extension version\n");
 | |
| 	return (False);
 | |
|     }
 | |
|     else if (!XF86VidModeQueryExtension(XtDisplay(toplevel),
 | |
| 					&EventBase, &ErrorBase)) {
 | |
| 	fprintf(stderr, "Unable to query video extension information\n");
 | |
| 	return (False);
 | |
|     }
 | |
|     else if (MajorVersion < MINMAJOR ||
 | |
| 	(MajorVersion == MINMAJOR && MinorVersion < MINMINOR)) {
 | |
| 	fprintf(stderr,
 | |
| 		"Xserver is running an old XFree86-VidModeExtension version"
 | |
| 		" (%d.%d)\n", MajorVersion, MinorVersion);
 | |
| 	fprintf(stderr, "Minimum required version is %d.%d\n",
 | |
| 		MINMAJOR, MINMINOR);
 | |
| 	return (False);
 | |
|     }
 | |
|     else
 | |
| 	InitializeVidmodes();
 | |
| 
 | |
|     vtune = XtCreateWidget("vidtune", formWidgetClass,
 | |
| 			   work, NULL, 0);
 | |
| 
 | |
|     (void) XtVaCreateManagedWidget("vesaB", menuButtonWidgetClass, vtune,
 | |
| 				    XtNmenuName, "vesaP", NULL);
 | |
|     vesap = XtCreatePopupShell("vesaP", simpleMenuWidgetClass, vtune, NULL, 0);
 | |
|     for (i = 0; i < sizeof(vesamodes) / sizeof(vesamodes[0]); i++) {
 | |
| 	rep = XtCreateManagedWidget(vesamodes[i].ident, smeBSBObjectClass,
 | |
| 				    vesap, NULL, 0);
 | |
| 	XtAddCallback(rep, XtNcallback, AddVesaModeCallback,
 | |
| 		      (XtPointer)&vesamodes[i]);
 | |
|     }
 | |
| 
 | |
|     rep = XtCreateManagedWidget("prev", commandWidgetClass, vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNcallback, SwitchCallback, (XtPointer)-1);
 | |
|     mode = XtCreateManagedWidget("mode", menuButtonWidgetClass, vtune, NULL, 0);
 | |
|     rep = XtCreateManagedWidget("next", commandWidgetClass, vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNcallback, SwitchCallback, (XtPointer)1);
 | |
| 
 | |
|     screenp = XtCreatePopupShell("screenP", simpleMenuWidgetClass, vtune,
 | |
| 				 NULL, 0);
 | |
| 
 | |
|     XmuSnprintf(dispstr, sizeof(dispstr), "%s",
 | |
| 		DisplayString(XtDisplay(toplevel)));
 | |
|     ptr = strrchr(dispstr, '.');
 | |
|     tmp = strrchr(dispstr, ':');
 | |
|     if (tmp != NULL && ptr != NULL && ptr > tmp)
 | |
| 	*ptr = '\0';
 | |
| 
 | |
|     for (i = 0; i < ScreenCount(XtDisplay(toplevel)); i++) {
 | |
| 	char name[128];
 | |
| 
 | |
| 	XmuSnprintf(name, sizeof(name), "%s.%d", dispstr, i);
 | |
| 	rep = XtCreateManagedWidget(name, smeBSBObjectClass, screenp,
 | |
| 				    NULL, 0);
 | |
| 	XtAddCallback(rep, XtNcallback, ChangeScreenCallback,
 | |
| 	    (XtPointer)(long)i);
 | |
| 	if (i == 0) {
 | |
| 	    screenb = XtVaCreateManagedWidget("screenB", menuButtonWidgetClass,
 | |
| 					      vtune,
 | |
| 					      XtNmenuName, "screenP",
 | |
| 					      XtNlabel, name,
 | |
| 					      NULL);
 | |
| 	}
 | |
|     }
 | |
|     XtRealizeWidget(screenp);
 | |
| 
 | |
|     rep = XtCreateManagedWidget("up", repeaterWidgetClass,
 | |
| 				vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 | |
|     XtAddCallback(rep, XtNcallback,
 | |
| 		  AdjustMonitorCallback, (XtPointer)UP);
 | |
|     XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 | |
|     rep = XtCreateManagedWidget("left", repeaterWidgetClass,
 | |
| 				vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 | |
|     XtAddCallback(rep, XtNcallback,
 | |
| 		  AdjustMonitorCallback, (XtPointer)LEFT);
 | |
|     XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 | |
|     XtCreateManagedWidget("monitor", simpleWidgetClass, vtune, NULL, 0);
 | |
|     rep = XtCreateManagedWidget("right", repeaterWidgetClass,
 | |
| 				vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 | |
|     XtAddCallback(rep, XtNcallback,
 | |
| 		  AdjustMonitorCallback, (XtPointer)RIGHT);
 | |
|     XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 | |
|     rep = XtCreateManagedWidget("down", repeaterWidgetClass,
 | |
| 				vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 | |
|     XtAddCallback(rep, XtNcallback,
 | |
| 		  AdjustMonitorCallback, (XtPointer)DOWN);
 | |
|     XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 | |
|     rep = XtCreateManagedWidget("wider", repeaterWidgetClass,
 | |
| 				vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 | |
|     XtAddCallback(rep, XtNcallback,
 | |
| 		  AdjustMonitorCallback, (XtPointer)WIDER);
 | |
|     XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 | |
|     rep = XtCreateManagedWidget("narrower", repeaterWidgetClass,
 | |
| 				vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 | |
|     XtAddCallback(rep, XtNcallback,
 | |
| 		  AdjustMonitorCallback, (XtPointer)NARROWER);
 | |
|     XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 | |
|     rep = XtCreateManagedWidget("shorter", repeaterWidgetClass,
 | |
| 				vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 | |
|     XtAddCallback(rep, XtNcallback,
 | |
| 		  AdjustMonitorCallback, (XtPointer)SHORTER);
 | |
|     XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 | |
|     rep = XtCreateManagedWidget("taller", repeaterWidgetClass,
 | |
| 				vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 | |
|     XtAddCallback(rep, XtNcallback,
 | |
| 		  AdjustMonitorCallback, (XtPointer)TALLER);
 | |
|     XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 | |
| 
 | |
|     automatic = XtCreateManagedWidget("auto", toggleWidgetClass, vtune, NULL, 0);
 | |
|     XtAddCallback(automatic, XtNcallback, AutoCallback, NULL);
 | |
|     apply = XtCreateManagedWidget("apply", commandWidgetClass, vtune, NULL, 0);
 | |
|     XtAddCallback(apply, XtNcallback, ApplyCallback, NULL);
 | |
|     restore = XtCreateManagedWidget("restore", commandWidgetClass, vtune, NULL, 0);
 | |
|     XtAddCallback(restore, XtNcallback, RestoreCallback, NULL);
 | |
|     rep = XtCreateManagedWidget("update", commandWidgetClass, vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNcallback, UpdateCallback, NULL);
 | |
|     rep = XtCreateManagedWidget("test", commandWidgetClass, vtune, NULL, 0);
 | |
|     XtAddCallback(rep, XtNcallback, TestCallback, NULL);
 | |
| 
 | |
|     form = XtCreateManagedWidget("form", formWidgetClass, vtune, NULL, 0);
 | |
|     for (i = 2; i < VSYNC + 1; i++) {
 | |
| 	(void) XtCreateManagedWidget(names[i], labelWidgetClass,
 | |
| 					  form, NULL, 0);
 | |
| 	values[i] = XtCreateManagedWidget(vnames[i], labelWidgetClass,
 | |
| 					  form, NULL, 0);
 | |
|     }
 | |
| 
 | |
|     add = XtCreateManagedWidget("add", commandWidgetClass, vtune, NULL, 0);
 | |
|     XtAddCallback(add, XtNcallback, AddModeCallback, NULL);
 | |
|     XtCreateManagedWidget("addto", labelWidgetClass, vtune, NULL, 0);
 | |
|     monitorb = XtCreateManagedWidget("ident", menuButtonWidgetClass, vtune,
 | |
| 				     NULL, 0);
 | |
|     XtCreateManagedWidget("as", labelWidgetClass, vtune, NULL, 0);
 | |
|     text = XtVaCreateManagedWidget("text", asciiTextWidgetClass, vtune,
 | |
| 				   XtNeditType, XawtextEdit, NULL);
 | |
| 
 | |
|     XtRealizeWidget(vtune);
 | |
| 
 | |
|     return (True);
 | |
| }
 | |
| 
 | |
| void
 | |
| InitializeVidmodes(void)
 | |
| {
 | |
|     int i;
 | |
|     Display *display = XtDisplay(toplevel);
 | |
| 
 | |
|     computer.num_vidmodes = ScreenCount(display);
 | |
|     computer.vidmodes = (xf86cfgVidmode**)
 | |
| 	XtMalloc(sizeof(xf86cfgVidmode*) * computer.num_vidmodes);
 | |
|     for (i = 0; i < computer.num_vidmodes; i++) {
 | |
| 
 | |
| 	computer.vidmodes[i] = (xf86cfgVidmode*)
 | |
| 	    XtCalloc(1, sizeof(xf86cfgVidmode));
 | |
| 	computer.vidmodes[i]->screen = i;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| VideoModeConfigureStart(void)
 | |
| {
 | |
|     vidtune = computer.vidmodes[screenno];
 | |
| 
 | |
|     XtSetSensitive(vtune, vidtune != NULL);
 | |
|     if (!XtIsManaged(vtune))
 | |
| 	XtManageChild(vtune);
 | |
|     else
 | |
| 	XtMapWidget(vtune);
 | |
|     if (vidtune != NULL) {
 | |
| 	Arg args[1];
 | |
| 	Boolean state;
 | |
| 	XF86ConfMonitorPtr mon;
 | |
| 	static char menuName[16];
 | |
| 	static int menuN;
 | |
| 
 | |
| 	XtErrorFunc = XSetErrorHandler(VidmodeError);
 | |
| 	XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, True);
 | |
| 	GetModeLine(True);
 | |
| 	GetModes();
 | |
| 
 | |
| 	SetLabels();
 | |
| 	XtSetArg(args[0], XtNstate, &state);
 | |
| 	XtGetValues(automatic, args, 1);
 | |
| 	XtSetSensitive(apply, !state);
 | |
| 	autoflag = state;
 | |
| 
 | |
| 	if (monitor)
 | |
| 	    XtDestroyWidget(monitor);
 | |
| 	XmuSnprintf(menuName, sizeof(menuName), "menuP%d", menuN);
 | |
| 	menuN = !menuN;
 | |
| 	monitor = XtCreatePopupShell(menuName, simpleMenuWidgetClass,
 | |
| 				     vtune, NULL, 0);
 | |
| 	XtVaSetValues(monitorb, XtNmenuName, menuName, NULL);
 | |
| 
 | |
| 	mon = XF86Config->conf_monitor_lst;
 | |
| 	while (mon != NULL) {
 | |
| 	    Widget sme = XtCreateManagedWidget(mon->mon_identifier,
 | |
| 					       smeBSBObjectClass,
 | |
| 					       monitor, NULL, 0);
 | |
| 	    XtAddCallback(sme, XtNcallback,
 | |
| 			  SelectMonitorCallback, (XtPointer)mon);
 | |
| 
 | |
| 	    /* guess the monitor at a given screen and/or
 | |
| 	     * updates configuration if a monitor was removed from the
 | |
| 	     * configuration.
 | |
| 	     */
 | |
| 	    if (XF86Config->conf_layout_lst) {
 | |
| 		XF86ConfAdjacencyPtr adj = XF86Config->conf_layout_lst->
 | |
| 		    lay_adjacency_lst;
 | |
| 
 | |
| 		while (adj != NULL) {
 | |
| 		    if (adj->adj_screen != NULL) {
 | |
| 			if (adj->adj_screen->scrn_monitor == mon &&
 | |
| 			    adj->adj_scrnum >= 0 &&
 | |
| 			    adj->adj_scrnum < ScreenCount(XtDisplay(toplevel))) {
 | |
| 			    if (computer.vidmodes[adj->adj_scrnum]->monitor ==
 | |
| 				NULL || computer.vidmodes[adj->adj_scrnum]->
 | |
| 				monitor == adj->adj_screen->scrn_monitor) {
 | |
| 				computer.vidmodes[adj->adj_scrnum]->monitor =
 | |
| 				    adj->adj_screen->scrn_monitor;
 | |
| 				break;
 | |
| 			    }
 | |
| 			    else
 | |
| 				computer.vidmodes[adj->adj_scrnum]->monitor =
 | |
| 				    NULL;
 | |
| 			}
 | |
| 		    }
 | |
| 		    adj = (XF86ConfAdjacencyPtr)(adj->list.next);
 | |
| 		}
 | |
| 	    }
 | |
| 	    mon = (XF86ConfMonitorPtr)(mon->list.next);
 | |
| 	}
 | |
| 	SetLabelAndModeline();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| VideoModeConfigureEnd(void)
 | |
| {
 | |
|     XtUnmapWidget(vtune);
 | |
|     if (vidtune != NULL) {
 | |
| 	XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, False);
 | |
| 	XSetErrorHandler(XtErrorFunc);
 | |
|     }
 | |
|     vidtune = NULL;
 | |
| }
 | |
| 
 | |
| static void
 | |
| SetLabelAndModeline(void)
 | |
| {
 | |
|     if (vidtune->monitor != NULL) {
 | |
| 	char string[32];
 | |
| 
 | |
| 	XtVaSetValues(monitorb, XtNlabel,
 | |
| 		      vidtune->monitor->mon_identifier, NULL);
 | |
| 	XtSetSensitive(add, True);
 | |
| 
 | |
| 	if (modeline.htotal && modeline.vtotal)
 | |
| 	    XmuSnprintf(string, sizeof(string), "%dx%d@%d",
 | |
| 			modeline.hdisplay, modeline.vdisplay,
 | |
| 			(int)((double)dot_clock / (double)modeline.htotal * 1000.0 /
 | |
| 			(double)modeline.vtotal));
 | |
| 	else
 | |
| 	    XmuSnprintf(string, sizeof(string), "%dx%d",
 | |
| 			modeline.hdisplay, modeline.vdisplay);
 | |
| 	XtVaSetValues(text, XtNstring, string, NULL);
 | |
|     }
 | |
|     else {
 | |
| 	XtVaSetValues(monitorb, XtNlabel, "", NULL);
 | |
| 	XtSetSensitive(add, False);
 | |
| 	XtVaSetValues(text, XtNstring, "", NULL);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| void
 | |
| VidmodeRestoreAction(Widget w, XEvent *event,
 | |
| 		     String *params, Cardinal *num_params)
 | |
| {
 | |
|     if (vidtune != NULL) {
 | |
| 	if (timeout != 0)
 | |
| 	    StopTestCallback(w, NULL, NULL);
 | |
| 	else
 | |
| 	    RestoreCallback(w, NULL, NULL);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| UpdateSyncRates(Bool update)
 | |
| {
 | |
|     if (modeline.htotal && modeline.vtotal) {
 | |
| 	hsync_rate = (dot_clock * 1000) / modeline.htotal;
 | |
| 	vsync_rate = (hsync_rate * 1000) / modeline.vtotal;
 | |
| 	if (modeline.flags & V_INTERLACE)
 | |
| 	    vsync_rate *= 2;
 | |
| 	else if (modeline.flags & V_DBLSCAN)
 | |
| 	    vsync_rate /= 2;
 | |
| 	if (update) {
 | |
| 	    SetLabel(HSYNC, hsync_rate);
 | |
| 	    SetLabel(VSYNC, vsync_rate);
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| SetLabel(int ident, int value)
 | |
| {
 | |
|     Arg args[1];
 | |
|     char label[256];
 | |
| 
 | |
|     if (ident == FLAGS) {
 | |
| 	int len = 0;
 | |
| 
 | |
| 	*label = '\0';
 | |
| 	if (value & V_PHSYNC)
 | |
| 	    len += XmuSnprintf(label, sizeof(label), "%s", "+hsync");
 | |
| 	if (modeline.flags & V_NHSYNC)
 | |
| 	    len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 | |
| 			       len ? " " : "", "-hsync");
 | |
| 	if (value & V_PVSYNC)
 | |
| 	    len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 | |
| 			       len ? " " : "", "+vsync");
 | |
| 	if (value & V_NVSYNC)
 | |
| 	    len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 | |
| 			       len ? " " : "", "-vsync");
 | |
| 	if (value & V_INTERLACE)
 | |
| 	    len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 | |
| 			       len ? " " : "", "interlace");
 | |
| 	if (value & V_CSYNC)
 | |
| 	    len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 | |
| 			       len ? " " : "", "composite");
 | |
| 	if (value & V_PCSYNC)
 | |
| 	    len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 | |
| 			       len ? " " : "", "+csync");
 | |
| 	if (value & V_NCSYNC)
 | |
| 	    len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 | |
| 			       len ? " " : "", "-csync");
 | |
| 	if (value & V_DBLSCAN)
 | |
| 	    len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 | |
| 			       len ? " " : "", "doublescan");
 | |
| 
 | |
|     }
 | |
|     else if (ident == CLOCK || ident == HSYNC || ident == VSYNC)
 | |
| 	XmuSnprintf(label, sizeof(label), "%6.2f", (float)value / 1000.0);
 | |
|     else
 | |
| 	XmuSnprintf(label, sizeof(label), "%d", value);
 | |
| 
 | |
|     XtSetArg(args[0], XtNlabel, label);
 | |
|     XtSetValues(values[ident], args, 1);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| StartAdjustMonitorCallback(Widget w, XtPointer client_data, XtPointer call_data)
 | |
| {
 | |
|     repeater = w;
 | |
| }
 | |
| 
 | |
| static void
 | |
| AdjustMonitorCallback(Widget w, XtPointer client_data, XtPointer call_data)
 | |
| {
 | |
|     if (repeater != w)
 | |
| 	return;
 | |
|     switch ((long)client_data) {
 | |
| 	case LEFT:
 | |
| 	    if (modeline.hsyncend + 4 < modeline.htotal) {
 | |
| 		modeline.hsyncstart += 4;
 | |
| 		modeline.hsyncend += 4;
 | |
| 		SetLabel(HSYNCSTART, modeline.hsyncstart);
 | |
| 		SetLabel(HSYNCEND, modeline.hsyncend);
 | |
| 	    }
 | |
| 	    else
 | |
| 		XBell(XtDisplay(w), 80);
 | |
| 	    break;
 | |
| 	case RIGHT:
 | |
| 	    if (modeline.hsyncstart - 4 > modeline.hdisplay) {
 | |
| 		modeline.hsyncstart -= 4;
 | |
| 		modeline.hsyncend -= 4;
 | |
| 		SetLabel(HSYNCSTART, modeline.hsyncstart);
 | |
| 		SetLabel(HSYNCEND, modeline.hsyncend);
 | |
| 	    }
 | |
| 	    else
 | |
| 		XBell(XtDisplay(w), 80);
 | |
| 	    break;
 | |
| 	case NARROWER:
 | |
| 	    modeline.htotal += 4;
 | |
| 	    SetLabel(HTOTAL, modeline.htotal);
 | |
| 	    UpdateSyncRates(True);
 | |
| 	    break;
 | |
| 	case WIDER:
 | |
| 	    if (modeline.htotal - 4 > modeline.hsyncend) {
 | |
| 		modeline.htotal -= 4;
 | |
| 		SetLabel(HTOTAL, modeline.htotal);
 | |
| 		UpdateSyncRates(True);
 | |
| 	    }
 | |
| 	    else
 | |
| 		XBell(XtDisplay(w), 80);
 | |
| 	    break;
 | |
| 	case UP:
 | |
| 	    if (modeline.vsyncend + 4 < modeline.vtotal) {
 | |
| 		modeline.vsyncstart += 4;
 | |
| 		modeline.vsyncend += 4;
 | |
| 		SetLabel(VSYNCSTART, modeline.vsyncstart);
 | |
| 		SetLabel(VSYNCEND, modeline.vsyncend);
 | |
| 	    }
 | |
| 	    else
 | |
| 		XBell(XtDisplay(w), 80);
 | |
| 	    break;
 | |
| 	case DOWN:
 | |
| 	    if (modeline.vsyncstart - 4 > modeline.vdisplay) {
 | |
| 		modeline.vsyncstart -= 4;
 | |
| 		modeline.vsyncend -= 4;
 | |
| 		SetLabel(VSYNCSTART, modeline.vsyncstart);
 | |
| 		SetLabel(VSYNCEND, modeline.vsyncend);
 | |
| 	    }
 | |
| 	    else
 | |
| 		XBell(XtDisplay(w), 80);
 | |
| 	    break;
 | |
| 	case SHORTER:
 | |
| 	    modeline.vtotal += 4;
 | |
| 	    SetLabel(VTOTAL, modeline.vtotal);
 | |
| 	    UpdateSyncRates(True);
 | |
| 	    break;
 | |
| 	case TALLER:
 | |
| 	    if (modeline.vtotal - 4 >  modeline.vsyncend) {
 | |
| 		modeline.vtotal -= 4;
 | |
| 		SetLabel(VTOTAL, modeline.vtotal);
 | |
| 		UpdateSyncRates(True);
 | |
| 	    }
 | |
| 	    else
 | |
| 		XBell(XtDisplay(w), 80);
 | |
| 	    break;
 | |
|     }
 | |
| 
 | |
|     if (autoflag)
 | |
| 	ApplyCallback(w, call_data, client_data);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| EndAdjustMonitorCallback(Widget w, XtPointer client_data, XtPointer call_data)
 | |
| {
 | |
|     repeater = NULL;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| GetModeLine(Bool save)
 | |
| {
 | |
|     if (XF86VidModeGetModeLine(XtDisplay(toplevel), vidtune->screen,
 | |
| 			       &dot_clock, &modeline)) {
 | |
| 	if (save)
 | |
| 	    memcpy(&orig_modeline, &modeline, sizeof(XF86VidModeModeLine));
 | |
| 	UpdateSyncRates(False);
 | |
| 	return (True);
 | |
|     }
 | |
| 
 | |
|     return (False);
 | |
| }
 | |
| 
 | |
| static void
 | |
| CleanUp(Display *display)
 | |
| {
 | |
|     /* Make sure mode switching is not locked out at exit */
 | |
|     XF86VidModeLockModeSwitch(display, vidtune->screen, False);
 | |
|     XFlush(display);
 | |
| }
 | |
| 
 | |
| static int
 | |
| VidmodeError(Display *display, XErrorEvent *error)
 | |
| {
 | |
|     if ((error->error_code >= ErrorBase &&
 | |
| 	 error->error_code < ErrorBase + XF86VidModeNumberErrors) ||
 | |
| 	 error->error_code == BadValue) {
 | |
| 	 hitError = 1;
 | |
|     }
 | |
|     else {
 | |
| 	CleanUp(display);
 | |
| 	if (XtErrorFunc) 
 | |
| 	    (*XtErrorFunc)(display, error);
 | |
|     }
 | |
|     return (0);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| ApplyCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     hitError = 0;
 | |
|     XF86VidModeModModeLine(XtDisplay(w), vidtune->screen, &modeline);
 | |
|     XSync(XtDisplay(w), False);
 | |
|     if (hitError) {
 | |
| 	if (repeater != NULL) {
 | |
| 	    XtCallActionProc(repeater, "unset", NULL, NULL, 0);
 | |
| 	    XtCallActionProc(repeater, "stop", NULL, NULL, 0);
 | |
| 	    repeater = NULL;
 | |
| 	}
 | |
| 	XBell(XtDisplay(w), 80);
 | |
| 	if (timeout)
 | |
| 	    StopTestCallback(w, NULL, NULL);
 | |
| 	GetModeLine(False);
 | |
| 	SetLabels();
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| AutoCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     autoflag = (Bool)(long)client_data;
 | |
|     XtSetSensitive(apply, !autoflag);
 | |
| }
 | |
| 
 | |
| static void
 | |
| RestoreCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     memcpy(&modeline, &orig_modeline, sizeof(XF86VidModeModeLine));
 | |
|     if (autoflag)
 | |
| 	ApplyCallback(w, call_data, client_data);
 | |
|     SetLabels();
 | |
| }
 | |
| 
 | |
| static void
 | |
| SelectCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     XF86VidModeModeInfo *info = (XF86VidModeModeInfo*)call_data;
 | |
|     Arg args[1];
 | |
|     Bool result;
 | |
| 
 | |
|     XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, False);
 | |
|     result = XF86VidModeSwitchToMode(XtDisplay(toplevel), vidtune->screen, info);
 | |
|     XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, True);
 | |
|     if (!result)
 | |
| 	return;
 | |
| 
 | |
|     XtSetArg(args[0], XtNlabel, XtName(w));
 | |
|     XtSetValues(mode, args, 1);
 | |
|     UpdateCallback(w, call_data, client_data);
 | |
| }
 | |
| 
 | |
| static void
 | |
| SwitchCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     int direction = (long)call_data;
 | |
|     Arg args[1];
 | |
|     Bool result;
 | |
|     char label[32];
 | |
| 
 | |
|     XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, False);
 | |
|     result = XF86VidModeSwitchMode(XtDisplay(toplevel), vidtune->screen,
 | |
| 				   direction);
 | |
|     XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, True);
 | |
|     if (!result)
 | |
| 	return;
 | |
| 
 | |
|     UpdateCallback(w, call_data, client_data);
 | |
| 
 | |
|     if (modeline.htotal && modeline.vtotal)
 | |
| 	XmuSnprintf(label, sizeof(label), "%dx%d @ %d Hz",
 | |
| 		    modeline.hdisplay, modeline.vdisplay,
 | |
| 		    (int)((double)dot_clock / (double)modeline.htotal * 1000.0 /
 | |
| 		    (double)modeline.vtotal));
 | |
|     else
 | |
| 	XmuSnprintf(label, sizeof(label), "%dx%d",
 | |
| 		    modeline.hdisplay, modeline.vdisplay);
 | |
|     XtSetArg(args[0], XtNlabel, label);
 | |
|     XtSetValues(mode, args, 1);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| UpdateCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     GetModeLine(True);
 | |
|     SetLabels();
 | |
|     SetLabelAndModeline();
 | |
| }
 | |
| 
 | |
| static void
 | |
| SetLabels(void)
 | |
| {
 | |
|     SetLabel(HSYNCSTART, modeline.hsyncstart);
 | |
|     SetLabel(VSYNCSTART, modeline.vsyncstart);
 | |
|     SetLabel(HSYNCEND, modeline.hsyncend);
 | |
|     SetLabel(VSYNCEND, modeline.vsyncend);
 | |
|     SetLabel(HTOTAL, modeline.htotal);
 | |
|     SetLabel(VTOTAL, modeline.vtotal);
 | |
|     SetLabel(FLAGS, modeline.flags);
 | |
|     SetLabel(CLOCK, dot_clock);
 | |
|     UpdateSyncRates(True);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| ChangeScreenCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     Arg args[1];
 | |
| 
 | |
|     screenno = (long)call_data;
 | |
|     if (screenno > computer.num_vidmodes || screenno < 0 ||
 | |
| 	vidtune == computer.vidmodes[screenno])
 | |
| 	return;
 | |
| 
 | |
|     XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, False);
 | |
|     vidtune = computer.vidmodes[screenno];
 | |
|     XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, True);
 | |
|     UpdateCallback(w, call_data, client_data);
 | |
|     GetModes();
 | |
| 
 | |
|     XtSetArg(args[0], XtNlabel, XtName(w));
 | |
|     XtSetValues(screenb, args, 1);
 | |
| 
 | |
|     SetLabelAndModeline();
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| SelectMonitorCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     vidtune->monitor = (XF86ConfMonitorPtr)(call_data);
 | |
|     SetLabelAndModeline();
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| AddVesaModeCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     xf86cfgVesaModeInfo *vesa = (xf86cfgVesaModeInfo*)call_data;
 | |
|     XF86VidModeModeInfo mode;
 | |
|     int num_infos = vidtune->num_infos;
 | |
| 
 | |
|     memcpy(&mode, &vesa->info, sizeof(XF86VidModeModeInfo));
 | |
|     if (XF86VidModeAddModeLine(XtDisplay(toplevel), vidtune->screen,
 | |
| 			       &vesa->info, &mode)) {
 | |
| 	XSync(XtDisplay(toplevel), False);
 | |
| 	GetModes();
 | |
|     }
 | |
|     else {
 | |
| 	XBell(XtDisplayOfObject(w), 80);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     if (vidtune && num_infos == vidtune->num_infos) {
 | |
| 	/* XF86VidModeAddModeLine returned True, but no modeline was added */
 | |
| 	XBell(XtDisplayOfObject(w), 80);
 | |
| 	if (vidtune->monitor && AddMode()) {
 | |
| 	    XF86ConfModeLinePtr mode;
 | |
| 	    char label[256], *ptr, *str;
 | |
| 
 | |
| 	    XmuSnprintf(label, sizeof(label), "%s", vesa->ident);
 | |
| 
 | |
| 	    /* format mode name to not have spaces */
 | |
| 	    ptr = strchr(label, ')');
 | |
| 	    if (ptr)
 | |
| 		*++ptr = '\0';
 | |
| 	    ptr = str = label;
 | |
| 	    while (*ptr) {
 | |
| 		if (*ptr != ' ')
 | |
| 		    *str++ = *ptr;
 | |
| 		++ptr;
 | |
| 	    }
 | |
| 	    *str = '\0';
 | |
| 
 | |
| 	    if (xf86findModeLine(label, vidtune->monitor->mon_modeline_lst)
 | |
| 		!= NULL && !ForceAddMode())
 | |
| 		return;
 | |
| 
 | |
| 	    mode = (XF86ConfModeLinePtr)XtCalloc(1, sizeof(XF86ConfModeLineRec));
 | |
| 	    mode->ml_identifier = XtNewString(label);
 | |
| 	    mode->ml_clock = vesa->info.dotclock;
 | |
| 	    mode->ml_hdisplay = vesa->info.hdisplay;
 | |
| 	    mode->ml_hsyncstart = vesa->info.hsyncstart;
 | |
| 	    mode->ml_hsyncend = vesa->info.hsyncend;
 | |
| 	    mode->ml_htotal = vesa->info.htotal;
 | |
| 	    mode->ml_vdisplay = vesa->info.vdisplay;
 | |
| 	    mode->ml_vsyncstart = vesa->info.vsyncstart;
 | |
| 	    mode->ml_vsyncend = vesa->info.vsyncend;
 | |
| 	    mode->ml_vtotal = vesa->info.vtotal;
 | |
| /*	    mode->ml_vscan = ???;*/
 | |
| 	    mode->ml_flags = vesa->info.flags;
 | |
| 	    mode->ml_hskew = vesa->info.hskew;
 | |
| 	    vidtune->monitor->mon_modeline_lst =
 | |
| 		xf86addModeLine(vidtune->monitor->mon_modeline_lst, mode);
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| GetModes(void)
 | |
| {
 | |
|     int i;
 | |
|     char label[32];
 | |
|     Arg args[1];
 | |
|     static char menuName[16];
 | |
|     static int menuN;
 | |
| 
 | |
|     XFree(vidtune->infos);
 | |
|     XF86VidModeGetAllModeLines(XtDisplay(toplevel), vidtune->screen,
 | |
| 			       &vidtune->num_infos, &vidtune->infos);
 | |
| 
 | |
|     XmuSnprintf(menuName, sizeof(menuName), "menu%d", menuN);
 | |
|     menuN = !menuN;
 | |
|     if (menu)
 | |
| 	XtDestroyWidget(menu);
 | |
|     menu = XtCreatePopupShell(menuName, simpleMenuWidgetClass, vtune, NULL, 0);
 | |
|     XtVaSetValues(mode, XtNmenuName, menuName, NULL);
 | |
|     for (i = 0; i < vidtune->num_infos; i++) {
 | |
| 	Widget sme;
 | |
| 
 | |
| 	if ((double)vidtune->infos[i]->htotal &&
 | |
| 	    (double)vidtune->infos[i]->vtotal)
 | |
| 	    XmuSnprintf(label, sizeof(label), "%dx%d @ %d Hz",
 | |
| 			vidtune->infos[i]->hdisplay,
 | |
| 			vidtune->infos[i]->vdisplay,
 | |
| 			(int)((double)vidtune->infos[i]->dotclock /
 | |
| 			(double)vidtune->infos[i]->htotal * 1000.0 /
 | |
| 			(double)vidtune->infos[i]->vtotal));
 | |
| 	else
 | |
| 	    XmuSnprintf(label, sizeof(label), "%dx%d",
 | |
| 			vidtune->infos[i]->hdisplay,
 | |
| 			vidtune->infos[i]->vdisplay);
 | |
| 	sme = XtCreateManagedWidget(label, smeBSBObjectClass, menu, NULL, 0);
 | |
| 	XtAddCallback(sme, XtNcallback, SelectCallback,
 | |
| 		      (XtPointer)vidtune->infos[i]);
 | |
|     }
 | |
| 
 | |
|     if (modeline.htotal && modeline.vtotal)
 | |
| 	XmuSnprintf(label, sizeof(label), "%dx%d @ %d Hz",
 | |
| 		    modeline.hdisplay, modeline.vdisplay,
 | |
| 		    (int)((double)dot_clock / (double)modeline.htotal * 1000.0 /
 | |
| 		    (double)modeline.vtotal));
 | |
|     else
 | |
| 	XmuSnprintf(label, sizeof(label), "%dx%d",
 | |
| 		    modeline.hdisplay, modeline.vdisplay);
 | |
|     XtSetArg(args[0], XtNlabel, label);
 | |
|     XtSetValues(mode, args, 1);
 | |
| }
 | |
| 
 | |
| static int do_force, asking_force;
 | |
| 
 | |
| static void
 | |
| PopdownForce(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     asking_force = 0;
 | |
|     XtPopdown(forceshell);
 | |
|     do_force = (long)user_data;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ForceAddMode(void)
 | |
| {
 | |
|     if (forceshell == NULL) {
 | |
| 	Widget dialog;
 | |
| 
 | |
| 	forceshell = XtCreatePopupShell("force", transientShellWidgetClass,
 | |
| 					toplevel, NULL, 0);
 | |
| 	dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass,
 | |
| 					 forceshell, XtNvalue, NULL, NULL);
 | |
| 	XawDialogAddButton(dialog, "yes", PopdownForce, (XtPointer)True);
 | |
| 	XawDialogAddButton(dialog, "no", PopdownForce, (XtPointer)False);
 | |
| 	XtRealizeWidget(forceshell);
 | |
| 	XSetWMProtocols(DPY, XtWindow(forceshell), &wm_delete_window, 1);
 | |
|     }
 | |
| 
 | |
|     asking_force = 1;
 | |
| 
 | |
|     XtPopup(forceshell, XtGrabExclusive);
 | |
|     while (asking_force)
 | |
| 	XtAppProcessEvent(XtWidgetToApplicationContext(forceshell), XtIMAll);
 | |
| 
 | |
|     return (do_force);
 | |
| }
 | |
| 
 | |
| static int do_add, asking_add;
 | |
| 
 | |
| static void
 | |
| PopdownAdd(Widget w, XtPointer user_data, XtPointer call_data)
 | |
| {
 | |
|     asking_add = 0;
 | |
|     XtPopdown(addshell);
 | |
|     do_add = (long)user_data;
 | |
| }
 | |
| 
 | |
| void
 | |
| CancelAddModeAction(Widget w, XEvent *event,
 | |
| 		       String *params, Cardinal *num_params)
 | |
| {
 | |
|     if (asking_force)
 | |
| 	PopdownForce(w, (XtPointer)False, NULL);
 | |
|     else if (asking_add)
 | |
| 	PopdownAdd(w, (XtPointer)False, NULL);
 | |
| }
 | |
| 
 | |
| static int
 | |
| AddMode(void)
 | |
| {
 | |
|     if (addshell == NULL) {
 | |
| 	Widget dialog;
 | |
| 
 | |
| 	addshell = XtCreatePopupShell("addMode", transientShellWidgetClass,
 | |
| 				      toplevel, NULL, 0);
 | |
| 	dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass,
 | |
| 					 addshell, XtNvalue, NULL, NULL);
 | |
| 	XawDialogAddButton(dialog, "yes", PopdownAdd, (XtPointer)True);
 | |
| 	XawDialogAddButton(dialog, "no", PopdownAdd, (XtPointer)False);
 | |
| 	XtRealizeWidget(addshell);
 | |
| 	XSetWMProtocols(DPY, XtWindow(addshell), &wm_delete_window, 1);
 | |
|     }
 | |
| 
 | |
|     asking_add = 1;
 | |
| 
 | |
|     XtPopup(addshell, XtGrabExclusive);
 | |
|     while (asking_add)
 | |
| 	XtAppProcessEvent(XtWidgetToApplicationContext(addshell), XtIMAll);
 | |
| 
 | |
|     return (do_add);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| AddModeCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     if (vidtune && vidtune->monitor) {
 | |
| 	char *label;
 | |
| 	Arg args[1];
 | |
| 	XF86ConfModeLinePtr mode;
 | |
| 
 | |
| 	XtSetArg(args[0], XtNstring, &label);
 | |
| 	XtGetValues(text, args, 1);
 | |
| 	if (*label == '\0') {
 | |
| 	    XBell(XtDisplay(w), 80);
 | |
| 	    return;
 | |
| 	}	    
 | |
| 	if (xf86findModeLine(label, vidtune->monitor->mon_modeline_lst)
 | |
| 	    != NULL && !ForceAddMode())
 | |
| 	    return;
 | |
| 
 | |
| 	mode = (XF86ConfModeLinePtr)XtCalloc(1, sizeof(XF86ConfModeLineRec));
 | |
| 	mode->ml_identifier = XtNewString(label);
 | |
| 	mode->ml_clock = dot_clock;
 | |
| 	mode->ml_hdisplay = modeline.hdisplay;
 | |
| 	mode->ml_hsyncstart = modeline.hsyncstart;
 | |
| 	mode->ml_hsyncend = modeline.hsyncend;
 | |
| 	mode->ml_htotal = modeline.htotal;
 | |
| 	mode->ml_vdisplay = modeline.vdisplay;
 | |
| 	mode->ml_vsyncstart = modeline.vsyncstart;
 | |
| 	mode->ml_vsyncend = modeline.vsyncend;
 | |
| 	mode->ml_vtotal = modeline.vtotal;
 | |
| /*	mode->ml_vscan = ???;*/
 | |
| 	mode->ml_flags = modeline.flags;
 | |
| 	mode->ml_hskew = modeline.hskew;
 | |
| 	vidtune->monitor->mon_modeline_lst =
 | |
| 	    xf86addModeLine(vidtune->monitor->mon_modeline_lst, mode);
 | |
|     }
 | |
|     else
 | |
| 	XBell(XtDisplay(w), 80);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| StopTestCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     XtRemoveTimeOut(timeout);
 | |
|     TestTimeout((XtPointer)w, NULL);
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| void
 | |
| CancelTestModeAction(Widget w, XEvent *event,
 | |
| 		     String *params, Cardinal *num_params)
 | |
| {
 | |
|     StopTestCallback(w, NULL, NULL);
 | |
| }
 | |
| 
 | |
| static void
 | |
| TestTimeout(XtPointer client_data, XtIntervalId* id)
 | |
| {
 | |
|     XF86VidModeModeLine mode;
 | |
| 
 | |
|     XtPopdown(testshell);
 | |
|     timeout = 0;
 | |
|     memcpy(&mode, &modeline, sizeof(XF86VidModeModeLine));
 | |
|     memcpy(&modeline, &orig_modeline, sizeof(XF86VidModeModeLine));
 | |
|     ApplyCallback((Widget)client_data, NULL, NULL);
 | |
| /*    if (hitError == 0)*/
 | |
| 	memcpy(&modeline, &mode, sizeof(XF86VidModeModeLine));
 | |
|     SetLabels();
 | |
| }
 | |
| 
 | |
| static void
 | |
| TestCallback(Widget w, XtPointer call_data, XtPointer client_data)
 | |
| {
 | |
|     if (testshell == NULL) {
 | |
| 	Widget dialog;
 | |
| 
 | |
| 	testshell = XtCreatePopupShell("test", transientShellWidgetClass,
 | |
| 					toplevel, NULL, 0);
 | |
| 	dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass,
 | |
| 					 testshell, XtNvalue, NULL, NULL);
 | |
| 	XawDialogAddButton(dialog, "stop", StopTestCallback, NULL);
 | |
| 	XtRealizeWidget(testshell);
 | |
| 	XSetWMProtocols(DPY, XtWindow(testshell), &wm_delete_window, 1);
 | |
|     }
 | |
| 
 | |
|     XtPopup(testshell, XtGrabExclusive);
 | |
| 
 | |
|     XSync(XtDisplay(toplevel), False);
 | |
|     timeout = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
 | |
|     /* the timeout probably shoud be converted to a resource */
 | |
| 			      4000, TestTimeout, (XtPointer)w);
 | |
|     ApplyCallback(w, call_data, client_data);
 | |
| }
 |