summaryrefslogtreecommitdiff
path: root/hw/xfree86/utils/xorgcfg/vidmode.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/utils/xorgcfg/vidmode.c')
-rw-r--r--hw/xfree86/utils/xorgcfg/vidmode.c1357
1 files changed, 1357 insertions, 0 deletions
diff --git a/hw/xfree86/utils/xorgcfg/vidmode.c b/hw/xfree86/utils/xorgcfg/vidmode.c
new file mode 100644
index 000000000..d28ac0899
--- /dev/null
+++ b/hw/xfree86/utils/xorgcfg/vidmode.c
@@ -0,0 +1,1357 @@
+/*
+ * 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>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/vidmode.c,v 1.7 2001/07/07 23:00:43 paulo Exp $
+ */
+
+/*
+ * 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 Bool S3Specials;
+static int invert_vclk, blank1, blank2, early_sc, screenno;
+static int (*XtErrorFunc)(Display*, XErrorEvent*);
+static Widget labels[VSYNC + 1], values[VSYNC + 1], repeater, monitor,
+ monitorb, add, text, vesab, 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);
+
+ vesab = XtVaCreateManagedWidget("vesaB", menuButtonWidgetClass, vtune,
+ XtNmenuName, "vesaP", NULL, 0);
+ 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, 0);
+ }
+ }
+ 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++) {
+ labels[i] = 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, 0);
+
+ 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, 0);
+
+ 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);
+ if (modeline.privsize != 0 && modeline.private != NULL) {
+ S3Specials = True;
+ invert_vclk = modeline.private[1];
+ blank1 = modeline.private[2] & 7;
+ blank2 = (modeline.private[2] >> 4) & 7;
+ early_sc = modeline.private[3];
+ }
+ else
+ S3Specials = 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, 0);
+ 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, 0);
+ 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, 0);
+ 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, 0);
+ 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);
+}