summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2009-03-13 17:22:43 -0700
committerAaron Plattner <aplattner@nvidia.com>2009-03-13 17:22:43 -0700
commitd36e8bac95985a6aeee9e923a03949285ebfa513 (patch)
tree6d289f50292ecbd51bc41c69b72098de1f732644
parentbff3a55890967cb405e751de91b55cd45bd3fd3c (diff)
185.13185.13
-rw-r--r--src/gtk+-2.x/ctkconfig.c2
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig-utils.c755
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig-utils.h44
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig.c844
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig.h16
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice-dfp.c12
-rw-r--r--src/gtk+-2.x/ctkdisplaylayout.h3
-rw-r--r--src/gtk+-2.x/ctkevent.c5
-rw-r--r--src/gtk+-2.x/ctkframelock.c102
-rw-r--r--src/gtk+-2.x/ctkglx.c34
-rw-r--r--src/gtk+-2.x/ctkgpu.c37
-rw-r--r--src/gtk+-2.x/ctkimagesliders.c15
-rw-r--r--src/gtk+-2.x/ctkimagesliders.h1
-rw-r--r--src/gtk+-2.x/ctkmultisample.c5
-rw-r--r--src/gtk+-2.x/ctkpowermizer.c6
-rw-r--r--src/gtk+-2.x/ctkserver.c21
-rw-r--r--src/gtk+-2.x/ctkslimm.c633
-rw-r--r--src/gtk+-2.x/ctkslimm.h2
-rw-r--r--src/gtk+-2.x/ctkxvideo.c10
-rw-r--r--src/libXNVCtrl/NVCtrl.h28
-rw-r--r--src/parse.c7
21 files changed, 1655 insertions, 927 deletions
diff --git a/src/gtk+-2.x/ctkconfig.c b/src/gtk+-2.x/ctkconfig.c
index 5cf3c45..441e93e 100644
--- a/src/gtk+-2.x/ctkconfig.c
+++ b/src/gtk+-2.x/ctkconfig.c
@@ -45,7 +45,7 @@ static const char *__tooltip_help =
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.";
diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.c b/src/gtk+-2.x/ctkdisplayconfig-utils.c
index 7e6914c..825d841 100644
--- a/src/gtk+-2.x/ctkdisplayconfig-utils.c
+++ b/src/gtk+-2.x/ctkdisplayconfig-utils.c
@@ -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 @@ nvScreenPtr layout_get_a_screen(nvLayoutPtr layout, nvGpuPtr preferred_gpu)
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() */
diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.h b/src/gtk+-2.x/ctkdisplayconfig-utils.h
index 8ede91c..205c2d2 100644
--- a/src/gtk+-2.x/ctkdisplayconfig-utils.h
+++ b/src/gtk+-2.x/ctkdisplayconfig-utils.h
@@ -27,6 +27,8 @@
#include <gtk/gtk.h>
+#include "XF86Config-parser/xf86Parser.h"
+
#include "ctkdisplaylayout.h"
@@ -101,6 +103,48 @@ nvScreenPtr layout_get_a_screen(nvLayoutPtr layout, nvGpuPtr preferred_gpu);
+
+/* 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
diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c
index 9403fe6..bd9fc42 100644
--- a/src/gtk+-2.x/ctkdisplayconfig.c
+++ b/src/gtk+-2.x/ctkdisplayconfig.c
@@ -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>
@@ -88,12 +81,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);
static void save_clicked(GtkWidget *widget, gpointer user_data);
@@ -102,14 +89,18 @@ static void advanced_clicked(GtkWidget *widget, gpointer user_data);
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);
+
+
/*** D E F I N I T I O N S ***************************************************/
@@ -209,17 +200,20 @@ static const char * __screen_depth_help =
"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 +543,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object,
nvScreenPtr screen,
gchar **pMetamode_strs)
{
+ nvLayoutPtr layout = screen->gpu->layout;
gchar *metamode_strs = NULL;
gchar *metamode_str;
gchar *tmp;
@@ -558,8 +553,8 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object,
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 +576,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object,
* 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 +597,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object,
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 +607,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object,
* 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 +1058,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
GtkWidget *frame;
GtkWidget *notebook;
GtkWidget *hbox;
- GtkWidget *hbox2;
GtkWidget *vbox;
GdkScreen *screen;
GtkWidget *label;
@@ -1114,8 +1108,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
ctk_object->notify_user_of_reset = TRUE;
ctk_object->ignore_reset_events = FALSE;
- ctk_object->advanced_mode = FALSE;
-
ctk_object->last_resolution_idx = -1;
/* Set container properties of the object & pack the banner */
@@ -1477,56 +1469,11 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
/* 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 +1810,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
(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 +1883,7 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
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 +1891,16 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
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 +1909,12 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
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 +1930,10 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
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 +2011,10 @@ static void setup_display_modename(CtkDisplayConfig *ctk_object)
{
nvDisplayPtr display = ctk_display_layout_get_selected_display
(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ nvLayoutPtr layout = ctk_object->layout;
- if (!display || !display->screen || !ctk_object->advanced_mode) {
+ if (!display || !display->screen || !layout->advanced_mode) {
gtk_widget_hide(ctk_object->box_display_modename);
return;
}
@@ -2190,6 +2087,7 @@ static void setup_display_refresh_dropdown(CtkDisplayConfig *ctk_object)
nvDisplayPtr display = ctk_display_layout_get_selected_display
(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ nvLayoutPtr layout = ctk_object->layout;
@@ -2290,14 +2188,14 @@ static void setup_display_refresh_dropdown(CtkDisplayConfig *ctk_object)
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;
}
@@ -2953,14 +2851,17 @@ static void setup_primary_display(CtkDisplayConfig *ctk_object)
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 +3014,12 @@ static void setup_screen_depth_dropdown(CtkDisplayConfig *ctk_object)
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 +3297,13 @@ static void setup_screen_position(CtkDisplayConfig *ctk_object)
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 +4676,7 @@ static gboolean do_query_remove_display(CtkDisplayConfig *ctk_object,
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 +4684,7 @@ void do_disable_display(CtkDisplayConfig *ctk_object, nvDisplayPtr display)
/* 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 +4962,7 @@ static void display_refresh_changed(GtkWidget *widget, gpointer user_data)
gint idx;
nvModeLinePtr modeline;
nvDisplayPtr display;
+ nvLayoutPtr layout = ctk_object->layout;
/* Get the modeline and display to set */
@@ -5065,7 +4975,7 @@ static void display_refresh_changed(GtkWidget *widget, gpointer user_data)
/* 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 +5014,7 @@ static void display_resolution_changed(GtkWidget *widget, gpointer user_data)
CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
gint idx;
gint last_idx;
+ nvLayoutPtr layout = ctk_object->layout;
nvModeLinePtr modeline;
nvDisplayPtr display;
@@ -5128,7 +5039,7 @@ static void display_resolution_changed(GtkWidget *widget, gpointer user_data)
/* 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 +6346,6 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data)
-/** 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 +7129,61 @@ static int generateXConfig(CtkDisplayConfig *ctk_object, XConfigPtr *pConfig)
-/*
- * 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)
+/** xconfig_generate() ***********************************************
*
- * 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.
+ * Callback to generate an X config structure based on the current
+ * display configuration.
*
**/
-
-static int save_xconfig_file(CtkDisplayConfig *ctk_object,
- gchar *filename, char *buf, mode_t mode)
+static XConfigPtr xconfig_generate(XConfigPtr xconfCur,
+ Bool merge,
+ Bool *merged,
+ void *callback_data)
{
- gchar *backup_filename = NULL;
- FILE *fp = NULL;
- size_t size;
- gchar *err_msg = NULL;
+ CtkDisplayConfig *ctk_object = (CtkDisplayConfig *)callback_data;
+ XConfigPtr xconfGen = NULL;
+ gint result;
- int ret = 0;
+ *merged = FALSE;
- if (!buf || !filename) goto done;
+ /* Generate an X config structure from our layout */
+ result = generateXConfig(ctk_object, &xconfGen);
+ if ((result != XCONFIG_GEN_OK) || !xconfGen) {
+ goto fail;
+ }
- size = strlen(buf) ;
+ /* If we're not merging, we're done */
+ if (!xconfCur || !merge) {
+ return xconfGen;
+ }
- /* Backup any existing file */
- if ((access(filename, F_OK) == 0)) {
+ /* 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);
+ return xconfGen;
+ }
- 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;
- }
- }
+ /* Merge worked */
+ xconfigFreeConfig(&xconfGen);
+ *merged = TRUE;
+ return xconfCur;
- /* 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;
+ fail:
+ if (xconfGen) {
+ xconfigFreeConfig(&xconfGen);
}
- 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);
- g_free(err_msg);
- }
+ return NULL;
- if (fp) fclose(fp);
- g_free(backup_filename);
- return ret;
-
-} /* save_xconfig_file() */
+} /* xconfig_generate() */
@@ -7746,13 +7196,6 @@ static int save_xconfig_file(CtkDisplayConfig *ctk_object,
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 +7203,8 @@ static void save_clicked(GtkWidget *widget, gpointer user_data)
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 +7219,24 @@ static void save_clicked(GtkWidget *widget, gpointer user_data)
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);
}
diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h
index 5155e36..32a41a0 100644
--- a/src/gtk+-2.x/ctkdisplayconfig.h
+++ b/src/gtk+-2.x/ctkdisplayconfig.h
@@ -28,6 +28,8 @@
#include "ctkevent.h"
#include "ctkconfig.h"
#include "ctkdisplaylayout.h"
+#include "ctkdisplayconfig-utils.h"
+
G_BEGIN_DECLS
@@ -158,18 +160,7 @@ typedef struct _CtkDisplayConfig
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 @@ typedef struct _CtkDisplayConfig
GtkWidget *btn_probe;
GtkWidget *btn_advanced;
- gboolean advanced_mode; /* True if we are in advanced mode */
GtkWidget *btn_reset;
diff --git a/src/gtk+-2.x/ctkdisplaydevice-dfp.c b/src/gtk+-2.x/ctkdisplaydevice-dfp.c
index 86c2a66..f5e1552 100644
--- a/src/gtk+-2.x/ctkdisplaydevice-dfp.c
+++ b/src/gtk+-2.x/ctkdisplaydevice-dfp.c
@@ -86,9 +86,9 @@ static const char *__scaling_help =
"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 @@ GtkTextBuffer *ctk_display_device_dfp_create_help(GtkTextTagTable *table,
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 @@ GtkTextBuffer *ctk_display_device_dfp_create_help(GtkTextTagTable *table,
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);
diff --git a/src/gtk+-2.x/ctkdisplaylayout.h b/src/gtk+-2.x/ctkdisplaylayout.h
index 95bb229..79d8894 100644
--- a/src/gtk+-2.x/ctkdisplaylayout.h
+++ b/src/gtk+-2.x/ctkdisplaylayout.h
@@ -312,6 +312,9 @@ typedef struct nvGpuRec {
typedef struct nvLayoutRec {
XConfigLayoutPtr conf_layout;
char *filename;
+ Bool advanced_mode; /* Allow advanced layout modifications: */
+ /* - panning */
+ /* - multiple (meta)modes */
NvCtrlAttributeHandle *handle;
diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c
index 0055e35..b406b88 100644
--- a/src/gtk+-2.x/ctkevent.c
+++ b/src/gtk+-2.x/ctkevent.c
@@ -261,12 +261,15 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
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);
#undef MAKE_SIGNAL
@@ -277,7 +280,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
* knows about.
*/
-#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GVO_ENABLE_RGB_DATA
+#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_IMAGE_SHARPENING_DEFAULT
#warning "There are attributes that do not emit signals!"
#endif
diff --git a/src/gtk+-2.x/ctkframelock.c b/src/gtk+-2.x/ctkframelock.c
index f7cad7c..27db08a 100644
--- a/src/gtk+-2.x/ctkframelock.c
+++ b/src/gtk+-2.x/ctkframelock.c
@@ -213,6 +213,7 @@ struct _nvGPUDataRec {
struct _nvFrameLockDataRec {
gpointer handle; /* NV-CONTROL Frame Lock Target */
+ int server_id;
/* Signal Handler IDs */
gulong signal_ids[NUM_FRAMELOCK_SIGNALS];
@@ -326,7 +327,7 @@ static const char * __client_checkbox_help =
-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 +2470,54 @@ static nvListEntryPtr find_server_by_name(nvListTreePtr tree,
+/** 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
@@ -5155,7 +5204,8 @@ static unsigned int add_gpu_devices(CtkFramelock *ctk_framelock,
*
*/
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;
@@ -5230,6 +5280,8 @@ static unsigned int add_framelock_devices(CtkFramelock *ctk_framelock,
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 +5342,7 @@ static gint add_devices(CtkFramelock *ctk_framelock,
{
gpointer handle = NULL;
Display *display;
+ int server_id = -1;
gint devices_added = 0;
char *server_name = NULL;
char *ptr;
@@ -5329,30 +5382,6 @@ static gint add_devices(CtkFramelock *ctk_framelock,
/* 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 +5417,28 @@ static gint add_devices(CtkFramelock *ctk_framelock,
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\" "
diff --git a/src/gtk+-2.x/ctkglx.c b/src/gtk+-2.x/ctkglx.c
index 7b3462f..1ef3c96 100644
--- a/src/gtk+-2.x/ctkglx.c
+++ b/src/gtk+-2.x/ctkglx.c
@@ -70,21 +70,21 @@ static const char * __db_help =
"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 @@ GtkTextBuffer *ctk_glx_create_help(GtkTextTagTable *table,
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 @@ GtkTextBuffer *ctk_glx_create_help(GtkTextTagTable *table,
"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.");
@@ -885,6 +906,7 @@ GtkTextBuffer *ctk_glx_create_help(GtkTextTagTable *table,
"\t%s\n\n"
"\t%s\n\n"
"\t%s\n\n"
+ "\t%s\n\n"
"\t%s\n\n"
"\t%s\n\n"
diff --git a/src/gtk+-2.x/ctkgpu.c b/src/gtk+-2.x/ctkgpu.c
index 0a5fe34..d3ad614 100644
--- a/src/gtk+-2.x/ctkgpu.c
+++ b/src/gtk+-2.x/ctkgpu.c
@@ -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 @@ GtkWidget* ctk_gpu_new(
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 = "?:?:?";
@@ -226,6 +230,21 @@ GtkWidget* ctk_gpu_new(
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 */
ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VBIOS_VERSION,
@@ -345,7 +364,7 @@ GtkWidget* ctk_gpu_new(
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 @@ GtkWidget* ctk_gpu_new(
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 @@ GtkTextBuffer *ctk_gpu_create_help(GtkTextTagTable *table)
"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.");
diff --git a/src/gtk+-2.x/ctkimagesliders.c b/src/gtk+-2.x/ctkimagesliders.c
index ff5a317..ace90fd 100644
--- a/src/gtk+-2.x/ctkimagesliders.c
+++ b/src/gtk+-2.x/ctkimagesliders.c
@@ -94,6 +94,8 @@ GtkWidget* ctk_image_sliders_new(NvCtrlAttributeHandle *handle,
GtkWidget *frame;
GtkWidget *vbox;
+ ReturnStatus status;
+ gint val;
/*
* now that we know that we will have atleast one attribute,
@@ -110,6 +112,17 @@ GtkWidget* ctk_image_sliders_new(NvCtrlAttributeHandle *handle,
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 @@ void ctk_image_sliders_reset(CtkImageSliders *ctk_image_sliders)
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);
diff --git a/src/gtk+-2.x/ctkimagesliders.h b/src/gtk+-2.x/ctkimagesliders.h
index 21172e6..3e5da70 100644
--- a/src/gtk+-2.x/ctkimagesliders.h
+++ b/src/gtk+-2.x/ctkimagesliders.h
@@ -68,6 +68,7 @@ struct _CtkImageSliders
GtkWidget *frame;
GtkWidget *digital_vibrance;
GtkWidget *image_sharpening;
+ gint default_val;
};
struct _CtkImageSlidersClass
diff --git a/src/gtk+-2.x/ctkmultisample.c b/src/gtk+-2.x/ctkmultisample.c
index d8b65c1..f5c85c9 100644
--- a/src/gtk+-2.x/ctkmultisample.c
+++ b/src/gtk+-2.x/ctkmultisample.c
@@ -1349,7 +1349,7 @@ GtkTextBuffer *ctk_multisample_create_help(GtkTextTagTable *table,
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 @@ GtkTextBuffer *ctk_multisample_create_help(GtkTextTagTable *table,
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) {
diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c
index a191588..294dba4 100644
--- a/src/gtk+-2.x/ctkpowermizer.c
+++ b/src/gtk+-2.x/ctkpowermizer.c
@@ -604,12 +604,12 @@ GtkTextBuffer *ctk_powermizer_create_help(GtkTextTagTable *table,
ctk_help_heading(b, &i, "Adaptive Clocking");
ctk_help_para(b, &i, __adaptive_clock_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, "Power Source");
+ ctk_help_para(b, &i, __power_source_help);
+
ctk_help_heading(b, &i, "Performance Level");
ctk_help_para(b, &i, __performance_level_help);
diff --git a/src/gtk+-2.x/ctkserver.c b/src/gtk+-2.x/ctkserver.c
index 9e80594..1c66b61 100644
--- a/src/gtk+-2.x/ctkserver.c
+++ b/src/gtk+-2.x/ctkserver.c
@@ -433,10 +433,10 @@ GtkWidget* ctk_server_new(NvCtrlAttributeHandle *handle,
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 @@ GtkTextBuffer *ctk_server_create_help(GtkTextTagTable *table,
"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 @@ GtkTextBuffer *ctk_server_create_help(GtkTextTagTable *table,
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).");
diff --git a/src/gtk+-2.x/ctkslimm.c b/src/gtk+-2.x/ctkslimm.c
index a75aa9e..9b1a265 100644
--- a/src/gtk+-2.x/ctkslimm.c
+++ b/src/gtk+-2.x/ctkslimm.c
@@ -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 display_config_changed(GtkWidget *widget, gpointer user_data);
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 @@ static Bool other_displays_have_modeline(nvLayoutPtr layout,
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 @@ typedef struct GridConfigRec {
*
**/
-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,72 @@ GType ctk_slimm_get_type()
return ctk_slimm_type;
}
-static void remove_slimm_options(CtkSLIMM *ctk_object)
+static void remove_slimm_options(XConfigPtr xconf)
{
- 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;
- }
-
/* 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;
- XConfigAdjacencyPtr adj;
- gchar *filename = "/etc/X11/xorg.conf";
- char *tmp_filename;
- if (!metamode_str) {
- return;
- }
+/* get_ith_valid_grid_config()
+ * Returns valid grid configuration from gridConfig list.
+ */
- 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;
+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() */
- 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);
+
+static void add_slimm_options(XConfigPtr xconf, gchar *metamode_str)
+{
+ XConfigAdjacencyPtr adj;
+
+ /* 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)
+
+
+static XConfigPtr xconfig_generate(XConfigPtr xconfCur,
+ Bool merge,
+ Bool *merged,
+ void *callback_data)
{
- CtkSLIMM *ctk_object = CTK_SLIMM(user_data);
+ CtkSLIMM *ctk_object = (CtkSLIMM *)callback_data;
+
gint idx;
gint xctr,yctr;
@@ -221,15 +202,28 @@ static void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data)
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,14 +251,31 @@ static void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data)
}
}
- 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 void save_xconfig_button_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkSLIMM *ctk_object = CTK_SLIMM(user_data);
+
+ /* Run the dialog */
+ run_save_xconfig_dialog(ctk_object->save_xconfig_dlg);
+
+}
+
+
+
static void txt_overlap_activated(GtkWidget *widget, gpointer user_data)
{
CtkSLIMM *ctk_object = CTK_SLIMM(user_data);
@@ -377,6 +388,8 @@ static void setup_total_size_label(CtkSLIMM *ctk_object)
gint h_overlap, v_overlap;
gchar *xscreen_size;
gint x_total, y_total;
+ GridConfig *grid_config;
+
if (!ctk_object->cur_modeline) {
return;
}
@@ -384,9 +397,14 @@ static void setup_total_size_label(CtkSLIMM *ctk_object)
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;
+ }
+
gtk_widget_set_sensitive(ctk_object->spbtn_hedge_overlap,
x_displays > 1 ? True : False);
gtk_widget_set_sensitive(ctk_object->spbtn_vedge_overlap,
@@ -694,10 +712,326 @@ static void setup_display_resolution_dropdown(CtkSLIMM *ctk_object)
(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; }
+ 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; }
+ 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;
+}
+
+
+
static void remove_duplicate_modelines(nvDisplayPtr display)
{
nvModeLinePtr m, nextm;
@@ -709,7 +1043,7 @@ static void remove_duplicate_modelines(nvDisplayPtr display)
/* 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 +1151,7 @@ static nvDisplayPtr intersect_modelines(nvLayoutPtr layout)
}
remove_duplicate_modelines(display);
+
return display;
}
@@ -842,11 +1177,20 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1202,15 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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;
+ }
/*
* Create the display configuration widgets
@@ -867,6 +1220,52 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
/* 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) {
gchar *str;
@@ -919,10 +1318,14 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
}
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 +1365,29 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1411,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1420,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1466,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1475,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1488,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1499,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1511,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1522,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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,7 +1532,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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);
label = gtk_label_new("Save to X Configuration File");
@@ -1129,6 +1543,12 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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 +1559,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
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);
diff --git a/src/gtk+-2.x/ctkslimm.h b/src/gtk+-2.x/ctkslimm.h
index 1321f5c..19cda5a 100644
--- a/src/gtk+-2.x/ctkslimm.h
+++ b/src/gtk+-2.x/ctkslimm.h
@@ -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 @@ struct _CtkSLIMM
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;
diff --git a/src/gtk+-2.x/ctkxvideo.c b/src/gtk+-2.x/ctkxvideo.c
index 0810de2..2c0ec80 100644
--- a/src/gtk+-2.x/ctkxvideo.c
+++ b/src/gtk+-2.x/ctkxvideo.c
@@ -1138,16 +1138,16 @@ GtkTextBuffer *ctk_xvideo_create_help(GtkTextTagTable *table,
ctk_help_para(b, &i, __xv_texture_sync_to_vblank_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_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_HUE) {
ctk_help_heading(b, &i, "Video Texture Hue");
ctk_help_para(b, &i, __xv_texture_hue_help);
diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h
index 3767edf..1c9526f 100644
--- a/src/libXNVCtrl/NVCtrl.h
+++ b/src/libXNVCtrl/NVCtrl.h
@@ -2248,6 +2248,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
@@ -2296,17 +2305,32 @@
#define NV_CTRL_GVO_FULL_RANGE_COLOR_ENABLED 1
/*
+ * 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
-#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_GVO_ENABLE_RGB_DATA
+/*
+ * NV_CTRL_IMAGE_SHARPENING_DEFAULT - Returns default value of
+ * Image Sharpening.
+ */
+
+#define NV_CTRL_IMAGE_SHARPENING_DEFAULT 305 /* R-- */
+#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_IMAGE_SHARPENING_DEFAULT
/**************************************************************************/
diff --git a/src/parse.c b/src/parse.c
index d871dd5..5a4476e 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -107,6 +107,7 @@ AttributeTableEntry attributeTable[] = {
{ "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 @@ AttributeTableEntry attributeTable[] = {
{ "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." },
@@ -228,7 +230,8 @@ AttributeTableEntry attributeTable[] = {
{ "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." },
@@ -286,7 +289,7 @@ AttributeTableEntry attributeTable[] = {
* about.
*/
-#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GVO_ENABLE_RGB_DATA
+#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_IMAGE_SHARPENING_DEFAULT
#warning "Have you forgotten to add a new integer attribute to attributeTable?"
#endif