[pkg-nvidia-devel] r574 - in /packages/nvidia-settings/trunk: ./ src/ src/XF86Config-parser/ src/gtk+-2.x/ src/libXNVCtrl/

fabo at users.alioth.debian.org fabo at users.alioth.debian.org
Tue Jul 28 07:31:58 UTC 2009


Author: fabo
Date: Tue Jul 28 07:31:57 2009
New Revision: 574

URL: http://svn.debian.org/wsvn/pkg-nvidia/?sc=1&rev=574
Log:
Update nvidia-settings upstream source code to 185.18.14

Modified:
    packages/nvidia-settings/trunk/Makefile
    packages/nvidia-settings/trunk/src/XF86Config-parser/Generate.c
    packages/nvidia-settings/trunk/src/XF86Config-parser/xf86Parser.h
    packages/nvidia-settings/trunk/src/config-file.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkconfig.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig-utils.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig-utils.h
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig.h
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-crt.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-dfp.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-tv.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaylayout.h
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkevent.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkframelock.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkglx.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkgpu.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkgvo.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkhelp.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkhelp.h
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkimagesliders.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkimagesliders.h
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkmultisample.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkpowermizer.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkserver.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkslimm.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkslimm.h
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkwindow.c
    packages/nvidia-settings/trunk/src/gtk+-2.x/ctkxvideo.c
    packages/nvidia-settings/trunk/src/libXNVCtrl/NVCtrl.h
    packages/nvidia-settings/trunk/src/libXNVCtrl/nv_control.h
    packages/nvidia-settings/trunk/src/parse.c
    packages/nvidia-settings/trunk/src/parse.h
    packages/nvidia-settings/trunk/src/query-assign.c

Modified: packages/nvidia-settings/trunk/Makefile
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/Makefile?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/Makefile (original)
+++ packages/nvidia-settings/trunk/Makefile Tue Jul 28 07:31:57 2009
@@ -1,6 +1,3 @@
-DESTDIR=
-ROOT=$(DESTDIR)
-X11R6_LIB_DIR = /usr/lib
 #
 # nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
 # and Linux systems.

Modified: packages/nvidia-settings/trunk/src/XF86Config-parser/Generate.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/XF86Config-parser/Generate.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/XF86Config-parser/Generate.c (original)
+++ packages/nvidia-settings/trunk/src/XF86Config-parser/Generate.c Tue Jul 28 07:31:57 2009
@@ -374,6 +374,15 @@
 static void add_modules(GenerateOptions *gop, XConfigPtr config)
 {
     XConfigLoadPtr l = NULL;
+
+    /*
+     * if the X server will automatically autoload GLX, then don't
+     * bother adding a modules section; it is difficult for
+     * nvidia-xconfig to know if modules like "type1" are present,
+     * anyway.
+     */
+
+    if (gop->autoloads_glx) return;
 
     config->modules = xconfigAlloc(sizeof(XConfigModuleRec));
     
@@ -1329,6 +1338,104 @@
 
 
 
+
+/*
+ * get_xserver_information() - parse the versionString (from `X
+ * -version`) and assign relevant information that we infer from the X
+ * server version.
+ *
+ * Note: this implementation should be shared with nvidia-installer
+ */
+
+static int get_xserver_information(const char *versionString,
+                                   int *isXorg,
+                                   int *isModular,
+                                   int *autoloadsGLX,
+                                   int *supportsExtensionSection)
+{
+#define XSERVER_VERSION_FORMAT_1 "X Window System Version"
+#define XSERVER_VERSION_FORMAT_2 "X.Org X Server"
+
+    int major, minor, found;
+    const char *ptr;
+
+    /* check if this is an XFree86 X server */
+
+    if (strstr(versionString, "XFree86 Version")) {
+        *isXorg = FALSE;
+        *isModular = FALSE;
+        *autoloadsGLX = FALSE;
+        *supportsExtensionSection = FALSE;
+        return TRUE;
+    }
+
+    /* this must be an X.Org X server */
+
+    *isXorg = TRUE;
+
+    /* attempt to parse the major.minor version out of the string */
+
+    found = FALSE;
+
+    if (((ptr = strstr(versionString, XSERVER_VERSION_FORMAT_1)) != NULL) &&
+        (sscanf(ptr, XSERVER_VERSION_FORMAT_1 " %d.%d", &major, &minor) == 2)) {
+        found = TRUE;
+    }
+
+    if (!found &&
+        ((ptr = strstr(versionString, XSERVER_VERSION_FORMAT_2)) != NULL) &&
+        (sscanf(ptr, XSERVER_VERSION_FORMAT_2 " %d.%d", &major, &minor) == 2)) {
+        found = TRUE;
+    }
+
+    /* if we can't parse the version, give up */
+
+    if (!found) return FALSE;
+
+    /*
+     * isModular: X.Org X11R6.x X servers are monolithic, all others
+     * are modular
+     */
+
+    if (major == 6) {
+        *isModular = FALSE;
+    } else {
+        *isModular = TRUE;
+    }
+
+    /*
+     * supportsExtensionSection: support for the "Extension" xorg.conf
+     * section was added between X.Org 6.7 and 6.8.  To account for
+     * the X server version wrap, it is easier to check for X servers
+     * that do not support the Extension section: 6.x (x < 8) X
+     * servers.
+     */
+
+    if ((major == 6) && (minor < 8)) {
+        *supportsExtensionSection = FALSE;
+    } else {
+        *supportsExtensionSection = TRUE;
+    }
+
+    /*
+     * support for autoloading GLX was added in X.Org 1.5.  To account
+     * for the X server version wrap, it is easier to check for X
+     * servers that do not support GLX autoloading: 6.x, 7.x, or < 1.5
+     * X servers.
+     */
+
+    if ((major == 6) || (major == 7) || ((major == 1) && (minor < 5))) {
+        *autoloadsGLX = FALSE;
+    } else {
+        *autoloadsGLX = TRUE;
+    }
+
+    return TRUE;
+
+} /* get_xserver_information() */
+
+
+
 /*
  * xconfigGetXServerInUse() - try to determine which X server is in use
  * (XFree86, Xorg); also determine if the X server supports the
@@ -1341,33 +1448,29 @@
 
 #define NV_LINE_LEN 1024
 #define EXTRA_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/bin/X11"
-#define VERSION_FORMAT "X Protocol Version %d, Revision %d, Release %d.%d"
+#if defined(NV_SUNOS)
+#define XSERVER_BIN_NAME "Xorg"
+#else
+#define XSERVER_BIN_NAME "X"
+#endif
+
 
 void xconfigGetXServerInUse(GenerateOptions *gop)
 {
-#if defined(NV_SUNOS)    
-
-    /*
-     * Solaris x86/x64 always uses X.Org 6.8 or higher, atleast as far
-     * as the NVIDIA X driver is concerned
-     */
-    
-    gop->xserver = X_IS_XORG;
-    gop->supports_extension_section = TRUE;
-    
-#else
-    
     FILE *stream = NULL;
     int xserver = -1;
-    int dummy, len, release_major, release_minor;
+    int isXorg;
+    int dummy, len, found;
     char *cmd, *ptr, *ret;
     
     gop->supports_extension_section = FALSE;
-    
+    gop->autoloads_glx = FALSE;
+
     /* run `X -version` with a PATH that hopefully includes the X binary */
     
     cmd = xconfigStrcat("PATH=", gop->x_project_root, ":",
-                        EXTRA_PATH, ":$PATH X -version 2>&1", NULL);
+                        EXTRA_PATH, ":$PATH ", XSERVER_BIN_NAME,
+                        " -version 2>&1", NULL);
     
     if ((stream = popen(cmd, "r"))) {
         char buf[NV_LINE_LEN];
@@ -1382,23 +1485,26 @@
             ptr = strchr(ptr, '\0');
         } while ((ret != NULL) && (len > 1));
         
-        /* Check if this is an XFree86 release */
-        
-        if (strstr(buf, "XFree86 Version") != NULL) {
-            xserver = X_IS_XF86;
-            gop->supports_extension_section = FALSE;
+        /*
+         * process the `X -version` output to infer relevant
+         * information from this X server
+         */
+        
+        found = get_xserver_information(buf,
+                                        &isXorg,
+                                        &dummy, /* isModular */
+                                        &gop->autoloads_glx,
+                                        &gop->supports_extension_section);
+                
+        if (found) {
+            if (isXorg) {
+                xserver = X_IS_XORG;
+            } else {
+                xserver = X_IS_XF86;
+            }
         } else {
-            xserver = X_IS_XORG;
-            if ((ptr = strstr(buf, "X Protocol Version")) != NULL &&
-                sscanf(ptr, VERSION_FORMAT, &dummy, &dummy,
-                       &release_major, &release_minor) == 4) {
-                
-                if ((release_major > 6) ||
-                    ((release_major == 6) && (release_minor >= 8))) {
-                    gop->supports_extension_section = TRUE; 
-                }
-            }
-        } 
+            xconfigErrorMsg(WarnMsg, "Unable to parse X.Org version string.");
+        }
     }
     /* Close the popen()'ed stream. */
     pclose(stream);
@@ -1417,7 +1523,6 @@
     }
     
     gop->xserver=xserver;
-#endif
 
 } /* xconfigGetXServerInUse() */
 

Modified: packages/nvidia-settings/trunk/src/XF86Config-parser/xf86Parser.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/XF86Config-parser/xf86Parser.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/XF86Config-parser/xf86Parser.h (original)
+++ packages/nvidia-settings/trunk/src/XF86Config-parser/xf86Parser.h Tue Jul 28 07:31:57 2009
@@ -593,6 +593,7 @@
     char *keyboard_driver;
 
     int supports_extension_section;
+    int autoloads_glx;
 
 } GenerateOptions;
 

Modified: packages/nvidia-settings/trunk/src/config-file.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/config-file.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/config-file.c (original)
+++ packages/nvidia-settings/trunk/src/config-file.c Tue Jul 28 07:31:57 2009
@@ -214,7 +214,8 @@
     NVCTRLAttributeValidValuesRec valid;
     uint32 mask;
     CtrlHandleTarget *t;
-    char *tmp_d_str, *tmp, *prefix, scratch[4];
+    char *tmp_d_str, *prefix, scratch[4];
+    const char *tmp;
     char *locale = "C";
 
     stream = fopen(filename, "w");
@@ -386,7 +387,8 @@
             continue;
         }
 
-        tmp = nv_get_attribute_name(p->attr);
+        tmp = nv_get_attribute_name(p->attr, NV_PARSER_TYPE_STRING_ATTRIBUTE,
+                                    p->flags);
         if (!tmp) {
             nv_error_msg("Failure to save unknown attribute %d.", p->attr);
             p = p->next;

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkconfig.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkconfig.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkconfig.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkconfig.c Tue Jul 28 07:31:57 2009
@@ -45,7 +45,7 @@
 
 static const char *__status_bar_help =
 "The status bar in the bottom "
-"right of the nvidia-settings GUI displays the most "
+"left of the nvidia-settings GUI displays the most "
 "recent change that has been sent to the X "
 "server.  The 'Display Status Bar' check box "
 "controls whether this status bar is displayed.";

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig-utils.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkdisplayconfig-utils.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig-utils.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig-utils.c Tue Jul 28 07:31:57 2009
@@ -22,9 +22,17 @@
  *
  */
  
-#include <stdlib.h>
-#include <string.h>
+#include <stdlib.h> /* malloc */
+#include <string.h> /* strlen,  strdup */
+#include <unistd.h> /* lseek, close */
 #include <locale.h>
+#include <errno.h>
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
 
 #include <gtk/gtk.h>
 
@@ -32,6 +40,10 @@
 #include "parse.h"
 
 #include "ctkdisplayconfig-utils.h"
+#include "ctkutils.h"
+
+
+static void xconfig_update_buffer(GtkWidget *widget, gpointer user_data);
 
 
 
@@ -2548,3 +2560,742 @@
     return screen;
 
 } /* layout_get_a_screen() */
+
+
+
+
+/*****************************************************************************/
+/** XCONFIG FUNCTIONS ********************************************************/
+/*****************************************************************************/
+
+
+/*
+ * tilde_expansion() - do tilde expansion on the given path name;
+ * based loosely on code snippets found in the comp.unix.programmer
+ * FAQ.  The tilde expansion rule is: if a tilde ('~') is alone or
+ * followed by a '/', then substitute the current user's home
+ * directory; if followed by the name of a user, then substitute that
+ * user's home directory.
+ *
+ * Code adapted from nvidia-xconfig
+ */
+
+char *tilde_expansion(char *str)
+{
+    char *prefix = NULL;
+    char *replace, *user, *ret;
+    struct passwd *pw;
+    int len;
+
+    if ((!str) || (str[0] != '~')) return str;
+    
+    if ((str[1] == '/') || (str[1] == '\0')) {
+
+        /* expand to the current user's home directory */
+
+        prefix = getenv("HOME");
+        if (!prefix) {
+            
+            /* $HOME isn't set; get the home directory from /etc/passwd */
+            
+            pw = getpwuid(getuid());
+            if (pw) prefix = pw->pw_dir;
+        }
+        
+        replace = str + 1;
+        
+    } else {
+    
+        /* expand to the specified user's home directory */
+
+        replace = strchr(str, '/');
+        if (!replace) replace = str + strlen(str);
+
+        len = replace - str;
+        user = malloc(len + 1);
+        strncpy(user, str+1, len-1);
+        user[len] = '\0';
+        pw = getpwnam(user);
+        if (pw) prefix = pw->pw_dir;
+        free (user);
+    }
+
+    if (!prefix) return str;
+    
+    ret = malloc(strlen(prefix) + strlen(replace) + 1);
+    strcpy(ret, prefix);
+    strcat(ret, replace);
+    
+    return ret;
+
+} /* tilde_expansion() */
+
+
+
+/*
+ * update_banner() - add our banner at the top of the config, but
+ * first we need to remove any lines that already include our prefix
+ * (because presumably they are a banner from an earlier run of
+ * nvidia-settings)
+ *
+ * Code adapted from nvidia-xconfig
+ */
+
+extern const char *pNV_ID;
+
+static void update_banner(XConfigPtr config)
+{
+    static const char *banner =
+        "X configuration file generated by nvidia-settings\n";
+    static const char *prefix =
+        "# nvidia-settings: ";
+
+    char *s = config->comment;
+    char *line, *eol, *tmp;
+    
+    /* remove all lines that begin with the prefix */
+    
+    while (s && (line = strstr(s, prefix))) {
+        
+        eol = strchr(line, '\n'); /* find the end of the line */
+        
+        if (eol) {
+            eol++;
+            if (*eol == '\0') eol = NULL;
+        }
+        
+        if (line == s) { /* the line with the prefix is at the start */
+            if (eol) {   /* there is more after the prefix line */
+                tmp = g_strdup(eol);
+                g_free(s);
+                s = tmp;
+            } else {     /* the prefix line is the only line */
+                g_free(s);
+                s = NULL;
+            }
+        } else {         /* prefix line is in the middle or end */
+            *line = '\0';
+            tmp = g_strconcat(s, eol, NULL);
+            g_free(s);
+            s = tmp;
+        }
+    }
+    
+    /* add our prefix lines at the start of the comment */
+    config->comment = g_strconcat(prefix, banner,
+                                  "# ", pNV_ID, "\n",
+                                  (s ? s : ""),
+                                  NULL);
+    if (s) g_free(s);
+    
+} /* update_banner() */
+
+
+
+/** save_xconfig_file() **********************************************
+ *
+ * Saves the X config file text from buf into a file called
+ * filename.  If filename already exists, a backup file named
+ * 'filename.backup' is created.
+ *
+ **/
+
+static int save_xconfig_file(SaveXConfDlg *dlg,
+                             gchar *filename, char *buf, mode_t mode)
+{
+    gchar *backup_filename = NULL;
+    FILE *fp = NULL;
+    size_t size;
+    gchar *err_msg = NULL;
+
+    int ret = 0;
+
+
+    if (!buf || !filename) goto done;
+
+    size = strlen(buf) ;
+
+    /* Backup any existing file */
+    if ((access(filename, F_OK) == 0)) {
+
+        backup_filename = g_strdup_printf("%s.backup", filename);
+        nv_info_msg("", "X configuration file '%s' already exists, "
+                    "backing up file as '%s'", filename,
+                    backup_filename);
+        
+        /* Delete any existing backup file */
+        if (access(backup_filename, F_OK) == 0) {
+
+            if (unlink(backup_filename) != 0) {
+                err_msg =
+                    g_strdup_printf("Unable to remove old X config backup "
+                                    "file '%s'.",
+                                    backup_filename);
+                goto done;
+            }
+        }
+
+        /* Make the current x config file the backup */
+        if (rename(filename, backup_filename)) {
+                err_msg =
+                    g_strdup_printf("Unable to create new X config backup "
+                                    "file '%s'.",
+                                    backup_filename);
+            goto done;            
+        }
+    }
+
+    /* Write out the X config file */
+    fp = fopen(filename, "w");
+    if (!fp) {
+        err_msg =
+            g_strdup_printf("Unable to open X config file '%s' for writing.",
+                            filename);
+        goto done;
+    }
+    fprintf(fp, "%s", buf);
+
+    ret = 1;
+    
+ done:
+    /* Display any errors that might have occured */
+    if (err_msg) {
+        ctk_display_error_msg(ctk_get_parent_window(GTK_WIDGET(dlg->parent)),
+                              err_msg);
+        g_free(err_msg);
+    }
+
+    if (fp) fclose(fp);
+    g_free(backup_filename);
+    return ret;
+    
+} /* save_xconfig_file() */
+
+
+
+/**  update_xconfig_save_buffer() ************************************
+ *
+ * Updates the "preview" buffer to hold the right contents based on
+ * how the user wants the X config file to be generated (and what is
+ * possible.)
+ *
+ * Also updates the state of the "Merge" checkbox in the case where
+ * the named file can/cannot be parsed as a valid X config file.
+ *
+ */
+static void update_xconfig_save_buffer(SaveXConfDlg *dlg)
+{
+    gchar *filename;
+
+    XConfigPtr xconfCur = NULL;
+    XConfigPtr xconfGen = NULL;
+    XConfigError xconfErr;
+
+    char *tmp_filename;
+    int tmp_fd;
+    struct stat st;
+    void *buf;
+    GtkTextIter buf_start, buf_end;
+
+    gboolean merge;
+    gboolean merged;
+    gboolean merge_error;
+
+    gchar *err_msg = NULL;
+
+
+
+    /* Get how the user wants to generate the X config file */
+    merge = gtk_toggle_button_get_active
+        (GTK_TOGGLE_BUTTON(dlg->btn_xconfig_merge));
+
+    filename = (gchar *)gtk_entry_get_text(GTK_ENTRY(dlg->txt_xconfig_file));
+
+    /* Find out if the file is mergable */
+    if (filename && (filename[0] != '\0')) {
+        /* Must be able to open the file */
+        tmp_filename = (char *)xconfigOpenConfigFile(filename, NULL);
+        if (!tmp_filename || strcmp(tmp_filename, filename)) {
+            err_msg = g_strdup_printf("Failed to open existing X config "
+                                      "file '%s'!",
+                                      filename);
+            ctk_display_warning_msg
+                (ctk_get_parent_window(GTK_WIDGET(dlg->parent)), err_msg);
+
+            xconfigCloseConfigFile();
+
+        } else {
+            GenerateOptions gop;
+
+            /* Must be able to parse the file as an X config file */
+            xconfErr = xconfigReadConfigFile(&xconfCur);
+            xconfigCloseConfigFile();
+            if ((xconfErr != XCONFIG_RETURN_SUCCESS) || !xconfCur) {
+                /* If we failed to parse the config file, we should not
+                 * allow a merge.
+                 */
+                err_msg = g_strdup_printf("Failed to parse existing X "
+                                          "config file '%s'!",
+                                          filename);
+                ctk_display_warning_msg
+                    (ctk_get_parent_window(GTK_WIDGET(dlg->parent)), err_msg);
+
+                xconfCur = NULL;
+            }
+
+            /* Sanitize the X config file */
+            xconfigGenerateLoadDefaultOptions(&gop);
+            xconfigGetXServerInUse(&gop);
+
+            if (!xconfigSanitizeConfig(xconfCur, NULL, &gop)) {
+                err_msg = g_strdup_printf("Failed to sanitize existing X "
+                                          "config file '%s'!",
+                                          filename);
+                ctk_display_warning_msg
+                    (ctk_get_parent_window(GTK_WIDGET(dlg->parent)), err_msg);
+
+                xconfigFreeConfig(&xconfCur);
+                xconfCur = NULL;
+            }
+        }
+
+        /* If we're not actualy doing a merge, close the file */
+        if (!merge && xconfCur) {
+            xconfigFreeConfig(&xconfCur);
+        }
+    }
+
+    merge_error = merge && !xconfCur;
+    merge = (merge && !merge_error);
+
+
+    /* If we have to merge but we can't, report the problem. */
+    if (merge_error && !dlg->merge_toggleable) {
+        // XXX Instead of bailing here, we may want to just disable
+        //     the "Save" button until the user specifies a file
+        //     that we can parse.
+        goto fail;
+    }
+
+    /* Generate the X config file */
+    xconfGen = dlg->xconf_gen_func(xconfCur, merge, &merged,
+                                   dlg->callback_data);
+    if (!xconfGen) {
+        err_msg = g_strdup_printf("Failed to generate X config file!");
+        goto fail;
+    }
+
+    merge_error = merge && !merged;
+
+    /* Update merge status */
+    g_signal_handlers_block_by_func
+        (G_OBJECT(dlg->btn_xconfig_merge),
+         G_CALLBACK(xconfig_update_buffer), (gpointer) dlg);
+    
+    gtk_toggle_button_set_active
+        (GTK_TOGGLE_BUTTON(dlg->btn_xconfig_merge), merged);
+    
+    g_signal_handlers_unblock_by_func
+        (G_OBJECT(dlg->btn_xconfig_merge),
+         G_CALLBACK(xconfig_update_buffer), (gpointer) dlg);
+    
+    gtk_widget_set_sensitive(dlg->btn_xconfig_merge,
+                             (dlg->merge_toggleable && !merge_error) ?
+                             TRUE : FALSE);
+    
+
+    /* We're done with the user's X config, so do some cleanup,
+     * but make sure to handle the case where the generation
+     * function modifies the user's X config structure instead
+     * of generating a new one.
+     */
+    if (xconfGen == xconfCur) {
+        xconfCur = NULL;
+    } else {
+        xconfigFreeConfig(&xconfCur);
+    }
+
+
+    /* Update the X config banner */
+    update_banner(xconfGen);
+
+
+    /* Setup the X config file preview buffer by writing to a temp file */
+    tmp_filename = g_strdup_printf("/tmp/.xconfig.tmp.XXXXXX");
+    tmp_fd = mkstemp(tmp_filename);
+    if (!tmp_fd) {
+        err_msg = g_strdup_printf("Failed to create temp X config file '%s' "
+                                  "for display.",
+                                  tmp_filename);
+        g_free(tmp_filename);
+        goto fail;
+    }
+    xconfigWriteConfigFile(tmp_filename, xconfGen);
+    xconfigFreeConfig(&xconfGen);
+
+    lseek(tmp_fd, 0, SEEK_SET);
+    fstat(tmp_fd, &st);
+    buf = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, tmp_fd, 0);
+
+    /* Clear the GTK buffer */
+    gtk_text_buffer_get_bounds
+        (GTK_TEXT_BUFFER(dlg->buf_xconfig_save), &buf_start,
+         &buf_end);
+    gtk_text_buffer_delete
+        (GTK_TEXT_BUFFER(dlg->buf_xconfig_save), &buf_start,
+         &buf_end);
+
+    /* Set the new GTK buffer contents */
+    gtk_text_buffer_set_text(GTK_TEXT_BUFFER(dlg->buf_xconfig_save),
+                             buf, st.st_size);
+    munmap(buf, st.st_size);
+    close(tmp_fd);
+    remove(tmp_filename);
+    g_free(tmp_filename);
+
+    return;
+
+
+ fail:
+    /* Clear the GTK buffer */
+    gtk_text_buffer_get_bounds
+        (GTK_TEXT_BUFFER(dlg->buf_xconfig_save), &buf_start,
+         &buf_end);
+    gtk_text_buffer_delete
+        (GTK_TEXT_BUFFER(dlg->buf_xconfig_save), &buf_start,
+         &buf_end);
+
+    if (err_msg) {
+        ctk_display_warning_msg(ctk_get_parent_window(GTK_WIDGET(dlg->parent)),
+                                err_msg);
+        g_free(err_msg);
+    }
+
+    if (xconfGen) {
+        xconfigFreeConfig(&xconfGen);
+    }
+
+    if (xconfCur) {
+        xconfigFreeConfig(&xconfCur);
+    }
+
+    return;
+
+} /* update_xconfig_save_buffer() */
+
+
+
+/** xconfig_preview_clicked() ****************************************
+ *
+ * Called when the user clicks on the "Preview" button of the
+ * X config save dialog.
+ *
+ **/
+
+static void xconfig_preview_clicked(GtkWidget *widget, gpointer user_data)
+{
+    SaveXConfDlg *dlg = (SaveXConfDlg *)user_data;
+    gboolean show = !GTK_WIDGET_VISIBLE(dlg->box_xconfig_save);
+
+    if (show) {
+        gtk_widget_show_all(dlg->box_xconfig_save);
+        gtk_window_set_resizable(GTK_WINDOW(dlg->dlg_xconfig_save),
+                                 TRUE);
+        gtk_widget_set_size_request(dlg->txt_xconfig_save, 450, 350);
+        gtk_button_set_label(GTK_BUTTON(dlg->btn_xconfig_preview),
+                             "Hide Preview...");
+    } else {
+        gtk_widget_hide(dlg->box_xconfig_save);
+        gtk_window_set_resizable(GTK_WINDOW(dlg->dlg_xconfig_save), FALSE);
+        gtk_button_set_label(GTK_BUTTON(dlg->btn_xconfig_preview),
+                             "Show Preview...");
+    }
+
+} /* xconfig_preview_clicked() */
+
+
+
+/** xconfig_update_buffer() ******************************************
+ *
+ * Called when the user selects a new X config filename.
+ *
+ **/
+
+static void xconfig_update_buffer(GtkWidget *widget, gpointer user_data)
+{
+    SaveXConfDlg *dlg = (SaveXConfDlg *)user_data;
+
+    update_xconfig_save_buffer(dlg);
+
+} /* xconfig_update_buffer() */
+
+
+
+/** xconfig_file_clicked() *******************************************
+ *
+ * Called when the user clicks on the "Browse..." button of the
+ * X config save dialog.
+ *
+ **/
+
+static void xconfig_file_clicked(GtkWidget *widget, gpointer user_data)
+{
+    SaveXConfDlg *dlg = (SaveXConfDlg *)user_data;
+    const gchar *filename =
+        gtk_entry_get_text(GTK_ENTRY(dlg->txt_xconfig_file));
+    gint result;
+
+
+    /* Ask user for a filename */
+    gtk_window_set_transient_for
+        (GTK_WINDOW(dlg->dlg_xconfig_file),
+         GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(dlg->parent))));
+
+    gtk_file_selection_set_filename
+        (GTK_FILE_SELECTION(dlg->dlg_xconfig_file), filename);
+    
+    result = gtk_dialog_run(GTK_DIALOG(dlg->dlg_xconfig_file));
+    gtk_widget_hide(dlg->dlg_xconfig_file);
+    
+    switch (result) {
+    case GTK_RESPONSE_ACCEPT:
+    case GTK_RESPONSE_OK:
+        filename = gtk_file_selection_get_filename
+            (GTK_FILE_SELECTION(dlg->dlg_xconfig_file));
+
+        gtk_entry_set_text(GTK_ENTRY(dlg->txt_xconfig_file), filename);
+
+        update_xconfig_save_buffer(dlg);
+        break;
+    default:
+        return;
+    }
+
+} /* xconfig_file_clicked() */
+
+
+
+/** run_save_xconfig_dialog() ****************************************
+ *
+ * run_save_xconfig_dialog() - Takes care of running the "Save X
+ * Configuration File" dialog.  Generates the X config file by
+ * calling the registered callback and takes care of keeping
+ * track of the requested filename etc.
+ *
+ **/
+
+void run_save_xconfig_dialog(SaveXConfDlg *dlg)
+{
+    void *buf;
+    GtkTextIter buf_start, buf_end;
+    gchar *filename;
+    gchar *tmp_filename;
+
+    gint result;
+
+
+    /* Generate the X config file save buffer */
+    update_xconfig_save_buffer(dlg);
+
+
+    /* Show the save dialog */
+    gtk_window_set_transient_for
+        (GTK_WINDOW(dlg->dlg_xconfig_save),
+         GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(dlg->parent))));
+
+    gtk_widget_hide(dlg->box_xconfig_save);
+    gtk_window_resize(GTK_WINDOW(dlg->dlg_xconfig_save), 350, 1);
+    gtk_window_set_resizable(GTK_WINDOW(dlg->dlg_xconfig_save),
+                             FALSE);
+    gtk_button_set_label(GTK_BUTTON(dlg->btn_xconfig_preview),
+                         "Show preview...");
+    gtk_widget_show(dlg->dlg_xconfig_save);
+    result = gtk_dialog_run(GTK_DIALOG(dlg->dlg_xconfig_save));
+    gtk_widget_hide(dlg->dlg_xconfig_save);
+    
+    
+    /* Handle user's response */
+    switch (result)
+    {
+    case GTK_RESPONSE_ACCEPT:
+
+        /* Get the filename to write to */
+        tmp_filename =
+            (gchar *) gtk_entry_get_text(GTK_ENTRY(dlg->txt_xconfig_file));
+        filename = tilde_expansion(tmp_filename);
+        if (filename == tmp_filename) {
+            filename = g_strdup(tmp_filename);
+        }
+
+        /* Get the buffer to write */
+        gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(dlg->buf_xconfig_save),
+                                   &buf_start, &buf_end);
+        buf = (void *) gtk_text_buffer_get_text
+            (GTK_TEXT_BUFFER(dlg->buf_xconfig_save), &buf_start,
+             &buf_end, FALSE);
+        if (!buf) {
+            nv_error_msg("Failed to read X configuration buffer!");
+            break;
+        }
+
+        /* Save the X config file */
+        nv_info_msg("", "Writing X config file '%s'", filename);
+        save_xconfig_file(dlg, filename, (char *)buf, 0644);
+        g_free(buf);
+        g_free(filename);
+        break;
+        
+    case GTK_RESPONSE_REJECT:
+    default:
+        /* do nothing. */
+        break;
+    }
+
+} /* run_save_xconfig_dialog() */
+
+
+
+/** create_save_xconfig_dialog() *************************************
+ *
+ * Creates the "Save X Configuration" button widget
+ *
+ **/
+
+SaveXConfDlg *create_save_xconfig_dialog(GtkWidget *parent,
+                                         Bool merge_toggleable,
+                                         generate_xconfig_callback xconf_gen_func,
+                                         void *callback_data)
+{
+    SaveXConfDlg *dlg;
+    GtkWidget *hbox;
+    GtkWidget *hbox2;
+    gchar *filename;
+
+
+    dlg = (SaveXConfDlg *) malloc (sizeof(SaveXConfDlg));
+    if (!dlg) return NULL;
+
+    dlg->parent = parent;
+    dlg->xconf_gen_func = xconf_gen_func;
+    dlg->merge_toggleable = merge_toggleable;
+    dlg->callback_data = callback_data;
+
+    /* Setup the default filename */
+    filename = (gchar *) xconfigOpenConfigFile(NULL, NULL);
+    if (filename) {
+        filename = g_strdup(filename);
+    } else {
+        filename = g_strdup("");
+    }
+    xconfigCloseConfigFile();
+
+    if (!filename) {
+        free(dlg);
+        return NULL;
+    }
+
+    /* Create the dialog */
+    dlg->dlg_xconfig_save = gtk_dialog_new_with_buttons
+        ("Save X Configuration",
+         GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(parent))),
+         GTK_DIALOG_MODAL |  GTK_DIALOG_DESTROY_WITH_PARENT |
+         GTK_DIALOG_NO_SEPARATOR,
+         GTK_STOCK_SAVE,
+         GTK_RESPONSE_ACCEPT,
+         GTK_STOCK_CANCEL,
+         GTK_RESPONSE_REJECT,
+         NULL);
+
+    gtk_dialog_set_default_response(GTK_DIALOG(dlg->dlg_xconfig_save),
+                                    GTK_RESPONSE_REJECT);
+
+    gtk_dialog_set_has_separator(GTK_DIALOG(dlg->dlg_xconfig_save), TRUE);
+
+    /* Create the preview button */
+    dlg->btn_xconfig_preview = gtk_button_new();
+    g_signal_connect(G_OBJECT(dlg->btn_xconfig_preview), "clicked",
+                     G_CALLBACK(xconfig_preview_clicked),
+                     (gpointer) dlg);
+
+    /* Create the preview text window & buffer */
+    dlg->txt_xconfig_save = gtk_text_view_new();
+    gtk_text_view_set_left_margin
+        (GTK_TEXT_VIEW(dlg->txt_xconfig_save), 5);
+
+    dlg->buf_xconfig_save = gtk_text_buffer_new(NULL);
+    gtk_text_view_set_buffer(GTK_TEXT_VIEW(dlg->txt_xconfig_save),
+                             GTK_TEXT_BUFFER(dlg->buf_xconfig_save));
+
+    dlg->scr_xconfig_save = gtk_scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_shadow_type
+        (GTK_SCROLLED_WINDOW(dlg->scr_xconfig_save), GTK_SHADOW_IN);
+
+    /* Create the filename text entry */
+    dlg->txt_xconfig_file = gtk_entry_new();
+    gtk_widget_set_size_request(dlg->txt_xconfig_file, 300, -1);
+    gtk_entry_set_text(GTK_ENTRY(dlg->txt_xconfig_file), filename);
+    g_signal_connect(G_OBJECT(dlg->txt_xconfig_file), "activate",
+                     G_CALLBACK(xconfig_update_buffer),
+                     (gpointer) dlg);
+
+    /* Create the filename browse button */
+    dlg->btn_xconfig_file = gtk_button_new_with_label("Browse...");
+    g_signal_connect(G_OBJECT(dlg->btn_xconfig_file), "clicked",
+                     G_CALLBACK(xconfig_file_clicked),
+                     (gpointer) dlg);
+    dlg->dlg_xconfig_file =
+        gtk_file_selection_new("Please select the X configuration file");
+
+    /* Create the merge checkbox */
+    dlg->btn_xconfig_merge =
+        gtk_check_button_new_with_label("Merge with existing file.");
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dlg->btn_xconfig_merge),
+                                 TRUE);
+    gtk_widget_set_sensitive(dlg->btn_xconfig_merge, merge_toggleable);
+    g_signal_connect(G_OBJECT(dlg->btn_xconfig_merge), "toggled",
+                     G_CALLBACK(xconfig_update_buffer),
+                     (gpointer) dlg);
+
+
+    /* Pack the preview button */
+    hbox = gtk_hbox_new(FALSE, 0);
+    hbox2 = gtk_hbox_new(FALSE, 0);
+
+    gtk_box_pack_start(GTK_BOX(hbox), dlg->btn_xconfig_preview,
+                       FALSE, FALSE, 5);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg->dlg_xconfig_save)->vbox),
+                       hbox, FALSE, FALSE, 5);
+
+    /* Pack the preview window */
+    hbox = gtk_hbox_new(TRUE, 0);
+
+    gtk_container_add(GTK_CONTAINER(dlg->scr_xconfig_save),
+                      dlg->txt_xconfig_save);
+    gtk_box_pack_start(GTK_BOX(hbox), dlg->scr_xconfig_save, TRUE, TRUE, 5);
+    gtk_box_pack_start
+        (GTK_BOX(GTK_DIALOG(dlg->dlg_xconfig_save)->vbox),
+         hbox,
+         TRUE, TRUE, 0);
+    dlg->box_xconfig_save = hbox;
+    
+    /* Pack the filename text entry and browse button */
+    hbox = gtk_hbox_new(FALSE, 0);
+    hbox2 = gtk_hbox_new(FALSE, 5);
+    
+    gtk_box_pack_end(GTK_BOX(hbox2), dlg->btn_xconfig_file, FALSE, FALSE, 0);
+    gtk_box_pack_end(GTK_BOX(hbox2), dlg->txt_xconfig_file, TRUE, TRUE, 0);
+    gtk_box_pack_end(GTK_BOX(hbox), hbox2, TRUE, TRUE, 5);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg->dlg_xconfig_save)->vbox),
+                       hbox,
+                       FALSE, FALSE, 5);
+    
+    /* Pack the merge checkbox */
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg->dlg_xconfig_save)->vbox),
+                       dlg->btn_xconfig_merge,
+                       FALSE, FALSE, 5);
+    
+    gtk_widget_show_all(GTK_DIALOG(dlg->dlg_xconfig_save)->vbox);
+    
+    return dlg;
+
+} /* create_save_xconfig_button() */

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig-utils.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkdisplayconfig-utils.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig-utils.h (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig-utils.h Tue Jul 28 07:31:57 2009
@@ -26,6 +26,8 @@
 #define __CTK_DISPLAYCONFIG_UTILS_H__
 
 #include <gtk/gtk.h>
+
+#include "XF86Config-parser/xf86Parser.h"
 
 #include "ctkdisplaylayout.h"
 
@@ -101,6 +103,48 @@
 
 
 
+
+/* Save X config dialog  */
+
+typedef XConfigPtr (* generate_xconfig_callback) (XConfigPtr xconfCur,
+                                                  Bool merge,
+                                                  Bool *merged,
+                                                  gpointer callback_data);
+
+typedef struct _SaveXConfDlg {
+
+    GtkWidget *parent;
+    GtkWidget *top_window;
+
+    /* Callback functions for generating the XConfig struct */
+    generate_xconfig_callback xconf_gen_func;
+    void *callback_data;
+
+    Bool merge_toggleable; /* When possible, user able to toggle merge */
+
+    GtkWidget *dlg_xconfig_save;     /* Save X config dialog */
+    GtkWidget *scr_xconfig_save;     /* Scroll window */
+    GtkWidget *txt_xconfig_save;     /* Text view of file contents */
+    GtkTextBuffer *buf_xconfig_save; /* Text buffer (Actual) file contents */
+    GtkWidget *btn_xconfig_merge;    /* Merge with existing X config */
+    GtkWidget *btn_xconfig_preview;  /* Show/Hide button */
+    GtkWidget *box_xconfig_save;     /* Show/Hide this box */
+ 
+    GtkWidget *dlg_xconfig_file; /* File save dialog */
+    GtkWidget *btn_xconfig_file;
+    GtkWidget *txt_xconfig_file;
+
+} SaveXConfDlg;
+
+
+
+SaveXConfDlg *create_save_xconfig_dialog(GtkWidget *parent,
+                                         Bool merge_toggleable,
+                                         generate_xconfig_callback xconf_gen_func,
+                                         gpointer callback_data);
+
+void run_save_xconfig_dialog(SaveXConfDlg *dlg);
+
                    
 G_END_DECLS
 

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkdisplayconfig.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig.c Tue Jul 28 07:31:57 2009
@@ -22,16 +22,9 @@
  *
  */
 
-#include <stdlib.h> /* malloc */
-#include <unistd.h> /* lseek, close */
-#include <string.h> /* strlen,  strdup */
-#include <errno.h>
-
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/stat.h>
-#include <pwd.h>
 
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
@@ -87,12 +80,6 @@
 static void screen_metamode_activate(GtkWidget *widget, gpointer user_data);
 static void screen_metamode_add_clicked(GtkWidget *widget, gpointer user_data);
 static void screen_metamode_delete_clicked(GtkWidget *widget, gpointer user_data);
-
-static void xconfig_preview_clicked(GtkWidget *widget, gpointer user_data);
-static void xconfig_file_clicked(GtkWidget *widget, gpointer user_data);
-static void xconfig_merge_toggled(GtkWidget *widget, gpointer user_data);
-static void xconfig_file_activate(GtkWidget *widget, gpointer user_data);
-static gboolean update_xconfig_save_buffer(CtkDisplayConfig *ctk_object);
 
 static void xinerama_state_toggled(GtkWidget *widget, gpointer user_data);
 static void apply_clicked(GtkWidget *widget, gpointer user_data);
@@ -102,13 +89,17 @@
 static void reset_clicked(GtkWidget *widget, gpointer user_data);
 static void validation_details_clicked(GtkWidget *widget, gpointer user_data);
 
-static int generateXConfig(CtkDisplayConfig *ctk_object, XConfigPtr *pConfig);
-static void update_banner(XConfigPtr config);
 static void display_config_attribute_changed(GtkObject *object, gpointer arg1,
                                            gpointer user_data);
 static void reset_layout(CtkDisplayConfig *ctk_object);
 static gboolean force_layout_reset(gpointer user_data);
 static void user_changed_attributes(CtkDisplayConfig *ctk_object);
+
+static XConfigPtr xconfig_generate(XConfigPtr xconfCur,
+                                   Bool merge,
+                                   Bool *merged,
+                                   void *callback_data);
+
 
 
 
@@ -162,7 +153,8 @@
 
 static const char * __layout_xinerama_button_help =
 "The Enable Xinerama checkbox enables the Xinerama X extension; changing "
-"this option will require restarting your X server.";
+"this option will require restarting your X server.  Note that when Xinerama "
+"is enabled, resolution changes will also require restarting your X server.";
 
 
 /* Display tooltips */
@@ -181,16 +173,19 @@
 
 static const char * __dpy_position_type_help =
 "The Position Type drop-down allows you to set how the selected display "
-"device is placed within the X screen.";
+"device is placed within the X screen. This is only available when "
+"multiple display devices are present.";
 
 static const char * __dpy_position_relative_help =
 "The Position Relative drop-down allows you to set which other display "
 "device (within the X screen) the selected display device should be "
-"relative to.";
+"relative to. This is only available when multiple display "
+"devices are present.";
 
 static const char * __dpy_position_offset_help =
 "The Position Offset identifies the top left of the display device "
-"as an offset from the top left of the X screen position.";
+"as an offset from the top left of the X screen position. This is only "
+"available when multiple display devices are present.";
 
 static const char * __dpy_panning_help =
 "The Panning Domain sets the total width/height that the display "
@@ -209,17 +204,20 @@
 "screen; changing this option will require restarting your X server.";
 
 static const char * __screen_position_type_help =
-"The Position Type drop-down allows you to set how the selected screen "
+"The Position Type drop-down appears when two or more display devices are active. "
+"This allows you to set how the selected screen "
 "is placed within the X server layout; changing this option will require "
 "restarting your X server.";
 
 static const char * __screen_position_relative_help =
-"The Position Relative drop-down allows you to set which other Screen "
+"The Position Relative drop-down appears when two or more display devices are active. "
+"This allows you to set which other Screen "
 "the selected screen should be relative to; changing this option will "
 "require restarting your X server.";
 
 static const char * __screen_position_offset_help =
-"The Position Offset identifies the top left of the selected Screen as "
+"The Position Offset drop-down appears when two or more display devices are active. "
+"This identifies the top left of the selected Screen as "
 "an offset from the top left of the X server layout in absolute coordinates; "
 "changing this option will require restarting your X server.";
 
@@ -549,6 +547,7 @@
                                        nvScreenPtr screen,
                                        gchar **pMetamode_strs)
 {
+    nvLayoutPtr layout = screen->gpu->layout;
     gchar *metamode_strs = NULL;
     gchar *metamode_str;
     gchar *tmp;
@@ -558,8 +557,8 @@
     int start_width;
     int start_height;
 
-    int vendrel = NvCtrlGetVendorRelease(ctk_object->handle);
-    char *vendstr = NvCtrlGetServerVendor(ctk_object->handle);
+    int vendrel = NvCtrlGetVendorRelease(layout->handle);
+    char *vendstr = NvCtrlGetServerVendor(layout->handle);
     int xorg_major;
     int xorg_minor;
     Bool longStringsOK;
@@ -581,7 +580,7 @@
      * metamode first in the list so the X server starts
      * in this mode.
      */
-    if (!ctk_object->advanced_mode) {
+    if (!layout->advanced_mode) {
         metamode_strs = screen_get_metamode_str(screen,
                                                 screen->cur_metamode_idx, 1);
         len = strlen(metamode_strs);
@@ -602,7 +601,7 @@
         if (!(metamode->source & METAMODE_SOURCE_USER)) continue;
 
         /* The current mode was already included */
-        if (!ctk_object->advanced_mode &&
+        if (!layout->advanced_mode &&
             (metamode_idx == screen->cur_metamode_idx))
             continue;
 
@@ -612,7 +611,7 @@
          *     smaller that the bounding box of all the metamodes will result
          *     in an unwanted panning domain being setup for the first mode.
          */
-        if ((!ctk_object->advanced_mode) &&
+        if ((!layout->advanced_mode) &&
             ((metamode->edim[W] > start_width) ||
              (metamode->edim[H] > start_height)))
             continue;
@@ -1063,7 +1062,6 @@
     GtkWidget *frame;
     GtkWidget *notebook;
     GtkWidget *hbox;
-    GtkWidget *hbox2;
     GtkWidget *vbox;
     GdkScreen *screen;
     GtkWidget *label;
@@ -1113,8 +1111,6 @@
     ctk_object->forced_reset_allowed = TRUE;
     ctk_object->notify_user_of_reset = TRUE;
     ctk_object->ignore_reset_events = FALSE;
-
-    ctk_object->advanced_mode = FALSE;
 
     ctk_object->last_resolution_idx = -1;
 
@@ -1477,56 +1473,11 @@
 
 
     /* X config save dialog */
-    ctk_object->dlg_xconfig_save = gtk_dialog_new_with_buttons
-        ("Save X Configuration",
-         GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
-         GTK_DIALOG_MODAL |  GTK_DIALOG_DESTROY_WITH_PARENT |
-         GTK_DIALOG_NO_SEPARATOR,
-         GTK_STOCK_SAVE,
-         GTK_RESPONSE_ACCEPT,
-         GTK_STOCK_CANCEL,
-         GTK_RESPONSE_REJECT,
-         NULL);
-    gtk_dialog_set_default_response(GTK_DIALOG(ctk_object->dlg_xconfig_save),
-                                    GTK_RESPONSE_REJECT);
-
-    ctk_object->btn_xconfig_preview = gtk_button_new();
-    g_signal_connect(G_OBJECT(ctk_object->btn_xconfig_preview), "clicked",
-                     G_CALLBACK(xconfig_preview_clicked),
-                     (gpointer) ctk_object);
-
-    ctk_object->txt_xconfig_save = gtk_text_view_new();
-    gtk_text_view_set_left_margin
-        (GTK_TEXT_VIEW(ctk_object->txt_xconfig_save), 5);
-
-    ctk_object->buf_xconfig_save = gtk_text_buffer_new(NULL);
-    gtk_text_view_set_buffer(GTK_TEXT_VIEW(ctk_object->txt_xconfig_save),
-                             GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save));
-
-    ctk_object->scr_xconfig_save = gtk_scrolled_window_new(NULL, NULL);
-    gtk_scrolled_window_set_shadow_type
-        (GTK_SCROLLED_WINDOW(ctk_object->scr_xconfig_save), GTK_SHADOW_IN);
-
-    ctk_object->txt_xconfig_file = gtk_entry_new();
-    gtk_widget_set_size_request(ctk_object->txt_xconfig_file, 300, -1);
-    g_signal_connect(G_OBJECT(ctk_object->txt_xconfig_file), "activate",
-                     G_CALLBACK(xconfig_file_activate),
-                     (gpointer) ctk_object);
-
-    ctk_object->btn_xconfig_file = gtk_button_new_with_label("Browse...");
-    g_signal_connect(G_OBJECT(ctk_object->btn_xconfig_file), "clicked",
-                     G_CALLBACK(xconfig_file_clicked),
-                     (gpointer) ctk_object);
-    ctk_object->dlg_xconfig_file = gtk_file_selection_new
-        ("Please select the X configuration file");
-    
-    ctk_object->btn_xconfig_merge =
-        gtk_check_button_new_with_label("Merge with existing file.");
-    gtk_toggle_button_set_active
-        (GTK_TOGGLE_BUTTON(ctk_object->btn_xconfig_merge), TRUE);
-    g_signal_connect(G_OBJECT(ctk_object->btn_xconfig_merge), "toggled",
-                     G_CALLBACK(xconfig_merge_toggled),
-                     (gpointer) ctk_object);
+    ctk_object->save_xconfig_dlg =
+        create_save_xconfig_dialog(GTK_WIDGET(ctk_object),
+                                   TRUE, // Merge toggleable
+                                   xconfig_generate,
+                                   (void *)ctk_object);
 
 
     /* Apply button */
@@ -1863,57 +1814,6 @@
             (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_confirm)->vbox),
              hbox, TRUE, TRUE, 20);
         gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_display_confirm)->vbox);
-
-        /* X Config Save Dialog */
-        gtk_dialog_set_has_separator(GTK_DIALOG(ctk_object->dlg_xconfig_save),
-                                     TRUE);
-
-        /* Preview button */
-        hbox = gtk_hbox_new(FALSE, 0);
-        hbox2 = gtk_hbox_new(FALSE, 0);
-
-        gtk_box_pack_start(GTK_BOX(hbox), ctk_object->btn_xconfig_preview,
-                           FALSE, FALSE, 5);
-        gtk_box_pack_start
-            (GTK_BOX(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox),
-             hbox, FALSE, FALSE, 5);
-
-        /* Preview window */
-        hbox = gtk_hbox_new(TRUE, 0);
-
-        gtk_container_add(GTK_CONTAINER(ctk_object->scr_xconfig_save),
-                          ctk_object->txt_xconfig_save);
-        gtk_box_pack_start(GTK_BOX(hbox),
-                           ctk_object->scr_xconfig_save,
-                           TRUE, TRUE, 5);
-        gtk_box_pack_start
-            (GTK_BOX(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox),
-             hbox,
-             TRUE, TRUE, 0);
-        ctk_object->box_xconfig_save = hbox;
-
-        /* Filename */
-        hbox = gtk_hbox_new(FALSE, 0);
-        hbox2 = gtk_hbox_new(FALSE, 5);
-
-        gtk_box_pack_end(GTK_BOX(hbox2), ctk_object->btn_xconfig_file,
-                           FALSE, FALSE, 0);
-        gtk_box_pack_end(GTK_BOX(hbox2), ctk_object->txt_xconfig_file,
-                           TRUE, TRUE, 0);
-        gtk_box_pack_end(GTK_BOX(hbox), hbox2,
-                           TRUE, TRUE, 5);
-        gtk_box_pack_start
-            (GTK_BOX(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox),
-             hbox,
-             FALSE, FALSE, 5);
-
-        /* Merge checkbox */
-        gtk_box_pack_start
-            (GTK_BOX(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox),
-             ctk_object->btn_xconfig_merge,
-             FALSE, FALSE, 5);
-
-        gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox);
     }
 
 
@@ -1987,7 +1887,7 @@
     ctk_help_heading(b, &i, "Mode Name");
     ctk_help_para(b, &i, "The Mode name is the name of the modeline that is "
                   "currently chosen for the selected display device.  "
-                  "(Advanced view only)");
+                  "(Advanced view only.)");
     ctk_help_heading(b, &i, "Position Type");
     ctk_help_para(b, &i, __dpy_position_type_help);
     ctk_help_heading(b, &i, "Position Relative");
@@ -1995,16 +1895,16 @@
     ctk_help_heading(b, &i, "Position Offset");
     ctk_help_para(b, &i, __dpy_position_offset_help);
     ctk_help_heading(b, &i, "Panning");
-    ctk_help_para(b, &i, "%s.  (Advanced view only)", __dpy_panning_help);
+    ctk_help_para(b, &i, "%s  (Advanced view only.)", __dpy_panning_help);
     ctk_help_heading(b, &i, "Primary Display");
     ctk_help_para(b, &i, __dpy_primary_help);
 
 
     ctk_help_para(b, &i, "");
-    ctk_help_heading(b, &i, "Screen Section");
+    ctk_help_heading(b, &i, "X Screen Section");
     ctk_help_para(b, &i, "This section shows information and configuration "
                   "settings for the currently selected X screen.");
-    ctk_help_heading(b, &i, "Screen Depth");
+    ctk_help_heading(b, &i, "Color Depth");
     ctk_help_para(b, &i, __screen_depth_help);
     ctk_help_heading(b, &i, "Position Type");
     ctk_help_para(b, &i, __screen_position_type_help);
@@ -2013,12 +1913,12 @@
     ctk_help_heading(b, &i, "Position Offset");
     ctk_help_para(b, &i, __screen_position_offset_help);
     ctk_help_heading(b, &i, "MetaMode Selection");
-    ctk_help_para(b, &i, "%s.  (Advanced view only)", __screen_metamode_help);
+    ctk_help_para(b, &i, "%s  (Advanced view only.)", __screen_metamode_help);
     ctk_help_heading(b, &i, "Add Metamode");
-    ctk_help_para(b, &i, "%s.  (Advanced view only)",
+    ctk_help_para(b, &i, "%s  (Advanced view only.)",
                   __screen_metamode_add_button_help);
     ctk_help_heading(b, &i, "Delete Metamode");
-    ctk_help_para(b, &i, "%s.  (Advanced view only)",
+    ctk_help_para(b, &i, "%s  (Advanced view only.)",
                   __screen_metamode_delete_button_help);
     
     
@@ -2034,10 +1934,10 @@
     ctk_help_heading(b, &i, "Detect Displays");
     ctk_help_para(b, &i, __detect_displays_button_help);
     ctk_help_heading(b, &i, "Advanced/Basic...");
-    ctk_help_para(b, &i, "%s.  The Basic view modifies the currently active "
+    ctk_help_para(b, &i, "%s  The Basic view modifies the currently active "
                   "MetaMode for an X screen, while the Advanced view exposes "
                   "all the MetaModes available on an X screen, and lets you "
-                  "modify each of them", __advanced_button_help);
+                  "modify each of them.", __advanced_button_help);
     ctk_help_heading(b, &i, "Reset");
     ctk_help_para(b, &i, __reset_button_help);
     ctk_help_heading(b, &i, "Save to X Configuration File");
@@ -2115,9 +2015,10 @@
 {
     nvDisplayPtr display = ctk_display_layout_get_selected_display
         (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
-
-
-    if (!display || !display->screen || !ctk_object->advanced_mode) {
+    nvLayoutPtr layout = ctk_object->layout;
+
+
+    if (!display || !display->screen || !layout->advanced_mode) {
         gtk_widget_hide(ctk_object->box_display_modename);
         return;
     }
@@ -2190,6 +2091,7 @@
 
     nvDisplayPtr display = ctk_display_layout_get_selected_display
         (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+    nvLayoutPtr layout = ctk_object->layout;
 
 
 
@@ -2290,14 +2192,14 @@
             name = g_strdup("Auto");
 
         /* In advanced mode, all modelines are selectable */
-        } else if (count_ref > 1 && ctk_object->advanced_mode) {
+        } else if (count_ref > 1 && layout->advanced_mode) {
             gchar *tmp;
             tmp = g_strdup_printf("%s (%d)", name, num_ref);
             g_free(name);
             name = tmp;
 
         /* in simple mode only show one refresh rate */
-        } else if (num_ref > 1 && !ctk_object->advanced_mode) {
+        } else if (num_ref > 1 && !layout->advanced_mode) {
             continue;
         }
 
@@ -2537,6 +2439,7 @@
 
     gtk_option_menu_set_history
         (GTK_OPTION_MENU(ctk_object->mnu_display_resolution), cur_idx);
+    ctk_object->last_resolution_idx = cur_idx;
 
     /* If dropdown has only one item, disable menu selection */
     if (ctk_object->resolution_table_len > 1) {
@@ -2953,14 +2856,17 @@
 static void setup_display_panning(CtkDisplayConfig *ctk_object)
 {
     char *tmp_str;
+    nvLayoutPtr layout;
     nvDisplayPtr display;
     nvModePtr mode;
 
+    layout = ctk_object->layout;
+
     display = ctk_display_layout_get_selected_display
         (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
 
 
-    if (!display || !display->screen || !ctk_object->advanced_mode) {
+    if (!display || !display->screen || !layout->advanced_mode) {
         gtk_widget_hide(ctk_object->box_display_panning);
         return;
     }
@@ -3113,6 +3019,12 @@
     gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
     gtk_widget_show(menu_item);
     ctk_object->screen_depth_table[screen_depth_table_len++] = 16;
+
+    menu_item = gtk_menu_item_new_with_label("32,768 Colors (Depth 15)");
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+    gtk_widget_show(menu_item);
+    ctk_object->screen_depth_table[screen_depth_table_len++] = 15;
+
     menu_item = gtk_menu_item_new_with_label("256 Colors (Depth 8)");
     gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
     gtk_widget_show(menu_item);
@@ -3390,12 +3302,13 @@
 
 static void setup_screen_metamode(CtkDisplayConfig *ctk_object)
 {
+    nvLayoutPtr layout = ctk_object->layout;
     nvScreenPtr screen = ctk_display_layout_get_selected_screen
         (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
     gchar *str;
 
 
-    if (!screen || !ctk_object->advanced_mode) {
+    if (!screen || !layout->advanced_mode) {
         gtk_widget_hide(ctk_object->box_screen_metamode);
         return;
     }
@@ -4768,6 +4681,7 @@
 
 void do_disable_display(CtkDisplayConfig *ctk_object, nvDisplayPtr display)
 {
+    nvLayoutPtr layout = ctk_object->layout;
     nvGpuPtr gpu = display->gpu;
     nvScreenPtr screen = display->screen;
     gchar *str;
@@ -4775,7 +4689,7 @@
 
 
     /* Setup the remove display dialog */
-    if (ctk_object->advanced_mode) {
+    if (layout->advanced_mode) {
         str = g_strdup_printf("Disable the display device %s (%s) "
                               "on GPU-%d (%s)?",
                               display->name, type,
@@ -5053,6 +4967,7 @@
     gint idx;
     nvModeLinePtr modeline;
     nvDisplayPtr display;
+    nvLayoutPtr layout = ctk_object->layout;
 
 
     /* Get the modeline and display to set */
@@ -5065,7 +4980,7 @@
     /* In Basic view, we assume the user most likely wants
      * to change which metamode is being used.
      */
-    if (!ctk_object->advanced_mode && (display->screen->num_displays == 1)) {
+    if (!layout->advanced_mode && (display->screen->num_displays == 1)) {
         int metamode_idx =
             display_find_closest_mode_matching_modeline(display, modeline);
 
@@ -5104,6 +5019,7 @@
     CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
     gint idx;
     gint last_idx;
+    nvLayoutPtr layout = ctk_object->layout;
     nvModeLinePtr modeline;
     nvDisplayPtr display;
 
@@ -5128,7 +5044,7 @@
     /* In Basic view, we assume the user most likely wants
      * to change which metamode is being used.
      */
-    if (!ctk_object->advanced_mode && (display->screen->num_displays == 1)) {
+    if (!layout->advanced_mode && (display->screen->num_displays == 1)) {
         int metamode_idx =
             display_find_closest_mode_matching_modeline(display, modeline);
 
@@ -6435,321 +6351,6 @@
 
 
 
-/** xconfig_file_clicked() *******************************************
- *
- * Called when the user clicks on the "Browse..." button of the
- * X config save dialog.
- *
- **/
-
-static void xconfig_file_clicked(GtkWidget *widget, gpointer user_data)
-{
-    CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
-    const gchar *filename =
-        gtk_entry_get_text(GTK_ENTRY(ctk_object->txt_xconfig_file));
-    gint result;
-
-
-    /* Ask user for a filename */
-    gtk_window_set_transient_for
-        (GTK_WINDOW(ctk_object->dlg_xconfig_file),
-         GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
-
-    gtk_file_selection_set_filename
-        (GTK_FILE_SELECTION(ctk_object->dlg_xconfig_file), filename);
-    
-    result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_xconfig_file));
-    gtk_widget_hide(ctk_object->dlg_xconfig_file);
-    
-    switch (result) {
-    case GTK_RESPONSE_ACCEPT:
-    case GTK_RESPONSE_OK:
-        
-        filename = gtk_file_selection_get_filename
-            (GTK_FILE_SELECTION(ctk_object->dlg_xconfig_file));
-
-        gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_xconfig_file),
-                           filename);
-
-        update_xconfig_save_buffer(ctk_object);
-        break;
-    default:
-        return;
-    }
-
-} /* xconfig_file_clicked() */
-
-
-
-/** xconfig_file_activate() ******************************************
- *
- * Called when the user selects a new X config filename.
- *
- **/
-
-static void xconfig_file_activate(GtkWidget *widget, gpointer user_data)
-{
-    CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
-
-    update_xconfig_save_buffer(ctk_object);
-
-} /* xconfig_file_activate() */
-
-
-
-/** xconfig_preview_clicked() ****************************************
- *
- * Called when the user clicks on the "Preview" button of the
- * X config save dialog.
- *
- **/
-
-static void xconfig_preview_clicked(GtkWidget *widget, gpointer user_data)
-{
-    CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
-    gboolean show = !GTK_WIDGET_VISIBLE(ctk_object->box_xconfig_save);
-
-    if (show) {
-        gtk_widget_show_all(ctk_object->box_xconfig_save);
-        gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_xconfig_save),
-                                 TRUE);
-        gtk_widget_set_size_request(ctk_object->txt_xconfig_save, 450, 350);
-        gtk_button_set_label(GTK_BUTTON(ctk_object->btn_xconfig_preview),
-                             "Hide Preview...");
-    } else {
-        gtk_widget_hide(ctk_object->box_xconfig_save);
-        gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_xconfig_save),
-                                 FALSE);
-        gtk_button_set_label(GTK_BUTTON(ctk_object->btn_xconfig_preview),
-                             "Show Preview...");
-    }
-
-} /* xconfig_preview_clicked() */
-
-
-
-/**  update_xconfig_save_buffer() ************************************
- *
- * Updates the "preview" buffer to hold the right contents based on
- * how the user wants the X config file to be generated (and what is
- * possible.)
- *
- * Also updates the state of the "Merge" checkbox in the case where
- * the named file can/cannot be parsed as a valid X config file.
- *
- */
-static gboolean update_xconfig_save_buffer(CtkDisplayConfig *ctk_object)
-{
-    gchar *filename;
-    XConfigPtr config = NULL;
-    XConfigPtr mergeConfig = NULL;
-    XConfigError error;
-    gint result;
-
-    char *tmp_filename;
-    int tmp_fd;
-    struct stat st;
-    void *buf;
-    GtkTextIter buf_start, buf_end;
-
-    gboolean merge;
-    gboolean mergable = TRUE;
-
-    gchar *err_msg = NULL;
-
-
-    /* Get how the user wants to generate the X config file */
-    merge = gtk_toggle_button_get_active
-        (GTK_TOGGLE_BUTTON(ctk_object->btn_xconfig_merge));
-
-    filename = (gchar *)gtk_entry_get_text
-        (GTK_ENTRY(ctk_object->txt_xconfig_file));
-
-
-    /* Find out if the file is mergable */
-    if (!filename || (filename[0] == '\0')) {
-        mergable = FALSE;
-    } else {
-        /* Must be able to open the file */
-        tmp_filename = (char *)xconfigOpenConfigFile(filename, NULL);
-        if (!tmp_filename || strcmp(tmp_filename, filename)) {
-            gchar *msg =
-                g_strdup_printf("Failed to open existing X config file '%s'!",
-                                filename);
-            ctk_display_warning_msg
-                (ctk_get_parent_window(GTK_WIDGET(ctk_object)), msg);
-            g_free(msg);
-
-            xconfigCloseConfigFile();
-            mergable = FALSE;
-
-        } else {
-            GenerateOptions gop;
-
-            /* Must be able to parse the file as an X config file */
-            error = xconfigReadConfigFile(&mergeConfig);
-            xconfigCloseConfigFile();
-            if (error) {
-                /* If we failed to parse the config file, we should not
-                 * allow a merge.
-                 */
-                gchar *msg =
-                    g_strdup_printf("Failed to parse existing X config file "
-                                    "'%s'!", filename);
-                ctk_display_warning_msg
-                    (ctk_get_parent_window(GTK_WIDGET(ctk_object)),
-                     msg);
-                g_free(msg);
-
-                mergeConfig = NULL;
-                mergable = FALSE;
-            }
-
-            /* Sanitize the X config file */
-            xconfigGenerateLoadDefaultOptions(&gop);
-            xconfigGetXServerInUse(&gop);
-
-            if (!xconfigSanitizeConfig(mergeConfig, NULL, &gop)) {
-                gchar *msg = g_strdup_printf("Failed to sanitize existing X "
-                                             "config file '%s'!",
-                                             filename);
-                ctk_display_warning_msg
-                    (ctk_get_parent_window(GTK_WIDGET(ctk_object)), msg);
-                g_free(msg);
-
-                xconfigFreeConfig(&mergeConfig);
-                mergable = FALSE;
-            }
-        }
-
-        /* If we're not actualy doing a merge, close the file */
-        if (!merge && mergeConfig) {
-            xconfigFreeConfig(&mergeConfig);
-        }
-    }
-
-
-    /* Generate an X config structure from our layout */
-    result = generateXConfig(ctk_object, &config);
-    if ((result != XCONFIG_GEN_OK) || !config) {
-        err_msg = g_strdup("Failed to generate an X config file!");
-        goto fail;
-    }
-
-
-    /* Merge the two X config structures */
-    if (mergeConfig) {
-        result = xconfigMergeConfigs(mergeConfig, config);
-        if (!result) {
-            xconfigFreeConfig(&mergeConfig);
-            err_msg = g_strdup_printf("Failed to merge current configuration "
-                                      "with existing X config file '%s'!",
-                                      filename);
-            ctk_display_warning_msg
-                (ctk_get_parent_window(GTK_WIDGET(ctk_object)), err_msg);
-            g_free(err_msg);
-            err_msg = NULL;
-            mergable = FALSE;
-        } else {
-            xconfigFreeConfig(&config);
-            config = mergeConfig;
-            mergeConfig = NULL;
-        }
-    }
-
-
-    /* Report merge problems */
-    merge = (merge && mergable);
-
-    g_signal_handlers_block_by_func
-        (G_OBJECT(ctk_object->btn_xconfig_merge),
-         G_CALLBACK(xconfig_merge_toggled), (gpointer) ctk_object);
-    
-    gtk_toggle_button_set_active
-        (GTK_TOGGLE_BUTTON(ctk_object->btn_xconfig_merge), merge);
-    
-    g_signal_handlers_unblock_by_func
-        (G_OBJECT(ctk_object->btn_xconfig_merge),
-         G_CALLBACK(xconfig_merge_toggled), (gpointer) ctk_object);
-    
-    gtk_widget_set_sensitive(ctk_object->btn_xconfig_merge, mergable);
-
-
-    /* Update the X config banner */
-    update_banner(config);
-
-
-    /* Setup the X config file preview buffer by writing to a temp file */
-    tmp_filename = g_strdup_printf("/tmp/.xconfig.tmp.XXXXXX");
-    tmp_fd = mkstemp(tmp_filename);
-    if (!tmp_fd) {
-        err_msg = g_strdup_printf("Failed to create temp X config file '%s' "
-                                  "for display.",
-                                  tmp_filename);
-        g_free(tmp_filename);
-        goto fail;
-    }
-    xconfigWriteConfigFile(tmp_filename, config);
-    xconfigFreeConfig(&config);
-
-    lseek(tmp_fd, 0, SEEK_SET);
-    fstat(tmp_fd, &st);
-    buf = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, tmp_fd, 0);
-
-    /* Clear the GTK buffer */
-    gtk_text_buffer_get_bounds
-        (GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save), &buf_start,
-         &buf_end);
-    gtk_text_buffer_delete
-        (GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save), &buf_start,
-         &buf_end);
-
-    /* Set the new GTK buffer contents */
-    gtk_text_buffer_set_text(GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save),
-                             buf, st.st_size);
-    munmap(buf, st.st_size);
-    close(tmp_fd);
-    remove(tmp_filename);
-    g_free(tmp_filename);
-
-    return TRUE;
-
- fail:
-    if (err_msg) {
-        ctk_display_error_msg(ctk_get_parent_window(GTK_WIDGET(ctk_object)),
-                              err_msg);
-        g_free(err_msg);
-    }
-
-    if (config) {
-        xconfigFreeConfig(&config);
-    }
-
-    if (mergeConfig) {
-        xconfigFreeConfig(&mergeConfig);
-    }
-
-    return FALSE;
-
-} /* update_xconfig_save_buffer() */
-
-
-
-/** xconfig_merge_toggled() ******************************************
- *
- * Called when the user clicks on the "Merge" button of the X config
- * save dialog.
- *
- **/
-
-static void xconfig_merge_toggled(GtkWidget *widget, gpointer user_data)
-{
-    update_xconfig_save_buffer((CtkDisplayConfig *)user_data);
-
-} /* xconfig_merge_toggled() */
-
-
-
 /** makeXConfigModeline() ********************************************
  *
  * Returns a copy of an XF86Config-parser modeline structure.
@@ -7533,207 +7134,61 @@
 
 
 
-/*
- * tilde_expansion() - do tilde expansion on the given path name;
- * based loosely on code snippets found in the comp.unix.programmer
- * FAQ.  The tilde expansion rule is: if a tilde ('~') is alone or
- * followed by a '/', then substitute the current user's home
- * directory; if followed by the name of a user, then substitute that
- * user's home directory.
- *
- * Code adapted from nvidia-xconfig
- */
-
-char *tilde_expansion(char *str)
-{
-    char *prefix = NULL;
-    char *replace, *user, *ret;
-    struct passwd *pw;
-    int len;
-
-    if ((!str) || (str[0] != '~')) return str;
-    
-    if ((str[1] == '/') || (str[1] == '\0')) {
-
-        /* expand to the current user's home directory */
-
-        prefix = getenv("HOME");
-        if (!prefix) {
-            
-            /* $HOME isn't set; get the home directory from /etc/passwd */
-            
-            pw = getpwuid(getuid());
-            if (pw) prefix = pw->pw_dir;
-        }
-        
-        replace = str + 1;
-        
-    } else {
-    
-        /* expand to the specified user's home directory */
-
-        replace = strchr(str, '/');
-        if (!replace) replace = str + strlen(str);
-
-        len = replace - str;
-        user = malloc(len + 1);
-        strncpy(user, str+1, len-1);
-        user[len] = '\0';
-        pw = getpwnam(user);
-        if (pw) prefix = pw->pw_dir;
-        free (user);
-    }
-
-    if (!prefix) return str;
-    
-    ret = malloc(strlen(prefix) + strlen(replace) + 1);
-    strcpy(ret, prefix);
-    strcat(ret, replace);
-    
-    return ret;
-
-} /* tilde_expansion() */
-
-
-
-/*
- * update_banner() - add our banner at the top of the config, but
- * first we need to remove any lines that already include our prefix
- * (because presumably they are a banner from an earlier run of
- * nvidia-settings)
- *
- * Code adapted from nvidia-xconfig
- */
-
-extern const char *pNV_ID;
-
-static void update_banner(XConfigPtr config)
-{
-    static const char *banner =
-        "X configuration file generated by nvidia-settings\n";
-    static const char *prefix =
-        "# nvidia-settings: ";
-
-    char *s = config->comment;
-    char *line, *eol, *tmp;
-    
-    /* remove all lines that begin with the prefix */
-    
-    while (s && (line = strstr(s, prefix))) {
-        
-        eol = strchr(line, '\n'); /* find the end of the line */
-        
-        if (eol) {
-            eol++;
-            if (*eol == '\0') eol = NULL;
-        }
-        
-        if (line == s) { /* the line with the prefix is at the start */
-            if (eol) {   /* there is more after the prefix line */
-                tmp = g_strdup(eol);
-                g_free(s);
-                s = tmp;
-            } else {     /* the prefix line is the only line */
-                g_free(s);
-                s = NULL;
-            }
-        } else {         /* prefix line is in the middle or end */
-            *line = '\0';
-            tmp = g_strconcat(s, eol, NULL);
-            g_free(s);
-            s = tmp;
-        }
-    }
-    
-    /* add our prefix lines at the start of the comment */
-    config->comment = g_strconcat(prefix, banner,
-                                  "# ", pNV_ID, "\n",
-                                  (s ? s : ""),
-                                  NULL);
-    if (s) g_free(s);
-    
-} /* update_banner() */
-
-
-
-/** save_xconfig_file() **********************************************
- *
- * Saves the X config file text from buf into a file called
- * filename.  If filename already exists, a backup file named
- * 'filename.backup' is created.
- *
- **/
-
-static int save_xconfig_file(CtkDisplayConfig *ctk_object,
-                             gchar *filename, char *buf, mode_t mode)
-{
-    gchar *backup_filename = NULL;
-    FILE *fp = NULL;
-    size_t size;
-    gchar *err_msg = NULL;
-
-    int ret = 0;
-
-
-    if (!buf || !filename) goto done;
-
-    size = strlen(buf) ;
-
-    /* Backup any existing file */
-    if ((access(filename, F_OK) == 0)) {
-
-        backup_filename = g_strdup_printf("%s.backup", filename);
-        nv_info_msg("", "X configuration file '%s' already exists, "
-                    "backing up file as '%s'", filename,
-                    backup_filename);
-        
-        /* Delete any existing backup file */
-        if (access(backup_filename, F_OK) == 0) {
-
-            if (unlink(backup_filename) != 0) {
-                err_msg =
-                    g_strdup_printf("Unable to remove old X config backup "
-                                    "file '%s'.",
-                                    backup_filename);
-                goto done;
-            }
-        }
-
-        /* Make the current x config file the backup */
-        if (rename(filename, backup_filename)) {
-                err_msg =
-                    g_strdup_printf("Unable to create new X config backup "
-                                    "file '%s'.",
-                                    backup_filename);
-            goto done;            
-        }
-    }
-
-    /* Write out the X config file */
-    fp = fopen(filename, "w");
-    if (!fp) {
-        err_msg =
-            g_strdup_printf("Unable to open X config file '%s' for writing.",
-                            filename);
-        goto done;
-    }
-    fprintf(fp, "%s", buf);
-
-    ret = 1;
-    
- done:
-    /* Display any errors that might have occured */
-    if (err_msg) {
-        ctk_display_error_msg(ctk_get_parent_window(GTK_WIDGET(ctk_object)),
-                              err_msg);
+/** xconfig_generate() ***********************************************
+ *
+ * Callback to generate an X config structure based on the current
+ * display configuration.
+ *
+ **/
+static XConfigPtr xconfig_generate(XConfigPtr xconfCur,
+                                   Bool merge,
+                                   Bool *merged,
+                                   void *callback_data)
+{
+    CtkDisplayConfig *ctk_object = (CtkDisplayConfig *)callback_data;
+    XConfigPtr xconfGen = NULL;
+    gint result;
+
+
+    *merged = FALSE;
+
+    /* Generate an X config structure from our layout */
+    result = generateXConfig(ctk_object, &xconfGen);
+    if ((result != XCONFIG_GEN_OK) || !xconfGen) {
+        goto fail;
+    }
+
+    /* If we're not merging, we're done */
+    if (!xconfCur || !merge) {
+        return xconfGen;
+    }
+
+    /* Merge xconfGen into xconfCur */
+    result = xconfigMergeConfigs(xconfCur, xconfGen);
+    if (!result) {
+        gchar *err_msg = g_strdup_printf("Failed to merge generated "
+                                         "configuration with existing "
+                                         "X config file!");
+        ctk_display_warning_msg(ctk_get_parent_window(GTK_WIDGET(ctk_object)),
+                                err_msg);
         g_free(err_msg);
-    }
-
-    if (fp) fclose(fp);
-    g_free(backup_filename);
-    return ret;
-    
-} /* save_xconfig_file() */
+        return xconfGen;
+    }
+
+    /* Merge worked */
+    xconfigFreeConfig(&xconfGen);
+    *merged = TRUE;
+    return xconfCur;
+
+
+ fail:
+    if (xconfGen) {
+        xconfigFreeConfig(&xconfGen);
+    }
+
+    return NULL;
+
+} /* xconfig_generate() */
 
 
 
@@ -7746,13 +7201,6 @@
 static void save_clicked(GtkWidget *widget, gpointer user_data)
 {
     CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
-    gint result;
-    gboolean created;
-
-    gchar *filename;
-
-    void *buf;
-    GtkTextIter buf_start, buf_end;
 
 
     /* Make sure the layout is ready to be saved */
@@ -7760,84 +7208,8 @@
         return;
     }
 
-
-    /* Setup the default X config filename */
-    if (!ctk_object->layout->filename) {
-        filename = (gchar *) xconfigOpenConfigFile(NULL, NULL);
-        if (filename) {
-            ctk_object->layout->filename = g_strdup(filename);
-            xconfigCloseConfigFile();
-            filename = NULL;
-        } else {
-            ctk_object->layout->filename = g_strdup("");
-        }
-    }
-    gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_xconfig_file),
-                       ctk_object->layout->filename);
-
-
-    /* Generate the X config file save buffer */
-    created = update_xconfig_save_buffer(ctk_object);
-    if (!created) {
-        return;
-    }
-
-
-    /* Confirm the save */
-    gtk_window_set_transient_for
-        (GTK_WINDOW(ctk_object->dlg_xconfig_save),
-         GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
-    gtk_widget_hide(ctk_object->box_xconfig_save);
-    gtk_window_resize(GTK_WINDOW(ctk_object->dlg_xconfig_save), 350, 1);
-    gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_xconfig_save),
-                             FALSE);
-    gtk_button_set_label(GTK_BUTTON(ctk_object->btn_xconfig_preview),
-                         "Show preview...");
-    gtk_widget_show(ctk_object->dlg_xconfig_save);
-    result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_xconfig_save));
-    gtk_widget_hide(ctk_object->dlg_xconfig_save);
-    
-    
-    /* Handle user's response */
-    switch (result)
-    {
-    case GTK_RESPONSE_ACCEPT:
-
-        /* Get the filename to write to */
-        filename =
-            (gchar *) gtk_entry_get_text(GTK_ENTRY(ctk_object->txt_xconfig_file));
-
-        g_free(ctk_object->layout->filename);
-        ctk_object->layout->filename = tilde_expansion(filename);
-        if (ctk_object->layout->filename == filename) {
-            ctk_object->layout->filename = g_strdup(filename);
-        }
-        filename = ctk_object->layout->filename;
-
-
-        /* Get the buffer to write */
-        gtk_text_buffer_get_bounds
-            (GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save), &buf_start,
-             &buf_end);
-        buf = (void *) gtk_text_buffer_get_text
-            (GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save), &buf_start,
-             &buf_end, FALSE);
-        if (!buf) {
-            nv_error_msg("Failed to read X configuration buffer!");
-            break;
-        }
-
-        /* Save the X config file */
-        nv_info_msg("", "Writing X config file '%s'", filename);
-        save_xconfig_file(ctk_object, filename, (char *)buf, 0644);
-        g_free(buf);
-        break;
-        
-    case GTK_RESPONSE_REJECT:
-    default:
-        /* do nothing. */
-        break;
-    }
+    /* Run the save dialog */
+    run_save_xconfig_dialog(ctk_object->save_xconfig_dlg);
 
 } /* save_clicked() */
 
@@ -7852,23 +7224,24 @@
 static void advanced_clicked(GtkWidget *widget, gpointer user_data)
 {
     CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+    nvLayoutPtr layout = ctk_object->layout;
     
 
     /* Toggle advanced options for the display */
-    ctk_object->advanced_mode = !(ctk_object->advanced_mode);
+    layout->advanced_mode = !(layout->advanced_mode);
 
 
     /* Show advanced display options */
-    if (ctk_object->advanced_mode) {
+    if (layout->advanced_mode) {
         gtk_button_set_label(GTK_BUTTON(widget), "Basic...");
-        ctk_display_layout_set_advanced_mode(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
-                                             1);
+        ctk_display_layout_set_advanced_mode
+            (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), 1);
 
     /* Show basic display options */
     } else {
         gtk_button_set_label(GTK_BUTTON(widget), "Advanced...");
-        ctk_display_layout_set_advanced_mode(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
-                                             0);
+        ctk_display_layout_set_advanced_mode
+            (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), 0);
     }
 
     

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkdisplayconfig.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig.h (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplayconfig.h Tue Jul 28 07:31:57 2009
@@ -28,6 +28,8 @@
 #include "ctkevent.h"
 #include "ctkconfig.h"
 #include "ctkdisplaylayout.h"
+#include "ctkdisplayconfig-utils.h"
+
 
 
 G_BEGIN_DECLS
@@ -158,18 +160,7 @@
     guint display_confirm_timer;
     int display_confirm_countdown; /* Timeout to reset display config */
 
-    GtkWidget *dlg_xconfig_save;     /* Save X config dialog */
-    GtkWidget *scr_xconfig_save;     /* Scroll window */
-    GtkWidget *txt_xconfig_save;     /* Text view of file contents */
-    GtkTextBuffer *buf_xconfig_save; /* Text buffer (Actual) file contents */
-    GtkWidget *btn_xconfig_merge;    /* Merge with existing X config */
-    GtkWidget *btn_xconfig_preview;  /* Show/Hide button */
-    GtkWidget *box_xconfig_save;     /* Show/Hide this box */
- 
-    GtkWidget *dlg_xconfig_file; /* File save dialog */
-    GtkWidget *btn_xconfig_file;
-    GtkWidget *txt_xconfig_file;
-
+    SaveXConfDlg *save_xconfig_dlg;
 
     /* Buttons */
     GtkWidget *btn_apply;
@@ -186,7 +177,6 @@
     GtkWidget *btn_probe;
 
     GtkWidget *btn_advanced;
-    gboolean   advanced_mode;  /* True if we are in advanced mode */
 
     GtkWidget *btn_reset;
     

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-crt.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkdisplaydevice-crt.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-crt.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-crt.c Tue Jul 28 07:31:57 2009
@@ -266,6 +266,8 @@
         add_acquire_edid_help(b, &i);
     }
     
+    ctk_help_reset_hardware_defaults(b, &i, ctk_display_device_crt->name);
+
     ctk_help_finish(b);
 
     return b;

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-dfp.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkdisplaydevice-dfp.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-dfp.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-dfp.c Tue Jul 28 07:31:57 2009
@@ -86,9 +86,9 @@
 "A flat panel usually has a single 'native' resolution.  If you are "
 "using a resolution that is smaller than the flat panel's native "
 "resolution, then Flat Panel Scaling can adjust how the image is "
-"displayed on the flat panel.  This setting will only take effect "
-"when GPU scaling is active (This occurs when the frontend and "
-"backend resolutions of the current mode are different.)";
+"displayed on the flat panel. This setting will only take effect when "
+"GPU scaling is active, which occurs when the frontend and backend "
+"resolutions of the current mode are different.";
 
 static const char *__info_help = 
 "This section describes basic informations about the "
@@ -827,8 +827,8 @@
     ctk_help_term(b, &i, "Chip Location");
     ctk_help_para(b, &i, "Report whether the flat panel is driven by "
                   "the on-chip controller (internal), or a "
-                  " separate controller chip elsewhere on the "
-                  "graphics board (external)");
+                  "separate controller chip elsewhere on the "
+                  "graphics board (external).");
                       
     ctk_help_term(b, &i, "Link");
     ctk_help_para(b, &i, "Report whether the specified display device "
@@ -837,7 +837,7 @@
     
     ctk_help_term(b, &i, "Signal");
     ctk_help_para(b, &i, "Report whether the flat panel is driven by "
-                  "an LVDS, TMDS, or DisplayPort signal");
+                  "an LVDS, TMDS, or DisplayPort signal.");
 
     ctk_help_term(b, &i, "Native Resolution");
     ctk_help_para(b, &i, __native_res_help);
@@ -870,7 +870,8 @@
     
     ctk_help_term(b, &i, "Centered");
     ctk_help_para(b, &i, "The image will only occupy the number of pixels "
-                  "needed and be centered on the flat panel.");
+                  "needed and be centered on the flat panel. Setting this "
+                  "will disable image sharpening for the display device.");
     
     ctk_help_term(b, &i, "Aspect Ratio Scaled");
     ctk_help_para(b, &i, "The image will be scaled (retaining the original "
@@ -883,6 +884,8 @@
     if (ctk_display_device_dfp->edid) {
         add_acquire_edid_help(b, &i);
     }
+
+    ctk_help_reset_hardware_defaults(b, &i, ctk_display_device_dfp->name);
 
     ctk_help_finish(b);
     

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-tv.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkdisplaydevice-tv.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-tv.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaydevice-tv.c Tue Jul 28 07:31:57 2009
@@ -737,6 +737,8 @@
         add_acquire_edid_help(b, &i);
     }
     
+    ctk_help_reset_hardware_defaults(b, &i, ctk_display_device_tv->name);
+
     ctk_help_finish(b);
 
     return b;

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaylayout.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkdisplaylayout.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaylayout.h (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkdisplaylayout.h Tue Jul 28 07:31:57 2009
@@ -312,6 +312,9 @@
 typedef struct nvLayoutRec {
     XConfigLayoutPtr conf_layout;
     char *filename;
+    Bool  advanced_mode; /* Allow advanced layout modifications: */
+                         /*   - panning */
+                         /*   - multiple (meta)modes */
 
     NvCtrlAttributeHandle *handle;
 

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkevent.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkevent.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkevent.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkevent.c Tue Jul 28 07:31:57 2009
@@ -261,11 +261,16 @@
     MAKE_SIGNAL(NV_CTRL_STEREO_EYES_EXCHANGE);
     MAKE_SIGNAL(NV_CTRL_NO_SCANOUT);
     MAKE_SIGNAL(NV_CTRL_GVO_CSC_CHANGED_EVENT);
+    MAKE_SIGNAL(NV_CTRL_X_SERVER_UNIQUE_ID);
     MAKE_SIGNAL(NV_CTRL_PIXMAP_CACHE);
     MAKE_SIGNAL(NV_CTRL_PIXMAP_CACHE_ROUNDING_SIZE_KB);
     MAKE_SIGNAL(NV_CTRL_IS_GVO_DISPLAY);
     MAKE_SIGNAL(NV_CTRL_PCI_ID);
     MAKE_SIGNAL(NV_CTRL_GVO_FULL_RANGE_COLOR);
+    MAKE_SIGNAL(NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE);
+    MAKE_SIGNAL(NV_CTRL_GVO_ENABLE_RGB_DATA);
+    MAKE_SIGNAL(NV_CTRL_IMAGE_SHARPENING_DEFAULT);
+    MAKE_SIGNAL(NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION);
 
 #undef MAKE_SIGNAL
     
@@ -276,7 +281,7 @@
      * knows about.
      */
 
-#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GVO_FULL_RANGE_COLOR
+#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION
 #warning "There are attributes that do not emit signals!"
 #endif
 

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkframelock.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkframelock.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkframelock.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkframelock.c Tue Jul 28 07:31:57 2009
@@ -213,6 +213,9 @@
 struct _nvFrameLockDataRec {
 
     gpointer   handle; /* NV-CONTROL Frame Lock Target */
+    int        server_id;
+
+    int        sync_delay_resolution;
 
     /* Signal Handler IDs */
     gulong     signal_ids[NUM_FRAMELOCK_SIGNALS];
@@ -326,7 +329,7 @@
 
 
 
-static unsigned int add_framelock_devices(CtkFramelock *, gpointer);
+static unsigned int add_framelock_devices(CtkFramelock *, gpointer, int);
 static unsigned int add_gpu_devices(CtkFramelock *, nvListEntryPtr);
 static unsigned int add_display_devices(CtkFramelock *, nvListEntryPtr);
 static gint add_devices(CtkFramelock *, const gchar *, gboolean);
@@ -2469,6 +2472,54 @@
 
 
 
+/** find_server_by_id() ********************************************
+ *
+ * - Looks in the list tree for a framelock list entry with a target
+ *   server with an id 'server_id'. The first list entry found
+ *   with such a server id is returned.
+ */
+static nvListEntryPtr find_server_by_id(nvListTreePtr tree,
+                                        int server_id)
+{
+    nvListEntryPtr entry;
+
+    entry = tree->entries;
+    while (entry) {
+        /* hold server id only in framelock entries */
+        if (entry->data_type == ENTRY_DATA_FRAMELOCK &&
+            ((nvFrameLockDataPtr)(entry->data))->server_id == server_id) {
+
+            return entry;
+        }
+        
+        entry = entry->next_sibling;
+    }
+
+    return entry;
+}
+
+
+
+/** get_server_id() ****************************************
+ *
+ * - Gets the X_SERVER_UNIQUE_ID nv-control attribute
+ */
+static gboolean get_server_id(NvCtrlAttributeHandle *handle,
+                              int *server_id)
+{
+    ReturnStatus ret;
+
+    ret = NvCtrlGetAttribute(handle, NV_CTRL_X_SERVER_UNIQUE_ID, server_id);
+
+    if (ret != NvCtrlSuccess) {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+
 /** find_entry_by_name() *********************************************
  *
  * - Looks in the list tree for the first list entry to have a handle
@@ -3408,7 +3459,8 @@
     /* Sync Delay (Skew) */
     gtk_widget_set_sensitive(data->delay_label, framelock_enabled);
     gtk_widget_set_sensitive(data->delay_text, framelock_enabled);
-    fvalue = ((gfloat) delay) * NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR;
+    fvalue = ((gfloat) delay) *
+             ((gfloat) data->sync_delay_resolution) / 1000.0;
     snprintf(str, 32, "%.2f uS", fvalue); // 10.2f
     gtk_label_set_text(GTK_LABEL(data->delay_text), str);
 
@@ -5155,7 +5207,8 @@
  *
  */
 static unsigned int add_framelock_devices(CtkFramelock *ctk_framelock,
-                                          gpointer handle)
+                                          gpointer handle,
+                                          int server_id)
 {
     unsigned int        num_framelocks;
     unsigned int        framelocks_added = 0;
@@ -5194,7 +5247,19 @@
                                 framelock_id,
                                 NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM);
 
-        /* Get the framelock revision information */
+        /* Gather framelock device information */
+        ret = NvCtrlGetAttribute(framelock_data->handle,
+                                 NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION,
+                                 &val);
+        if (ret == NvCtrlSuccess) {
+            framelock_data->sync_delay_resolution = val;
+        } else {
+            /* Fall back to the GSync II's resolution when
+             * working with an older X server
+             */
+            framelock_data->sync_delay_resolution = 7810;
+        }
+
         ret = NvCtrlGetAttribute(framelock_data->handle,
                                  NV_CTRL_FRAMELOCK_FPGA_REVISION,
                                  &val);
@@ -5230,6 +5295,8 @@
 
         framelock_data->extra_info_hbox = gtk_hbox_new(FALSE, 5);
 
+        framelock_data->server_id = server_id;
+
         /* Create the frame lock list entry */
         entry = list_entry_new_with_framelock(framelock_data);
 
@@ -5290,6 +5357,7 @@
 {
     gpointer handle = NULL;
     Display *display;
+    int server_id = -1;
     gint devices_added = 0;
     char *server_name = NULL;
     char *ptr;
@@ -5328,30 +5396,6 @@
     } else {
         /* Assume sever id 0 if none given */
         sprintf(server_name + strlen(server_name), ":0");
-    }
-
-    /*
-     * try to prevent users from adding the same X server more than
-     * once.
-     *
-     * XXX This is not an absolute check: this does not catch
-     *     "localhost:0" versus ":0", for example, nor does it
-     *     catch entering an IP vs entering a hostname.
-     */
-   
-    if (find_server_by_name(ctk_framelock->tree, server_name)) {
-        if (error_dialog) {
-            error_msg(ctk_framelock, "<span weight=\"bold\" "
-                      "size=\"larger\">Unable to add X server "
-                      "to frame lock Group</span>\n\n"
-                      "The X server %s already belongs to the frame lock "
-                      "Group.", server_name);
-        } else {
-            nv_error_msg("Unable to add X server to frame lock group; "
-                         "the X server %s already belongs to the "
-                         "frame lock group.", server_name);
-        }
-        goto done;
     }
   
     /* open an X Display connection to that X server */
@@ -5388,9 +5432,28 @@
         goto done;
     }
     
+    /* Try to prevent users from adding the same X server more than once */
+
+    if (get_server_id(handle, &server_id) &&
+        server_id != -1 &&
+        find_server_by_id(ctk_framelock->tree, server_id)) {
+        if (error_dialog) {
+            error_msg(ctk_framelock, "<span weight=\"bold\" "
+                      "size=\"larger\">Unable to add X server "
+                      "to frame lock Group</span>\n\n"
+                      "The X server %s already belongs to the frame lock "
+                      "Group.", server_name);
+        } else {
+            nv_error_msg("Unable to add X server to frame lock group; "
+                         "the X server %s already belongs to the "
+                         "frame lock group.", server_name);
+        }
+        goto done;
+    }
+
     /* Add frame lock devices found on server */
 
-    devices_added = add_framelock_devices(ctk_framelock, handle);
+    devices_added = add_framelock_devices(ctk_framelock, handle, server_id);
     if (!devices_added) {
         if (error_dialog) {
             error_msg(ctk_framelock, "<span weight=\"bold\" "
@@ -5444,7 +5507,7 @@
 static void add_entry_to_parsed_attributes(nvListEntryPtr entry,
                                              ParsedAttribute *head)
 {
-    ParsedAttribute a;
+    ParsedAttribute a = { 0 };
     char *display_name = NULL;
     int target_type = 0;
     int target_id = 0;

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkglx.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkglx.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkglx.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkglx.c Tue Jul 28 07:31:57 2009
@@ -70,21 +70,21 @@
   "buffers that are swappable.  '-' if this is not supported.";
 static const char * __st_help =
   "st (Stereo buffer) - 'y' if the configuration has left and right color "
-  "buffers that are rendered to in stereo.  '-' if this is not supported";
+  "buffers that are rendered to in stereo.  '-' if this is not supported.";
 static const char * __rs_help =
   "rs (Red size) - Number of bits per color used for red. "
   "(Undefined for configurations that use color indexing.)";
 static const char * __gs_help =
-  "gs (Green size - Number of bits per color used for green. "
+  "gs (Green size) - Number of bits per color used for green. "
   "(Undefined for configurations that use color indexing.)";
 static const char * __bs_help =
-  "bs (Blue size - Number of bits per color used for blue. "
+  "bs (Blue size) - Number of bits per color used for blue. "
   "(Undefined for configurations that use color indexing.)";
 static const char * __as_help =
-  "as (Alpha size - Number of bits per color used for alpha. "
+  "as (Alpha size) - Number of bits per color used for alpha. "
   "(Undefined for configurations that use color indexing.)";
 static const char * __aux_help =
-  "aux (Auxillary buffers) - Number of available auxiliary color butters.";
+  "aux (Auxiliary buffers) - Number of available auxiliary color buffers.";
 static const char * __dpt_help =
   "dpt (Depth buffer size) - Number of bits per color in the depth buffer.";
 static const char * __stn_help =
@@ -816,7 +816,7 @@
     ctk_help_para(b, &i,
                   "This will tell you if direct rendering is available.  If "
                   "direct rendering is available, then a program running on "
-                  "the same computer that the control pannel is running on "
+                  "the same computer that the control panel is running on "
                   "will be able to bypass the X Server and take advantage of "
                   "faster rendering.  If direct rendering is not available, "
                   "then indirect rendering will be used and all rendering "
@@ -859,6 +859,27 @@
                   "libraries."
                   );
 
+    ctk_help_heading(b, &i, "OpenGL Vendor String");
+    ctk_help_para(b, &i,
+                  "This is the name of the vendor providing the OpenGL "
+                  "implementation."
+                 );
+    ctk_help_heading(b, &i, "OpenGL Renderer String");
+    ctk_help_para(b, &i,
+                  "This shows the details of the graphics card on which "
+                  "OpenGL is running."
+                 );
+    ctk_help_heading(b, &i, "OpenGL Version String");
+    ctk_help_para(b, &i,
+                  "This is the version of the OpenGL implementation."
+                 );
+    ctk_help_heading(b, &i, "OpenGL Extensions");
+    ctk_help_para(b, &i,
+                  "This is the list of OpenGL extensions that are supported "
+                  "by this driver."
+                 );
+
+
     ctk_help_heading(b, &i, "Frame Buffer Configurations");
     ctk_help_para(b, &i, "This table lists the supported frame buffer "
                   "configurations for the display.");
@@ -875,6 +896,7 @@
                   "\t%s\n\n"
                   "\t%s\n\n"
 
+                  "\t%s\n\n"
                   "\t%s\n\n"
                   "\t%s\n\n"
                   "\t%s\n\n"

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkgpu.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkgpu.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkgpu.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkgpu.c Tue Jul 28 07:31:57 2009
@@ -39,6 +39,7 @@
 
 static void probe_displays_received(GtkObject *object, gpointer arg1,
                                     gpointer user_data);
+#define ARRAY_ELEMENTS 16
 
 GType ctk_gpu_get_type(
     void
@@ -142,6 +143,9 @@
     int pci_device;
     int pci_func;
     gchar *pci_bus_id;
+    gchar pci_device_id[ARRAY_ELEMENTS];
+    gchar pci_vendor_id[ARRAY_ELEMENTS];
+    int pci_id;
 
     gchar *__pci_bus_id_unknown = "?:?:?";
 
@@ -224,6 +228,21 @@
                                      pci_bus, pci_device, pci_func);
     } else {
         pci_bus_id = g_strdup(__pci_bus_id_unknown);
+    }
+
+    /* NV_CTRL_PCI_ID */
+
+    pci_device_id[ARRAY_ELEMENTS-1] = '\0';
+    pci_vendor_id[ARRAY_ELEMENTS-1] = '\0';
+
+    ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_ID, &pci_id);
+
+    if (ret != NvCtrlSuccess) {
+        snprintf(pci_device_id, ARRAY_ELEMENTS, "Unknown");
+        snprintf(pci_vendor_id, ARRAY_ELEMENTS, "Unknown");
+    } else {
+        snprintf(pci_device_id, ARRAY_ELEMENTS, "0x%04x", (pci_id & 0xFFFF));
+        snprintf(pci_vendor_id, ARRAY_ELEMENTS, "0x%04x", (pci_id >> 16));
     }
 
     /* NV_CTRL_STRING_VBIOS_VERSION */
@@ -345,7 +364,7 @@
     hseparator = gtk_hseparator_new();
     gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
 
-    table = gtk_table_new(17, 2, FALSE);
+    table = gtk_table_new(19, 2, FALSE);
     gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
     gtk_table_set_row_spacings(GTK_TABLE(table), 3);
     gtk_table_set_col_spacings(GTK_TABLE(table), 15);
@@ -368,15 +387,21 @@
                   0, 0.5, "Bus ID:",
                   0, 0.5, pci_bus_id);
     add_table_row(table, 8,
+                  0, 0.5, "PCI Device ID:",
+                  0, 0.5, pci_device_id);
+    add_table_row(table, 9,
+                  0, 0.5, "PCI Vendor ID:",
+                  0, 0.5, pci_vendor_id);
+    add_table_row(table, 10,
                   0, 0.5, "IRQ:",
                   0, 0.5, irq);
     /* spacing */
-    add_table_row(table, 12,
+    add_table_row(table, 14,
                   0, 0, "X Screens:",
                   0, 0, screens);
     /* spacing */
     ctk_gpu->displays =
-        add_table_row(table, 16,
+        add_table_row(table, 18,
                       0, 0, "Display Devices:",
                       0, 0, displays);
 
@@ -447,6 +472,12 @@
                   "configuration file option to unambiguously associate "
                   "Device sections with this GPU.");
     
+    ctk_help_heading(b, &i, "PCI Device ID");
+    ctk_help_para(b, &i, "This is the PCI Device ID of the GPU.");
+    
+    ctk_help_heading(b, &i, "PCI Vendor ID");
+    ctk_help_para(b, &i, "This is the PCI Vendor ID of the GPU.");
+    
     ctk_help_heading(b, &i, "IRQ");
     ctk_help_para(b, &i, "This is the interrupt request line assigned to "
                   "this GPU.");

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkgvo.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkgvo.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkgvo.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkgvo.c Tue Jul 28 07:31:57 2009
@@ -1455,17 +1455,24 @@
 
     if (enabled) val = NV_CTRL_GVO_DISPLAY_X_SCREEN_ENABLE;
     else         val = NV_CTRL_GVO_DISPLAY_X_SCREEN_DISABLE;
-    NvCtrlSetAttribute(ctk_gvo->handle, NV_CTRL_GVO_DISPLAY_X_SCREEN, val);
-
-    /*
-     * XXX NV_CTRL_GVO_DISPLAY_X_SCREEN can silently fail if GLX
-     * locked GVO output for use by pbuffer(s).  Check that the
-     * setting actually stuck.
-     */
-    
-    ret = NvCtrlGetAttribute(ctk_gvo->handle,
-                             NV_CTRL_GVO_LOCK_OWNER,
-                             &ctk_gvo->lock_owner);
+
+    ret = NvCtrlSetDisplayAttributeWithReply(ctk_gvo->handle,
+                                             0, /* display_mask */
+                                             NV_CTRL_GVO_DISPLAY_X_SCREEN,
+                                             val);
+    
+    if (ret == NvCtrlSuccess) {
+
+        /*
+         * XXX NV_CTRL_GVO_DISPLAY_X_SCREEN can silently fail if GLX
+         * locked GVO output for use by pbuffer(s).  Check that the
+         * setting actually stuck.
+         */
+
+        ret = NvCtrlGetAttribute(ctk_gvo->handle,
+                                 NV_CTRL_GVO_LOCK_OWNER,
+                                 &ctk_gvo->lock_owner);
+    }
 
     if ((ret != NvCtrlSuccess) ||
         (enabled &&

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkhelp.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkhelp.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkhelp.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkhelp.c Tue Jul 28 07:31:57 2009
@@ -406,3 +406,14 @@
     gtk_text_buffer_apply_tag_by_name
         (buffer, CTK_HELP_SINGLE_SPACE_TAG, &start, &end);
 }
+
+void ctk_help_reset_hardware_defaults(GtkTextBuffer *b, GtkTextIter *i,
+                                      char *name)
+{
+    ctk_help_heading(b, i, "Reset Hardware Defaults");
+    ctk_help_para(b, i, "The Reset Hardware Defaults button restores "
+                  "the %s settings to their default "
+                  "values.", name);
+
+}
+

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkhelp.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkhelp.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkhelp.h (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkhelp.h Tue Jul 28 07:31:57 2009
@@ -78,6 +78,9 @@
 void ctk_help_term    (GtkTextBuffer *, GtkTextIter *, const gchar *, ...);
 void ctk_help_finish  (GtkTextBuffer *);
 
+void ctk_help_reset_hardware_defaults(GtkTextBuffer *, GtkTextIter *, char *);
+
+
 #define CTK_HELP_TITLE_TAG                "title"
 #define CTK_HELP_HEADING_TAG              "heading"
 #define CTK_HELP_HEADING_NOT_EDITABLE_TAG "not_editable"

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkimagesliders.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkimagesliders.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkimagesliders.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkimagesliders.c Tue Jul 28 07:31:57 2009
@@ -94,6 +94,8 @@
     
     GtkWidget *frame;
     GtkWidget *vbox;
+    ReturnStatus status;
+    gint val;
     
     /*
      * now that we know that we will have atleast one attribute,
@@ -110,6 +112,17 @@
     ctk_image_sliders->display_device_mask = display_device_mask;
     ctk_image_sliders->name = name;
     
+    /* cache image sharpening default value */
+
+    status = NvCtrlGetDisplayAttribute(ctk_image_sliders->handle,
+                                       ctk_image_sliders->display_device_mask,
+                                       NV_CTRL_IMAGE_SHARPENING_DEFAULT,
+                                       &val);
+    if (status != NvCtrlSuccess) {
+        val = 0;
+    }
+    ctk_image_sliders->default_val = val;
+    
     /* create the frame and vbox */
     
     frame = gtk_frame_new(NULL);
@@ -291,7 +304,7 @@
         NvCtrlSetDisplayAttribute(ctk_image_sliders->handle,
                                   ctk_image_sliders->display_device_mask,
                                   NV_CTRL_IMAGE_SHARPENING,
-                                  0);
+                                  ctk_image_sliders->default_val);
     }
 
     ctk_image_sliders_setup(ctk_image_sliders);

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkimagesliders.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkimagesliders.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkimagesliders.h (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkimagesliders.h Tue Jul 28 07:31:57 2009
@@ -68,6 +68,7 @@
     GtkWidget *frame;
     GtkWidget *digital_vibrance;
     GtkWidget *image_sharpening;
+    gint default_val;
 };
 
 struct _CtkImageSlidersClass

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkmultisample.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkmultisample.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkmultisample.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkmultisample.c Tue Jul 28 07:31:57 2009
@@ -1349,7 +1349,7 @@
         if (ctk_multisample->active_attributes & __FSAA_4x) {
             ctk_help_term(b, &i, "4x (4xMS)");
             ctk_help_para(b, &i, "This enables antialiasing using the 4x (4xMS)"
-                          "Bilinearmode. This mode offers higher image "
+                          "Bilinear mode. This mode offers higher image "
                           "quality at the expense of some performance in "
                           "OpenGL applications.");
         }
@@ -1373,8 +1373,7 @@
             ctk_help_term(b, &i, "8x (4xSS, 2xMS)");
             ctk_help_para(b, &i, "This enables antialiasing using the 8x "
                           "(4xSS, 2xMS) mode.  This mode offers better image "
-                          "quality than the 4x mode; 8xS is only available on "
-                          "Geforce (non-Quadro) FX or better GPUs.");
+                          "quality than the 4x mode.");
         }
 
         if (ctk_multisample->active_attributes & __FSAA_16x) {

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkpowermizer.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkpowermizer.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkpowermizer.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkpowermizer.c Tue Jul 28 07:31:57 2009
@@ -54,11 +54,11 @@
 "This indicates the current Performance Level of the GPU.";
 
 static const char *__performance_mode_short_help =
-"This indicates the current Performance Mode of the GPU.\n";
+"This indicates the current Performance Mode of the GPU.";
 
 static const char *__performance_mode_help =
-"This indicates the current Performance Mode of the GPU.\n"
-"Performance Mode can be either \"Desktop\" or\n"
+"This indicates the current Performance Mode of the GPU. "
+"Performance Mode can be either \"Desktop\" or "
 "\"Maximum Performance\".";
 
 static const char *__gpu_clock_freq_help =
@@ -604,11 +604,11 @@
     ctk_help_heading(b, &i, "Adaptive Clocking");
     ctk_help_para(b, &i, __adaptive_clock_help);
 
+    ctk_help_heading(b, &i, "Clock Frequencies");
+    ctk_help_para(b, &i, __clock_freq_help);
+
     ctk_help_heading(b, &i, "Power Source");
     ctk_help_para(b, &i, __power_source_help);
-
-    ctk_help_heading(b, &i, "Clock Frequencies");
-    ctk_help_para(b, &i, __clock_freq_help);
 
     ctk_help_heading(b, &i, "Performance Level");
     ctk_help_para(b, &i, __performance_level_help);

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkserver.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkserver.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkserver.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkserver.c Tue Jul 28 07:31:57 2009
@@ -433,10 +433,10 @@
                   0, 0.5, "Server Vendor Version:", 0, 0.5, vendor_ver);
     /* separator */
     add_table_row(table, 10,
-                  0, 0,   "NV-Control Version:",    0, 0, nv_control_server_version);
+                  0, 0,   "NV-CONTROL Version:",    0, 0, nv_control_server_version);
     /* separator */
     add_table_row(table, 14,
-                  0, 0,   "X Screens:",             0, 0, num_screens);
+                  0, 0,   "Screens:",               0, 0, num_screens);
 
 
     /* print special trademark text for FreeBSD */
@@ -510,7 +510,7 @@
                   "X driver is running; possible values are "
                   "'Linux', 'FreeBSD', and 'SunOS'.  This also specifies the "
                   "platform on which the operating system is running, such "
-                  "as x86, x86_64, or ia64");
+                  "as x86, x86_64, or ia64.");
     
     ctk_help_heading(b, &i, "NVIDIA Driver Version");
     ctk_help_para(b, &i, "This is the version of the NVIDIA Accelerated "
@@ -520,17 +520,22 @@
     ctk_help_para(b, &i, "This is the display connection string used to "
                   "communicate with the X Server.");
 
-    ctk_help_heading(b, &i, "X Server Version");
+    ctk_help_heading(b, &i, "Server Version");
     ctk_help_para(b, &i, "This is the version number of the X Server.");
 
-    ctk_help_heading(b, &i, "X Server Vendor String");
+    ctk_help_heading(b, &i, "Server Vendor String");
     ctk_help_para(b, &i, "This is the X Server vendor information string.");
 
-    ctk_help_heading(b, &i, "X Server Vendor Version");
-    ctk_help_para(b, &i, "This is the vertsion number of the X Server "
+    ctk_help_heading(b, &i, "Server Vendor Version");
+    ctk_help_para(b, &i, "This is the version number of the X Server "
                   "vendor.");
 
-    ctk_help_heading(b, &i, "X Screens");
+    ctk_help_heading(b, &i, "NV-CONTROL Version");
+    ctk_help_para(b, &i, "This is the version number of the NV-CONTROL X extension, "
+                  "used by nvidia-settings to communicate with the "
+                  "NVIDIA X driver.");
+
+    ctk_help_heading(b, &i, "Screens");
     ctk_help_para(b, &i, "This is the number of X Screens on the "
                   "display.  (When Xinerama is enabled this is always 1).");
 

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkslimm.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkslimm.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkslimm.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkslimm.c Tue Jul 28 07:31:57 2009
@@ -30,6 +30,9 @@
 #include <X11/Xlib.h>
 #include <X11/extensions/Xrandr.h>
 
+#include "msg.h"
+#include "parse.h"
+
 #include "ctkbanner.h"
 
 #include "ctkslimm.h"
@@ -48,8 +51,8 @@
 static void txt_overlap_activated(GtkWidget *widget, gpointer user_data);
 static void slimm_checkbox_toggled(GtkWidget *widget, gpointer user_data);
 static void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data);
-static void write_slimm_options(CtkSLIMM *ctk_object, gchar *metamode_str);
-static void remove_slimm_options(CtkSLIMM *ctk_object);
+static void add_slimm_options(XConfigPtr xconf, gchar *metamode_str);
+static void remove_slimm_options(XConfigPtr xconf);
 static nvDisplayPtr find_active_display(nvLayoutPtr layout);
 static nvDisplayPtr intersect_modelines(nvLayoutPtr layout);
 static void remove_duplicate_modelines(nvDisplayPtr display);
@@ -61,7 +64,17 @@
 typedef struct GridConfigRec {
     int rows;
     int columns;
-}GridConfig;
+    Bool valid; // Is this layout valid
+
+} GridConfig;
+
+typedef struct DpyLocRec { // Display Location
+    int x;
+    int y;
+
+} DpyLoc;
+
+
 
 /** 
  * The gridConfigs array enumerates the display grid configurations
@@ -69,16 +82,18 @@
  *
  **/
 
-static const GridConfig gridConfigs[] = {
-    {2, 2},
-    {3, 1},
-    {3, 2},
-    {1, 3},
-    {2, 1},
-    {1, 2},
-    {4, 1},
-    {1, 4},
-    {0, 0}
+static GridConfig gridConfigs[] = {
+    {2, 2, FALSE}, // rows, columns, valid
+    {2, 3, FALSE},
+    {2, 4, FALSE},
+    {3, 1, FALSE},
+    {3, 2, FALSE},
+    {1, 3, FALSE},
+    {2, 1, FALSE},
+    {1, 2, FALSE},
+    {4, 1, FALSE},
+    {1, 4, FALSE},
+    {0, 0, FALSE}
 };
 
 GType ctk_slimm_get_type()
@@ -106,106 +121,82 @@
     return ctk_slimm_type;
 }
 
-static void remove_slimm_options(CtkSLIMM *ctk_object)
-{
-    XConfigPtr configptr = NULL;
-    gchar *filename;
-    gchar *msg;
-
-    filename = (gchar *)xconfigOpenConfigFile(NULL, NULL);
- 
-    if (!filename) {
-        msg = g_strdup_printf("Failed to open X config file!");
-        ctk_display_warning_msg(ctk_get_parent_window(GTK_WIDGET(ctk_object)),
-                                msg);
-        g_free(msg);
-        xconfigCloseConfigFile();
-        return;
-    }
-
-    if (xconfigReadConfigFile(&configptr) != XCONFIG_RETURN_SUCCESS) {
-        msg = g_strdup_printf("Failed to read X config file '%s'!",
-                                     filename);
-        ctk_display_warning_msg(ctk_get_parent_window(GTK_WIDGET(ctk_object)),
-                                msg);
-        g_free(msg);
-        xconfigCloseConfigFile();
-        return;
-    }
-
+static void remove_slimm_options(XConfigPtr xconf)
+{
     /* Remove SLI Mosaic Option */
-    xconfigRemoveNamedOption(&configptr->layouts->adjacencies->screen->options,
+    xconfigRemoveNamedOption(&xconf->layouts->adjacencies->screen->options,
                              "SLI", NULL);
 
     /* Remove MetaMode Option */
-    xconfigRemoveNamedOption(&configptr->layouts->adjacencies->screen->options,
+    xconfigRemoveNamedOption(&xconf->layouts->adjacencies->screen->options,
                              "MetaModes", NULL);
-
-    xconfigWriteConfigFile(filename, configptr);
-    xconfigFreeConfig(&configptr);
-    xconfigCloseConfigFile();
-}
-
-static void write_slimm_options(CtkSLIMM *ctk_object, gchar *metamode_str)
-{
-    XConfigPtr configptr = NULL;
+}
+
+
+
+/* get_ith_valid_grid_config()
+ * Returns valid grid configuration from gridConfig list.
+ */
+
+static GridConfig *get_ith_valid_grid_config(int idx)
+{
+    int i, count = 0;
+    for (i = 0; gridConfigs[i].rows; i++) {
+        if (!gridConfigs[i].valid) continue;
+        if (count == idx) return &gridConfigs[i];
+        count++;
+    }
+    return NULL;
+} /* get_ith_valid_grid_config() */
+
+
+
+static void add_slimm_options(XConfigPtr xconf, gchar *metamode_str)
+{
     XConfigAdjacencyPtr adj;
-    gchar *filename = "/etc/X11/xorg.conf";
-    char *tmp_filename;
-
-    if (!metamode_str) {
-        return;
-    }
-
-
-    tmp_filename = (char *)xconfigOpenConfigFile(filename, NULL);
-    if (!tmp_filename || strcmp(tmp_filename, filename)) {
-        gchar *msg = g_strdup_printf("Failed to open X config file '%s'!",
-                                     filename);
-        ctk_display_warning_msg(ctk_get_parent_window(GTK_WIDGET(ctk_object)), msg);
-        g_free(msg);
-        xconfigCloseConfigFile();
-        return;
-    }
-
-    if (xconfigReadConfigFile(&configptr) != XCONFIG_RETURN_SUCCESS) {
-        gchar *msg = g_strdup_printf("Failed to read X config file '%s'!",
-                                     filename);
-        ctk_display_warning_msg(ctk_get_parent_window(GTK_WIDGET(ctk_object)), msg);
-        g_free(msg);
-        xconfigCloseConfigFile();
-        return;
-    }
-
-    /* Remove all but the first adjacency from the layout */
-    while ((adj = configptr->layouts->adjacencies->next) != NULL) {
-        xconfigRemoveListItem((GenericListPtr *)(&configptr->layouts->adjacencies),
-                              (GenericListPtr)adj);
+    XConfigScreenPtr screen;
+
+    /* Make sure there is only one screen specified in the main layout */
+    adj = xconf->layouts->adjacencies;
+    while (adj->next) {
+        xconfigRemoveListItem((GenericListPtr *)(&adj),
+                              (GenericListPtr)adj->next);
     }
 
     /* 
-     * Now fix up the screen in Device section (to prevent failure with
+     * Now fix up the screen in the Device section (to prevent failure with
      * seperate x screen config
      *
-    */
-    configptr->layouts->adjacencies->screen->device->screen = -1;
+     */
+    xconf->layouts->adjacencies->screen->device->screen = -1;
 
     /* Write out SLI Mosaic Option */
-    xconfigAddNewOption(&configptr->layouts->adjacencies->screen->options, 
+    xconfigAddNewOption(&(xconf->layouts->adjacencies->screen->options),
                         "SLI", "Mosaic");
 
     /* Write out MetaMode Option */
-    xconfigAddNewOption(&configptr->layouts->adjacencies->screen->options, 
+    xconfigAddNewOption(&(xconf->layouts->adjacencies->screen->options),
                         "MetaModes", metamode_str);
 
-    xconfigWriteConfigFile(tmp_filename, configptr);
-    xconfigFreeConfig(&configptr);
-    xconfigCloseConfigFile();
-}
-
-static void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data)
-{
-    CtkSLIMM *ctk_object = CTK_SLIMM(user_data); 
+    /* Remove Virtual size specification */
+    for (screen = xconf->layouts->adjacencies->screen; screen;
+         screen = screen->next) {
+        if ((screen->displays->virtualX) || (screen->displays->virtualY)) {
+            screen->displays->virtualX = 0;
+            screen->displays->virtualY = 0;
+        }
+    }
+}
+
+
+
+static XConfigPtr xconfig_generate(XConfigPtr xconfCur,
+                                   Bool merge,
+                                   Bool *merged,
+                                   void *callback_data)
+{
+    CtkSLIMM *ctk_object = (CtkSLIMM *)callback_data;
+
     gint idx;
 
     gint xctr,yctr;
@@ -221,15 +212,28 @@
     gint checkbox_state = 
         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctk_object->cbtn_slimm_enable));
 
+
+    /* Make sure we're being asked to merge */
+    if (!xconfCur || !merge) {
+        *merged = FALSE;
+        return NULL;
+    }
+
+
     if (checkbox_state) {
+        GridConfig *grid_config;
         /* SLI MM needs to be enabled */
         idx = gtk_option_menu_get_history(GTK_OPTION_MENU(ctk_object->mnu_display_config));
 
         /* Get grid configuration values from index */
-    
-        x_displays = gridConfigs[idx].columns;
-        y_displays = gridConfigs[idx].rows;
-
+
+        grid_config = get_ith_valid_grid_config(idx);
+        if (grid_config) {
+            x_displays = grid_config->columns;
+            y_displays = grid_config->rows;
+        } else {
+            x_displays = y_displays = 0;
+        }
 
         h_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_hedge_overlap));
         v_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_vedge_overlap));
@@ -257,13 +261,112 @@
             }
         }
 
-        write_slimm_options(ctk_object, metamode_str);
+        add_slimm_options(xconfCur, metamode_str);
     } else {
         /* SLI MM needs to be disabled */
 
-        remove_slimm_options(ctk_object);
-    }
-}
+        remove_slimm_options(xconfCur);
+    }
+
+    *merged = TRUE;
+
+    return xconfCur;
+}
+
+
+
+static Bool compute_screen_size(CtkSLIMM *ctk_object, gint *width,
+                                gint *height)
+{
+    gint config_idx;
+    GridConfig *grid_config;
+    gint x_displays,y_displays;
+    gint h_overlap, v_overlap;
+
+
+    if (!ctk_object->cur_modeline) {
+        return FALSE;
+    }
+
+    config_idx = gtk_option_menu_get_history(GTK_OPTION_MENU(ctk_object->mnu_display_config));
+
+    /* Get grid configuration values from index */
+    grid_config = get_ith_valid_grid_config(config_idx);
+    if (grid_config) {
+        x_displays = grid_config->columns;
+        y_displays = grid_config->rows;
+    } else {
+        x_displays = y_displays = 0;
+    }
+    
+    gtk_widget_set_sensitive(ctk_object->spbtn_hedge_overlap,
+                             x_displays > 1 ? True : False);
+    gtk_widget_set_sensitive(ctk_object->spbtn_vedge_overlap,
+                             y_displays > 1 ? True : False);
+
+    h_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_hedge_overlap));
+    v_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_vedge_overlap));
+
+    /* Total X Screen Size Calculation */
+    *width = x_displays * ctk_object->cur_modeline->data.hdisplay - 
+        (x_displays - 1) * h_overlap;
+    *height = y_displays * ctk_object->cur_modeline->data.vdisplay - 
+        (y_displays - 1) * v_overlap;
+
+    return TRUE;
+}
+
+
+
+static void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data)
+{
+    CtkSLIMM *ctk_object = CTK_SLIMM(user_data); 
+    gint width, height;
+    Bool error = FALSE;
+    gchar *err_msg = NULL;
+
+
+    /* Make sure the screen size is acceptable */
+    if (!compute_screen_size(ctk_object, &width, &height)) {
+        error = TRUE;
+        err_msg = g_strdup("Unknown screen size!");
+
+    } else if ((width > ctk_object->max_screen_width) ||
+               (height > ctk_object->max_screen_height)) {
+        error = TRUE;
+        err_msg = g_strdup_printf("The configured X screen size of %dx%d is \n"
+                                  "too large.  The maximum supported size is\n"
+                                  "%dx%d.",
+                                  width, height,
+                                  ctk_object->max_screen_width,
+                                  ctk_object->max_screen_height);
+    }
+
+    if (error) {
+        GtkWidget *dlg;
+        GtkWidget *parent;
+
+        parent = ctk_get_parent_window(GTK_WIDGET(ctk_object));
+
+        dlg = gtk_message_dialog_new
+            (GTK_WINDOW(parent),
+             GTK_DIALOG_DESTROY_WITH_PARENT,
+             GTK_MESSAGE_WARNING,
+             GTK_BUTTONS_OK,
+             err_msg);
+            
+        gtk_dialog_run(GTK_DIALOG(dlg));
+        gtk_widget_destroy(dlg);
+        g_free(err_msg);
+        return;
+    }
+
+
+    /* Run the save dialog */
+    run_save_xconfig_dialog(ctk_object->save_xconfig_dlg);
+}
+
+
 
 static void txt_overlap_activated(GtkWidget *widget, gpointer user_data)
 {
@@ -372,40 +475,20 @@
 
 static void setup_total_size_label(CtkSLIMM *ctk_object)
 {
-    gint idx;
-    gint x_displays,y_displays;
-    gint h_overlap, v_overlap;
+    gint width, height;
     gchar *xscreen_size;
-    gint x_total, y_total;
-    if (!ctk_object->cur_modeline) {
+
+
+    if (!compute_screen_size(ctk_object, &width, &height)) {
         return;
     }
 
-    idx = gtk_option_menu_get_history(GTK_OPTION_MENU(ctk_object->mnu_display_config));
-
-    /* Get grid configuration values from index */
-    x_displays = gridConfigs[idx].columns;
-    y_displays = gridConfigs[idx].rows;
-
-    gtk_widget_set_sensitive(ctk_object->spbtn_hedge_overlap,
-                             x_displays > 1 ? True : False);
-    gtk_widget_set_sensitive(ctk_object->spbtn_vedge_overlap,
-                             y_displays > 1 ? True : False);
-
-    h_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_hedge_overlap));
-    v_overlap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctk_object->spbtn_vedge_overlap));
-
-    /* Total X Screen Size Calculation */
-    x_total = x_displays * ctk_object->cur_modeline->data.hdisplay - 
-              (x_displays - 1) * h_overlap;
-    y_total = y_displays * ctk_object->cur_modeline->data.vdisplay - 
-              (y_displays - 1) * v_overlap;
-
-    xscreen_size = g_strdup_printf("%d x %d", x_total, y_total);
+    xscreen_size = g_strdup_printf("%d x %d", width, height);
     gtk_label_set_text(GTK_LABEL(ctk_object->lbl_total_size), xscreen_size);
     g_free(xscreen_size);
-
-}
+}
+
+
 
 /** setup_display_refresh_dropdown() *********************************
  *
@@ -694,7 +777,323 @@
         (GTK_OPTION_MENU(ctk_object->mnu_display_resolution));
 
     gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, False);
+
 } /* setup_display_resolution_dropdown() */
+
+
+
+// Adds the value to the array if it does not already exist
+static Bool add_array_value(int array[][2], int max_len, int *cur_len, int val)
+{
+    int i;
+
+    /* Find the value */
+    for (i = 0; i < *cur_len; i++) {
+        if (array[i][0] == val) {
+            array[i][1]++;
+            return TRUE;
+        }
+    }
+
+    /* Add the value */
+    if (*cur_len < max_len) {
+        array[*cur_len][0] = val;
+        array[*cur_len][1] = 1;
+        (*cur_len)++;
+        return TRUE;
+    }
+
+    /* Value not found and array is full */
+    return FALSE;
+}
+
+static Bool parse_slimm_layout(CtkSLIMM *ctk_slimm,
+                               nvLayoutPtr layout,
+                               int *hoverlap,
+                               int *voverlap,
+                               int *grid_config_id)
+{
+    ReturnStatus ret;
+    char *metamode_str = NULL;
+    char *str;
+    const char *mode_str;
+    const char *tmp;
+    char *mode_name = NULL;
+    gchar *err_msg = NULL;
+
+    static DpyLoc *locs = NULL;  // Location of displays
+    static int max_locs = 0; // Maximum number of supported displays basically
+    static int max_rows = 0;
+    static int max_cols = 0;
+    int loc_idx;
+    int num_locs;
+    int rows;
+    int cols;
+
+    int found;
+    nvModeLinePtr *cur_modeline; // Used to assign the current modeline
+    
+    nvDisplayPtr display = find_active_display(layout);
+    if (display == NULL) {
+        err_msg = "Active display not found.";
+        goto fail;
+    }
+
+    /* Point at the display's current modeline so we can patch it */
+    cur_modeline = &(display->cur_mode->modeline);
+    *cur_modeline = NULL;
+
+
+    /* Make space for the display location array */
+    if (!locs) {
+        for (loc_idx = 0; gridConfigs[loc_idx].rows; loc_idx++ ) {
+            if ( max_rows < gridConfigs[loc_idx].rows) {
+                max_rows = gridConfigs[loc_idx].rows;
+            }
+            if ( max_cols < gridConfigs[loc_idx].columns) {
+                max_cols = gridConfigs[loc_idx].columns;
+            }
+            if (max_locs < 
+                (gridConfigs[loc_idx].rows * gridConfigs[loc_idx].columns)) {
+                max_locs =
+                    gridConfigs[loc_idx].rows * gridConfigs[loc_idx].columns;
+            }
+        }
+        locs = (DpyLoc *)malloc(max_locs * sizeof(DpyLoc));
+        if (!locs) {
+            err_msg = "Out of memory.";
+            goto fail;
+        }
+    }
+
+
+    /* Get the current metamode string */
+    ret = NvCtrlGetStringAttribute(ctk_slimm->handle,
+                                   NV_CTRL_STRING_CURRENT_METAMODE,
+                                   &metamode_str);
+    if ((ret != NvCtrlSuccess) || !metamode_str) {
+        err_msg = "Error querying current MetaMode.";
+        goto fail;
+    }
+
+
+    /* Point to the start of the metamodes, skipping any tokens */
+    str = strstr(metamode_str, "::");
+    if (str) {
+        str += 2;
+    } else {
+        str = metamode_str;
+    }
+
+    /* Parse each metamode */
+    num_locs = 0;
+    mode_str = strtok(str, ",");
+    while (mode_str) {
+
+        /* Parse each mode */
+        mode_str = parse_skip_whitespace(mode_str);
+
+
+        /* Skip the display name */
+        tmp = strstr(mode_str, ":");
+        if (tmp) tmp++;
+        tmp = parse_skip_whitespace(tmp);
+
+
+        /* Read the mode name */
+        tmp = parse_read_name(tmp, &mode_name, 0);
+        if (!tmp || !mode_name) {
+            err_msg = "Failed to parse mode name from MetaMode.";
+            goto fail;
+        }
+
+        if (!(*cur_modeline)) {
+            /* Match the mode name to one of the modelines */
+            *cur_modeline = display->modelines;
+            while (*cur_modeline) {
+                if (!strcmp(mode_name, (*cur_modeline)->data.identifier)) {
+                    break;
+                }
+                *cur_modeline = (*cur_modeline)->next;
+            }
+        } else if (strcmp(mode_name, (*cur_modeline)->data.identifier)) {
+            /* Modes don't all have the same mode name */
+            free(mode_name);
+            err_msg = "MetaMode using mismatched modes.";
+            goto fail;
+        }
+        free(mode_name);
+
+
+        /* Read mode for position information */
+        found = 0;
+        while (*tmp && !found) {
+            if (*tmp == '+') {
+                if (num_locs >= max_locs) {
+                    /* Too many displays, not supported */
+                    err_msg = "Too many displays in MetaMode.";
+                    goto fail;
+                }
+                tmp++;
+                tmp = parse_read_integer_pair(tmp, 0,
+                                              &(locs[num_locs].x),
+                                              &(locs[num_locs].y));
+                num_locs++;
+                found = 1;
+            } else {
+                tmp++;
+            }
+
+            /* Catch errors */
+            if (!tmp) {
+                err_msg = "Failed to parse location information from "
+                    "MetaMode.";
+                goto fail;
+            }
+        }
+
+        /* Assume 0,0 positioning if position info not found */
+        if (!found) {
+            if (num_locs >= max_locs) {
+                /* Too many displays, not supported */
+                err_msg = "Too many displays in MetaMode.";
+                goto fail;
+            }
+            tmp++;
+            tmp = parse_read_integer_pair(tmp, 0,
+                                          &(locs[num_locs].x),
+                                          &(locs[num_locs].y));
+            num_locs++;
+        }
+ 
+        /* Parse next mode */
+        mode_str = strtok(NULL, ",");
+    }
+
+
+    /* Make sure we were able to find the current modeline */
+    if ( !(*cur_modeline)) {
+        err_msg = "Unable to identify current resolution and refresh rate.";
+        goto fail;
+    }
+
+
+    // Now that we've parsed all the points, count the number of rows/cols.
+    {
+        int row_loc[max_rows][2]; // As position, count
+        int col_loc[max_cols][2]; // As position, count
+        int i;
+        int found;
+
+        rows = 0;
+        cols = 0;
+
+        for (loc_idx = 0; loc_idx < num_locs; loc_idx++) {
+            if (!add_array_value(row_loc, max_rows, &rows,
+                                 locs[loc_idx].y)) {
+                err_msg = "Too many rows.";
+                goto fail;
+            }
+            if (!add_array_value(col_loc, max_cols, &cols,
+                                 locs[loc_idx].x)) {
+                err_msg = "Too many columns.";
+                goto fail;
+            }
+        }
+
+        /* Make sure that each row has the same number of columns,
+         *  and that each column has the same number of rows
+         */
+        for (i = 0; i < rows; i++) {
+            if (row_loc[i][1] != cols) {
+                err_msg = "Rows have varying number of columns.";
+                goto fail;
+            }
+        }
+        for (i = 0; i < cols; i++) {
+            if (col_loc[i][1] != rows) {
+                err_msg = "Columns have varying number of rows.";
+                goto fail;
+            }
+        }
+        
+        /* Make sure this is a known/supported grid config */
+        found = 0;
+        for (i = 0; gridConfigs[i].rows; i++) {
+            if ((gridConfigs[i].rows == rows) &&
+                (gridConfigs[i].columns == cols)) {
+                *grid_config_id = i;
+                found = 1;
+                break;
+            }
+        }
+        if (!found) {
+            err_msg = "Unknown grid configuration.";
+            return FALSE;
+        }
+
+
+        /* Calculate row overlap */
+        *voverlap = 0;
+        found = 0;
+        if (rows > 1) {
+            int loc = row_loc[0][0];
+            int best_dist = 0; // Best overlap distance
+            for (i = 1; i < rows; i++) {
+                int overlap = (row_loc[i][0] - loc);
+                int dist = (overlap >= 0) ? overlap : -overlap;
+                if (!found || dist < best_dist) {
+                    best_dist = dist;
+                    *voverlap = overlap;
+                    found = 1;
+                }
+            }
+        }
+        if (*voverlap > 0) { *voverlap = (*cur_modeline)->data.vdisplay - *voverlap; }
+        if (*voverlap < 0) { *voverlap += (*cur_modeline)->data.vdisplay; }
+
+
+        /* Calculte column overlap */
+        *hoverlap = 0;
+        found = 0;
+        if (cols > 1) {
+            int loc = col_loc[0][0];
+            int best_dist = 0; // Best overlap distance
+            for (i = 1; i < cols; i++) {
+                int overlap = (col_loc[i][0] - loc);
+                int dist = (overlap >= 0) ? overlap : -overlap;
+                if (!found || dist < best_dist) {
+                    best_dist = dist;
+                    *hoverlap = overlap;
+                    found = 1;
+                }
+            }
+        }
+        if (*hoverlap > 0) { *hoverlap = (*cur_modeline)->data.hdisplay - *hoverlap; }
+        if (*hoverlap < 0) { *hoverlap += (*cur_modeline)->data.hdisplay; }
+    }
+    
+    XFree(metamode_str);
+    return TRUE;
+
+
+ fail:
+    *hoverlap = 0;
+    *voverlap = 0;
+    *grid_config_id = 0;
+    
+    if (err_msg) {
+        nv_warning_msg("Unable to determine current SLI Mosaic Mode "
+                       "configuration (will fall back to default): %s\n",
+                       err_msg);
+    }
+
+    if (metamode_str) {
+        XFree(metamode_str);
+    }
+
+    return FALSE;
+}
 
 
 
@@ -709,7 +1108,7 @@
     /* Remove nvidia-auto-select modeline first */
     if (IS_NVIDIA_DEFAULT_MODE(m)) {
         display->modelines = m->next;
-        if(m == display->cur_mode->modeline) {
+        if (m == display->cur_mode->modeline) {
             display->cur_mode->modeline = m->next;
         }
         modeline_free(m);
@@ -817,6 +1216,7 @@
     }
 
     remove_duplicate_modelines(display);
+
     return display;
 }
 
@@ -842,11 +1242,20 @@
     gchar *tmp;
     gchar *sli_mode = NULL;
     ReturnStatus ret;
+    gint val;
 
     nvLayoutPtr layout;
     nvDisplayPtr display;
 
     int iter;
+    int grid_menu_selected_id;
+    int count;
+
+    Bool valid_layout = FALSE;
+
+    int hoverlap = 0;
+    int voverlap = 0;
+    int grid_config_id = 0;
 
     /* now, create the object */
     
@@ -858,6 +1267,30 @@
     ctk_slimm->handle = handle;
     ctk_slimm->ctk_config = ctk_config;
     ctk_object = ctk_slimm;
+    
+    /* Check if this screen supports SLI Mosaic Mode */
+    ret = NvCtrlGetAttribute(ctk_object->handle,
+                             NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE, &val);
+    if ((ret == NvCtrlSuccess) && 
+        (val == NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_FALSE)) {
+        /* Mosaic not supported */
+        return NULL;
+    }
+
+    /* Query the maximum screen sizes */
+    ret = NvCtrlGetAttribute(ctk_object->handle,
+                             NV_CTRL_MAX_SCREEN_WIDTH,
+                             &ctk_slimm->max_screen_width);
+    if (ret != NvCtrlSuccess) {
+        return NULL;
+    }
+
+    ret = NvCtrlGetAttribute(ctk_object->handle,
+                             NV_CTRL_MAX_SCREEN_HEIGHT,
+                             &ctk_slimm->max_screen_height);
+    if (ret != NvCtrlSuccess) {
+        return NULL;
+    }
 
     /*
      * Create the display configuration widgets
@@ -866,6 +1299,52 @@
 
     /* Load the layout structure from the X server */
     layout = layout_load_from_server(handle, &err_str);
+
+    if (!err_str && layout) {
+        nvGpuPtr gpu;
+        int num_displays = 0;
+        int min_displays = 0;
+        GridConfig *grid;
+        int num_valid = 0;
+
+        for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+            num_displays += gpu->num_displays;
+        }
+
+        /* Mark configs that have enough displays as valid */
+        for (grid = gridConfigs; grid->rows; grid++) {
+            if (!min_displays ||
+                (min_displays > (grid->rows * grid->columns))) {
+                min_displays = grid->rows * grid->columns;
+            }
+            if (num_displays >= (grid->rows * grid->columns)) {
+                grid->valid = TRUE;
+                num_valid++;
+            }
+        }
+        
+        /* Make sure we have enough dislays for the minimum config */
+        if (num_valid <= 0) {
+            err_str = g_strdup_printf("Not enough display devices to "
+                                      "configure SLI Mosaic Mode.\nYou must "
+                                      "have at least %d Display%s connected, "
+                                      "but only %d Display%s detected.",
+                                      min_displays, 
+                                      (min_displays != 1) ? "s" : "",
+                                      num_displays, 
+                                      (num_displays != 1) ? "s were" : " was");
+            layout_free(layout);
+            layout = NULL;
+
+        } else {
+            valid_layout = parse_slimm_layout(ctk_slimm,
+                                              layout,
+                                              &hoverlap,
+                                              &voverlap,
+                                              &grid_config_id);
+        }
+    }
+    
 
     /* If we failed to load, tell the user why */
     if (err_str || !layout) {
@@ -919,10 +1398,14 @@
     }
     ctk_object->num_modelines = display->num_modelines;
 
+    /* XXX Since we've hijacked the layout's modelines,
+     *     we can stub out the layout's pointer and free it.
+     */
     display->modelines = NULL;
     display->cur_mode->modeline = NULL;
     display->num_modelines = 0;
     layout_free(layout);
+    layout = NULL;
 
     /* set container properties of the object */
 
@@ -962,18 +1445,29 @@
     ctk_slimm->mnu_display_config = optionmenu;
     menu = gtk_menu_new();
 
-    for (iter = 0; gridConfigs[iter].columns && gridConfigs[iter].rows; iter++) {        
+    grid_menu_selected_id = 0;
+    count = 0;
+    for (iter = 0; gridConfigs[iter].rows; iter++) {
+        /* Don't show invalid configs */
+        if (!gridConfigs[iter].valid) continue;
         tmp = g_strdup_printf("%d x %d grid",
-                              gridConfigs[iter].columns,
-                              gridConfigs[iter].rows);
+                              gridConfigs[iter].rows,
+                              gridConfigs[iter].columns);
 
         menuitem = gtk_menu_item_new_with_label(tmp);
         gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
         gtk_widget_show(menuitem);
+
+        /* Update grid_config_id to set menu history */
+        if (iter == grid_config_id) {
+            grid_menu_selected_id = count;
+        }
+        count++;
     }
 
     gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu), menu);
-    gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_slimm->mnu_display_config), 0);
+    gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_slimm->mnu_display_config),
+                                grid_menu_selected_id);
 
     g_signal_connect(G_OBJECT(ctk_object->mnu_display_config), "changed",
                      G_CALLBACK(display_config_changed),
@@ -997,7 +1491,7 @@
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
     gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
 
-    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, 
+    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL,
                      GTK_EXPAND | GTK_FILL, 0.5, 0.5);
 
     hbox = gtk_hbox_new(FALSE, 0);
@@ -1006,7 +1500,7 @@
     gtk_widget_show(hseparator);
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
     gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
-    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 
+    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL,
                      GTK_EXPAND | GTK_FILL, 0.5, 0.5);
 
 
@@ -1052,7 +1546,7 @@
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
     gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
 
-    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 8, 9, GTK_EXPAND | GTK_FILL, 
+    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 8, 9, GTK_EXPAND | GTK_FILL,
                      GTK_EXPAND | GTK_FILL, 0.5, 0.5);
 
     hbox = gtk_hbox_new(FALSE, 0);
@@ -1061,7 +1555,7 @@
     gtk_widget_show(hseparator);
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
     gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
-    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 8, 9, GTK_EXPAND | GTK_FILL, 
+    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 8, 9, GTK_EXPAND | GTK_FILL,
                      GTK_EXPAND | GTK_FILL, 0.5, 0.5);
 
 
@@ -1074,7 +1568,7 @@
                                                 1);
 
     ctk_slimm->spbtn_hedge_overlap = spinbutton;
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton), 0);
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton), hoverlap);
 
     g_signal_connect(G_OBJECT(ctk_object->spbtn_hedge_overlap), "value-changed",
                      G_CALLBACK(txt_overlap_activated),
@@ -1085,7 +1579,7 @@
     label = gtk_label_new("pixels");
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
 
-    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 9, 10, GTK_EXPAND | GTK_FILL, 
+    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 9, 10, GTK_EXPAND | GTK_FILL,
                      GTK_EXPAND | GTK_FILL, 0.5, 0.5);
 
 
@@ -1097,7 +1591,7 @@
                                                 ctk_object->cur_modeline->data.vdisplay, 
                                                 1);
     ctk_slimm->spbtn_vedge_overlap = spinbutton;
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton), 0);
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton), voverlap);
 
     g_signal_connect(G_OBJECT(ctk_object->spbtn_vedge_overlap), "value-changed",
                      G_CALLBACK(txt_overlap_activated),
@@ -1108,7 +1602,7 @@
     label = gtk_label_new("pixels");
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
 
-    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 10, 11, GTK_EXPAND | GTK_FILL, 
+    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 10, 11, GTK_EXPAND | GTK_FILL,
                      GTK_EXPAND | GTK_FILL, 0.5, 0.5);
 
     label = gtk_label_new("NULL");
@@ -1118,8 +1612,27 @@
     hbox = gtk_hbox_new(FALSE, 0);
     ctk_slimm->box_total_size = hbox;
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
-    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 9, 10, GTK_EXPAND | GTK_FILL, 
+    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 9, 10, GTK_EXPAND | GTK_FILL,
                      GTK_EXPAND | GTK_FILL, 0.5, 0.5);
+
+    hbox = gtk_hbox_new(FALSE, 0);
+    label = gtk_label_new("Maximum Size");
+    hseparator = gtk_hseparator_new();
+    gtk_widget_show(hseparator);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+    gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 10, 11, GTK_EXPAND | GTK_FILL,
+                     GTK_EXPAND | GTK_FILL, 0.5, 0.5);
+
+    tmp = g_strdup_printf("%dx%d", ctk_slimm->max_screen_width,
+                          ctk_slimm->max_screen_height);
+    label = gtk_label_new(tmp);
+    g_free(tmp);
+    hbox = gtk_hbox_new(FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
+    gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 11, 12, GTK_EXPAND | GTK_FILL,
+                     GTK_EXPAND | GTK_FILL, 0.5, 0.5);
+
 
     label = gtk_label_new("Save to X Configuration File");
     hbox = gtk_hbox_new(FALSE, 0);
@@ -1129,6 +1642,12 @@
                      G_CALLBACK(save_xconfig_button_clicked),
                      (gpointer) ctk_object);
 
+    ctk_slimm->save_xconfig_dlg =
+        create_save_xconfig_dialog(GTK_WIDGET(ctk_slimm),
+                                   FALSE, // Merge toggleable
+                                   xconfig_generate,
+                                   (void *)ctk_slimm);
+
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
     gtk_container_add(GTK_CONTAINER(button), hbox);
 
@@ -1139,6 +1658,7 @@
     ret = NvCtrlGetStringAttribute(ctk_slimm->handle,
                                    NV_CTRL_STRING_SLI_MODE,
                                    &sli_mode);
+
     if ((ret != NvCtrlSuccess) ||
         (ret == NvCtrlSuccess && g_ascii_strcasecmp(sli_mode, "Mosaic"))) {
         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), FALSE);

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkslimm.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkslimm.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkslimm.h (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkslimm.h Tue Jul 28 07:31:57 2009
@@ -31,6 +31,7 @@
 #include "ctkevent.h"
 #include "ctkdisplaylayout.h"
 #include "ctkconfig.h"
+#include "ctkdisplayconfig-utils.h"
 
 #include "XF86Config-parser/xf86Parser.h"
 
@@ -71,6 +72,7 @@
     GtkWidget *lbl_total_size;
     GtkWidget *box_total_size;
     GtkWidget *btn_save_config;
+    SaveXConfDlg *save_xconfig_dlg;
     GtkWidget *cbtn_slimm_enable;
     nvModeLinePtr *resolution_table;
     nvModeLinePtr *refresh_table;
@@ -80,6 +82,9 @@
     nvModeLinePtr modelines;
     nvModeLinePtr cur_modeline;
     gint num_modelines;
+
+    int max_screen_width;
+    int max_screen_height;
 };
 
 struct _CtkSLIMMClass

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkwindow.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkwindow.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkwindow.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkwindow.c Tue Jul 28 07:31:57 2009
@@ -398,6 +398,7 @@
     CtkConfig *ctk_config;
     
     gint column_offset, i;
+    gboolean slimm_page_added; /* XXX Kludge to only show one SLIMM page */
     
     /* create the new object */
 
@@ -597,6 +598,7 @@
 
     /* add the per-screen entries into the tree model */
 
+    slimm_page_added = FALSE;
     for (i = 0; i < h->targets[X_SCREEN_TARGET].n; i++) {
 
         gchar *screen_name;
@@ -633,11 +635,12 @@
                            CTK_WINDOW_CONFIG_FILE_ATTRIBUTES_FUNC_COLUMN,
                            NULL, -1);
 
-        if (h->targets[VCS_TARGET].n) {
+        if (h->targets[VCS_TARGET].n && !slimm_page_added) {
             /* SLI Mosaic Mode information */
 
             child = ctk_slimm_new(screen_handle, ctk_event, ctk_config);
             if (child) {
+                slimm_page_added = TRUE;
                 help = ctk_slimm_create_help(tag_table, "SLI Mosaic Mode Settings");
                 add_page(child, help, ctk_window, &iter, NULL,
                          "SLI Mosaic Mode Settings", NULL, NULL, NULL);

Modified: packages/nvidia-settings/trunk/src/gtk+-2.x/ctkxvideo.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/gtk%2B-2.x/ctkxvideo.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/gtk+-2.x/ctkxvideo.c (original)
+++ packages/nvidia-settings/trunk/src/gtk+-2.x/ctkxvideo.c Tue Jul 28 07:31:57 2009
@@ -1138,16 +1138,16 @@
         ctk_help_para(b, &i, __xv_texture_sync_to_vblank_help);
     }
     
+    if (ctk_xvideo->active_attributes & __XV_TEXTURE_BRIGHTNESS) {   
+        ctk_help_heading(b, &i, "Video Texture Brightness");
+        ctk_help_para(b, &i, __xv_texture_brightness_help);
+    }
+
     if (ctk_xvideo->active_attributes & __XV_TEXTURE_CONTRAST) {
         ctk_help_heading(b, &i, "Video Texture Contrast");
         ctk_help_para(b, &i, __xv_texture_contrast_help);
     }
     
-    if (ctk_xvideo->active_attributes & __XV_TEXTURE_BRIGHTNESS) {   
-        ctk_help_heading(b, &i, "Video Texture Brightness");
-        ctk_help_para(b, &i, __xv_texture_brightness_help);
-    }
-
     if (ctk_xvideo->active_attributes & __XV_TEXTURE_HUE) {
         ctk_help_heading(b, &i, "Video Texture Hue");
         ctk_help_para(b, &i, __xv_texture_hue_help);

Modified: packages/nvidia-settings/trunk/src/libXNVCtrl/NVCtrl.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/libXNVCtrl/NVCtrl.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/libXNVCtrl/NVCtrl.h (original)
+++ packages/nvidia-settings/trunk/src/libXNVCtrl/NVCtrl.h Tue Jul 28 07:31:57 2009
@@ -404,17 +404,27 @@
 
 /*
  * NV_CTRL_FRAMELOCK_SYNC_DELAY - delay between the frame lock pulse
- * and the GPU sync.  This is an 11 bit value which is multipled by
- * 7.81 to determine the sync delay in microseconds.
+ * and the GPU sync.  This value must be multiplied by 
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION to determine the sync delay in
+ * nanoseconds.
  *
  * This attribute may be queried through XNVCTRLQueryTargetAttribute()
  * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
  * target.
+ *
+ * USAGE NODE: NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX and
+ *             NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR are deprecated.
+ *             The Sync Delay _MAX and _FACTOR are different for different
+ *             GSync products and so, to be correct, the valid values for
+ *             NV_CTRL_FRAMELOCK_SYNC_DELAY must be queried to get the range
+ *             of acceptable sync delay values, and 
+ *             NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION must be queried to
+ *             obtain the correct factor.
  */
 
 #define NV_CTRL_FRAMELOCK_SYNC_DELAY                            24 /* RW-F */
-#define NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX                        2047
-#define NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR                     7.81
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX                        2047 // deprecated
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR                     7.81 // deprecated
 
 
 /*
@@ -2248,6 +2258,15 @@
 #define NV_CTRL_GVO_SYNC_TO_DISPLAY_ENABLE                      1
 
 /*
+ * NV_CTRL_X_SERVER_UNIQUE_ID - returns a pseudo-unique identifier for this
+ * X server. Intended for use in cases where an NV-CONTROL client communicates
+ * with multiple X servers, and wants some level of confidence that two
+ * X Display connections correspond to the same or different X servers.
+ */
+
+#define NV_CTRL_X_SERVER_UNIQUE_ID                              297 /* R--- */
+
+/*
  * NV_CTRL_PIXMAP_CACHE - This attribute controls whether the driver attempts to
  * store video memory pixmaps in a cache.  The cache speeds up allocation and
  * deallocation of pixmaps, but could use more memory than when the cache is
@@ -2291,12 +2310,43 @@
  * without clamping to [64-940].
  */
 
-#define NV_CTRL_GVO_FULL_RANGE_COLOR                            302 /* R-- */
+#define NV_CTRL_GVO_FULL_RANGE_COLOR                            302 /* RW- */
 #define NV_CTRL_GVO_FULL_RANGE_COLOR_DISABLED                     0
 #define NV_CTRL_GVO_FULL_RANGE_COLOR_ENABLED                      1
 
-#define NV_CTRL_LAST_ATTRIBUTE  NV_CTRL_GVO_FULL_RANGE_COLOR
-
+/*
+ * NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE - returns whether or not
+ * SLI Mosaic Mode supported.
+ */
+
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE                       303 /* R-- */
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_FALSE                   0
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_TRUE                    1
+
+/*
+ * NV_CTRL_GVO_ENABLE_RGB_DATA - Allows clients to specify when
+ * the GVO board should process colors as RGB when the output data
+ * format is one of the NV_CTRL_GVO_DATA_FORMAT_???_PASSTRHU modes.
+ */
+
+#define NV_CTRL_GVO_ENABLE_RGB_DATA                             304 /* RW- */
+#define NV_CTRL_GVO_ENABLE_RGB_DATA_DISABLE                       0
+#define NV_CTRL_GVO_ENABLE_RGB_DATA_ENABLE                        1
+
+/* 
+ * NV_CTRL_IMAGE_SHARPENING_DEFAULT - Returns default value of
+ * Image Sharpening.
+ */
+
+#define NV_CTRL_IMAGE_SHARPENING_DEFAULT                        305 /* R-- */
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION - Returns the number of nanoseconds
+ * that one unit of NV_CTRL_FRAMELOCK_SYNC_DELAY corresponds to.
+ */
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION                 318 /* R-- */
+
+#define NV_CTRL_LAST_ATTRIBUTE  NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION
 
 
 /**************************************************************************/

Modified: packages/nvidia-settings/trunk/src/libXNVCtrl/nv_control.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/libXNVCtrl/nv_control.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/libXNVCtrl/nv_control.h (original)
+++ packages/nvidia-settings/trunk/src/libXNVCtrl/nv_control.h Tue Jul 28 07:31:57 2009
@@ -19,6 +19,28 @@
  * 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.
+ *
+ *
+ * NV-CONTROL Protocol Version History
+ *
+ * 1.0 - 1.5   NVIDIA Internal development versions
+ * 1.6         Initial public version
+ * 1.7         Added QueryBinaryData request
+ * 1.8         Added TargetTypes
+ * 1.9         Added QueryTargetCount request
+ * 1.10        Fixed target type/id byte ordering for compatibility with
+ *             pre-1.8 NV-CONTROL clients
+ * 1.11        NVIDIA Internal development version
+ * 1.12        Added StringOperation request
+ * 1.13        NVIDIA Internal development version
+ * 1.14        Fixed an NV_CTRL_BINARY_DATA_MODELINES double scan modeline
+ *             reporting bug (vsyncstart, vsyncend, and vtotal were incorrectly
+ *             doubled)
+ * 1.15        Added AVAILABILITY_TARGET_ATTRIBUTE_CHANGED_EVENT
+ * 1.16        Added TARGET_STRING_ATTRIBUTE_CHANGED_EVENT
+ * 1.17        Added TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT
+ * 1.18        Updated QueryTargetCount to return a count of 0, rather than
+ *             BadMatch, if an unknown TargetType is specified
  */
 
 #ifndef __NVCONTROL_H
@@ -29,7 +51,7 @@
 #define NV_CONTROL_NAME "NV-CONTROL"
 
 #define NV_CONTROL_MAJOR 1
-#define NV_CONTROL_MINOR 17
+#define NV_CONTROL_MINOR 18
 
 #define X_nvCtrlQueryExtension                      0
 #define X_nvCtrlIsNv                                1

Modified: packages/nvidia-settings/trunk/src/parse.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/parse.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/parse.c (original)
+++ packages/nvidia-settings/trunk/src/parse.c Tue Jul 28 07:31:57 2009
@@ -107,6 +107,7 @@
     { "NotebookInternalLCD",           NV_CTRL_NOTEBOOK_INTERNAL_LCD,             N|D,   "Returns the display device mask of the internal LCD of a notebook." },
     { "Depth30Allowed",                NV_CTRL_DEPTH_30_ALLOWED,                  N,     "Returns whether the NVIDIA X driver supports depth 30 on the specified X screen or GPU." },
     { "NoScanout",                     NV_CTRL_NO_SCANOUT,                        N,     "Returns whether the special \"NoScanout\" mode is enabled on the specified X screen or GPU." },
+    { "XServerUniqueId",               NV_CTRL_X_SERVER_UNIQUE_ID,                N,     "Returns a pseudo-unique identification number for the X server." },
     { "PixmapCache",                   NV_CTRL_PIXMAP_CACHE,                      N,     "Controls whether pixmaps are allocated in a cache." },
     { "PixmapCacheRoundSizeKB",        NV_CTRL_PIXMAP_CACHE_ROUNDING_SIZE_KB,     N,     "Controls the number of kilobytes to add to the pixmap cache when there is not enough room." },
 
@@ -129,6 +130,7 @@
     { "GammaCorrectedAALinesValue", NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE,       0,   "Returns the gamma value used by OpenGL when gamma-corrected antialiased lines are enabled." },
     { "StereoEyesExchange",         NV_CTRL_STEREO_EYES_EXCHANGE,             0,   "Swaps the left and right eyes of stereo images." },
     { "SLIMode",                    NV_CTRL_STRING_SLI_MODE,                  S|N, "Returns a string describing the current SLI mode, if any." },
+    { "SliMosaicModeAvailable",     NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE,        N,   "Returns whether or not SLI Mosaic Mode is supported." },
 
     /* GPU */
     { "BusType",                NV_CTRL_BUS_TYPE,                      0,   "Returns the type of bus connecting the GPU driving the specified X screen to the computer." },
@@ -177,6 +179,7 @@
     { "FrameLockSlaveable",    NV_CTRL_FRAMELOCK_SLAVEABLE,         N|F|G|D, "Returns whether the display device(s) can be set as slave(s) of the frame lock group." },
     { "FrameLockFPGARevision", NV_CTRL_FRAMELOCK_FPGA_REVISION,     N|F|G,   "Returns the FPGA revision of the Frame Lock device." },
     { "FrameLockSyncRate4",    NV_CTRL_FRAMELOCK_SYNC_RATE_4,       N|F|G,   "Returns the refresh rate that the frame lock board is sending to the GPU in 1/10000 Hz (i.e. to get the refresh rate in Hz, divide the returned value by 10000.)" },
+    { "FrameLockSyncDelayResolution", NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION, N|F|G, "Returns the number of nanoseconds that one unit of FrameLockSyncDelay corresponds to." },
 
     /* GVO */
     { "GvoSupported",                    NV_CTRL_GVO_SUPPORTED,                        I|N,   "Returns whether this X screen supports GVO; if this screen does not support GVO output, then all other GVO attributes are unavailable." },
@@ -211,6 +214,7 @@
     { "GvoSyncToDisplay",                NV_CTRL_GVO_SYNC_TO_DISPLAY,                  I|N,   "Controls synchronization of the non-SDI display to the SDI display when both are active." },
     { "GvoFullRangeColor",               NV_CTRL_GVO_FULL_RANGE_COLOR,                 I,     "Allow full range color data [4-1019].  If disabled, color data is clamped to [64-940]." },
     { "IsGvoDisplay",                    NV_CTRL_IS_GVO_DISPLAY,                       N|D,   "Returns whether or not the given display device is driven by the GVO device." },
+    { "GvoEnableRGBData",                NV_CTRL_GVO_ENABLE_RGB_DATA,                  I,     "Indicates that RGB data is being sent via a PASSTHU mode." },
 
     /* Display */
     { "Brightness",                 BRIGHTNESS_VALUE|ALL_CHANNELS,         N|C|G, "Controls the overall brightness of the display." },
@@ -227,7 +231,8 @@
     { "BlueGamma",                  GAMMA_VALUE|BLUE_CHANNEL,              C|G,   "Controls the gamma of the color blue in the display." },
     { "FlatpanelDithering",         NV_CTRL_FLATPANEL_DITHERING,           0,     "This is the current state of flat panel dithering.  (This attribute has been deprecated.)" },
     { "DigitalVibrance",            NV_CTRL_DIGITAL_VIBRANCE,              0,     "Sets the digital vibrance level of the display device." },
-    { "ImageSharpening",            NV_CTRL_IMAGE_SHARPENING,              0,     "Adjusts the sharpness of the display's image quality by amplifying high frequency content.  Valid values will normally be in the range [0,32).  Only available on GeForceFX or newer." },
+    { "ImageSharpening",            NV_CTRL_IMAGE_SHARPENING,              0,     "Adjusts the sharpness of the display's image quality by amplifying high frequency content." },
+    { "ImageSharpeningDefault",     NV_CTRL_IMAGE_SHARPENING_DEFAULT,      0,     "Returns default value of image sharpening." },
     { "FrontendResolution",         NV_CTRL_FRONTEND_RESOLUTION,           N|P,   "Returns the dimensions of the frontend (current) resolution as determined by the NVIDIA X Driver. This attribute is a packed integer; the width is packed in the upper 16 bits and the height is packed in the lower 16-bits." },
     { "BackendResolution",          NV_CTRL_BACKEND_RESOLUTION,            N|P,   "Returns the dimensions of the backend resolution as determined by the NVIDIA X Driver.  The backend resolution is the resolution (supported by the display device) the GPU is set to scale to.  If this resolution matches the frontend resolution, GPU scaling will not be needed/used.  This attribute is a packed integer; the width is packed in the upper 16-bits and the height is packed in the lower 16-bits." },
     { "FlatpanelNativeResolution",  NV_CTRL_FLATPANEL_NATIVE_RESOLUTION,   N|P,   "Returns the dimensions of the native resolution of the flat panel as determined by the NVIDIA X Driver.  The native resolution is the resolution at which a flat panel must display any image.  All other resolutions must be scaled to this resolution through GPU scaling or the DFP's native scaling capabilities in order to be displayed.  This attribute is only valid for flat panel (DFP) display devices.  This attribute is a packed integer; the width is packed in the upper 16-bits and the height is packed in the lower 16-bits." },
@@ -285,7 +290,7 @@
  * about.
  */
 
-#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GVO_FULL_RANGE_COLOR
+#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION
 #warning "Have you forgotten to add a new integer attribute to attributeTable?"
 #endif
 
@@ -303,28 +308,32 @@
       X_SCREEN_TARGET,               /* target_index */
       NV_CTRL_TARGET_TYPE_X_SCREEN,  /* nvctrl */
       ATTRIBUTE_TYPE_X_SCREEN,       /* permission_bit */
-      NV_TRUE },                     /* uses_display_devices */
+      NV_TRUE,                       /* uses_display_devices */
+      1, 6 },                        /* required major,minor protocol rev */
     
     { "GPU",                         /* name */
       "gpu",                         /* parsed_name */
       GPU_TARGET,                    /* target_index */
       NV_CTRL_TARGET_TYPE_GPU,       /* nvctrl */
       ATTRIBUTE_TYPE_GPU,            /* permission_bit */
-      NV_TRUE },                     /* uses_display_devices */
+      NV_TRUE,                       /* uses_display_devices */
+      1, 10 },                       /* required major,minor protocol rev */
     
     { "Frame Lock Device",           /* name */
       "framelock",                   /* parsed_name */
       FRAMELOCK_TARGET,              /* target_index */
       NV_CTRL_TARGET_TYPE_FRAMELOCK, /* nvctrl */
       ATTRIBUTE_TYPE_FRAMELOCK,      /* permission_bit */
-      NV_FALSE },                    /* uses_display_devices */
+      NV_FALSE,                      /* uses_display_devices */
+      1, 10 },                       /* required major,minor protocol rev */
 
     { "VCS",                         /* name */
       "vcs",                         /* parsed_name */
       VCS_TARGET,                    /* target_index */
       NV_CTRL_TARGET_TYPE_VCSC,      /* nvctrl */
       ATTRIBUTE_TYPE_VCSC,           /* permission_bit */
-      NV_FALSE },                    /* uses_display_devices */
+      NV_FALSE,                      /* uses_display_devices */
+      1, 12 },                       /* required major,minor protocol rev */
 
     { NULL, NULL, 0, 0, 0 },
 };
@@ -1087,12 +1096,16 @@
  * corresponds to the attribute constant.
  */
 
-char *nv_get_attribute_name(const int attr)
+const char *nv_get_attribute_name(const int attr, const int flagsMask,
+                                  const int flags)
 {
     int i;
 
     for (i = 0; attributeTable[i].name; i++) {
-        if (attributeTable[i].attr == attr) return attributeTable[i].name;
+        if (attributeTable[i].attr == attr &&
+            (attributeTable[i].flags & flagsMask) == (flags & flagsMask)) {
+            return attributeTable[i].name;
+        }
     }
 
     return NULL;

Modified: packages/nvidia-settings/trunk/src/parse.h
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/parse.h?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/parse.h (original)
+++ packages/nvidia-settings/trunk/src/parse.h Tue Jul 28 07:31:57 2009
@@ -167,6 +167,16 @@
     /* whether this target type is aware of display devices */
     int uses_display_devices;
     
+    /*
+     * the minimum NV-CONTROL Protocol version required to use this target
+     * type; note that all future target types should be able to use 1.18,
+     * since that version and later allows NV-CONTROL clients to query the
+     * count of TargetTypes not recognized by the X server
+     */
+
+    int major;
+    int minor;
+
 } TargetTypeEntry;
 
 
@@ -287,7 +297,8 @@
 void nv_parsed_attribute_free(ParsedAttribute *p);
 void nv_parsed_attribute_clean(ParsedAttribute *p);
 
-char *nv_get_attribute_name(const int attr);
+const char *nv_get_attribute_name(const int attr, const int flagsMask,
+                                  const int flags);
 
 char *nv_standardize_screen_name(const char *display_name, int screen);
 

Modified: packages/nvidia-settings/trunk/src/query-assign.c
URL: http://svn.debian.org/wsvn/pkg-nvidia/packages/nvidia-settings/trunk/src/query-assign.c?rev=574&op=diff
==============================================================================
--- packages/nvidia-settings/trunk/src/query-assign.c (original)
+++ packages/nvidia-settings/trunk/src/query-assign.c Tue Jul 28 07:31:57 2009
@@ -154,8 +154,33 @@
              */
             
             if (pQueryHandle) {
-                status = NvCtrlQueryTargetCount
-                    (pQueryHandle, targetTypeTable[j].nvctrl, &val);
+
+                /*
+                 * check that the NV-CONTROL protocol is new enough to
+                 * recognize this target type
+                 */
+
+                ReturnStatus ret1, ret2;
+                int major, minor;
+
+                ret1 = NvCtrlGetAttribute(pQueryHandle,
+                                          NV_CTRL_ATTR_NV_MAJOR_VERSION,
+                                          &major);
+                ret2 = NvCtrlGetAttribute(pQueryHandle,
+                                          NV_CTRL_ATTR_NV_MINOR_VERSION,
+                                          &minor);
+
+                if ((ret1 == NvCtrlSuccess) && (ret2 == NvCtrlSuccess) &&
+                    ((major > targetTypeTable[j].major) ||
+                     ((major == targetTypeTable[j].major) &&
+                      (minor >= targetTypeTable[j].minor)))) {
+
+                    status = NvCtrlQueryTargetCount
+                                (pQueryHandle, targetTypeTable[j].nvctrl,
+                                 &val);
+                } else {
+                    status = NvCtrlMissingExtension;
+                }
             } else {
                 status = NvCtrlMissingExtension;
             }
@@ -839,20 +864,21 @@
 {
     int bit;
 
-#define MORE_INDENT "      "
-
-    nv_msg(indent, "\nNames for valid '%s' values:\n", name);
+    nv_msg(indent, "\n");
+    nv_msg(indent, "Note to assign 'FSAA' on the commandline, you may also "
+           "need to assign\n");
+    nv_msg(indent, "'FSAAAppControlled' and 'FSAAAppEnhanced' to 0.\n");
+    nv_msg(indent, "\n");
+    nv_msg(indent, "Valid '%s' Values\n", name);
+    nv_msg(indent, "  value - description\n");
 
     for (bit = 0; bit < 32; bit++) {
         /* FSAA is not a packed attribute */
         if (valid_fsaa_modes & (1 << bit)) {
-            nv_msg(MORE_INDENT, "%2u - %s\n", 
+            nv_msg(indent, "   %2u   -   %s\n", 
                    bit, NvCtrlGetMultisampleModeName(bit));
         }
     }
-
-#undef MORE_INDENT
-
 }
 
 




More information about the Pkg-nvidia-devel mailing list