summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2011-05-19 12:19:12 -0700
committerAaron Plattner <aplattner@nvidia.com>2011-05-19 12:19:12 -0700
commit04bc597a5fe9cacf0ae470ae433b50c2ea1aeb71 (patch)
tree910342c8d024694427b93c5534c9a62b8b09ca1b
parentf5cb6655d9de05bdd5c6713e35dbf9cdc3f8bc5c (diff)
275.09275.09
-rw-r--r--src/common-utils/nvgetopt.h8
-rw-r--r--src/gtk+-2.x/ctkcolorcontrols.c12
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig-utils.c1045
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig-utils.h6
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig.c1165
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig.h15
-rw-r--r--src/gtk+-2.x/ctkdisplaylayout.c468
-rw-r--r--src/gtk+-2.x/ctkdisplaylayout.h26
-rw-r--r--src/gtk+-2.x/ctkditheringcontrols.c28
-rw-r--r--src/gtk+-2.x/ctkevent.c6
-rw-r--r--src/gtk+-2.x/ctkimagesliders.c10
-rw-r--r--src/gtk+-2.x/ctkpowermizer.c4
-rw-r--r--src/gtk+-2.x/ctkslimm.c13
-rw-r--r--src/libXNVCtrl/NVCtrl.h65
-rw-r--r--src/libXNVCtrl/nv_control.h3
-rw-r--r--src/parse.c10
-rw-r--r--src/parse.h3
-rw-r--r--src/query-assign.c153
-rw-r--r--version.mk2
19 files changed, 1579 insertions, 1463 deletions
diff --git a/src/common-utils/nvgetopt.h b/src/common-utils/nvgetopt.h
index 7083860..13b54d4 100644
--- a/src/common-utils/nvgetopt.h
+++ b/src/common-utils/nvgetopt.h
@@ -30,6 +30,14 @@
/*
+ * mask of bits not used by nvgetopt in NVGetoptOption::flags;
+ * these bits are available for use within specific users of
+ * nvgetopt
+ */
+
+#define NVGETOPT_UNUSED_FLAG_RANGE 0xffff0000
+
+/*
* indicates that the option is a boolean value; the presence of the
* option will be interpretted as a TRUE value; if the option is
* prepended with '--no-', the option will be interpretted as a FALSE
diff --git a/src/gtk+-2.x/ctkcolorcontrols.c b/src/gtk+-2.x/ctkcolorcontrols.c
index c818087..97bc873 100644
--- a/src/gtk+-2.x/ctkcolorcontrols.c
+++ b/src/gtk+-2.x/ctkcolorcontrols.c
@@ -333,6 +333,7 @@ void post_color_range_update(CtkColorControls *ctk_color_controls,
"Limited", /* NV_CTRL_COLOR_RANGE_LIMITED */
};
+ gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE);
ctk_config_statusbar_message(ctk_color_controls->ctk_config,
"Color Range set to %s for %s.",
color_range_table[color_range],
@@ -349,6 +350,7 @@ void post_color_space_update(CtkColorControls *ctk_color_controls,
"YCbCr444" /* NV_CTRL_COLOR_SPACE_YCbCr444 */
};
+ gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE);
ctk_config_statusbar_message(ctk_color_controls->ctk_config,
"Color Space set to %s for %s.",
color_space_table[ctk_color_controls->color_space_table[color_space]],
@@ -386,7 +388,6 @@ static void color_range_menu_changed(GtkOptionMenu *color_range_menu,
/* reflecting the change to statusbar message and the reset button */
post_color_range_update(ctk_color_controls, color_range);
- gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE);
} /* color_range_menu_changed() */
@@ -426,7 +427,6 @@ static void color_space_menu_changed(GtkOptionMenu *color_space_menu,
/* reflecting the change in color space to other widgets & reset button */
ctk_color_controls_setup(ctk_color_controls);
post_color_space_update(ctk_color_controls, color_space);
- gtk_widget_set_sensitive(ctk_color_controls->reset_button, TRUE);
} /* color_space_menu_changed() */
@@ -485,6 +485,14 @@ static void color_control_update_received(GtkObject *object, gpointer arg1,
}
ctk_color_controls_setup(ctk_object);
+
+ /* update status bar message */
+ switch (event_struct->attribute) {
+ case NV_CTRL_COLOR_RANGE:
+ post_color_range_update(ctk_object, event_struct->value); break;
+ case NV_CTRL_COLOR_SPACE:
+ post_color_space_update(ctk_object, event_struct->value); break;
+ }
} /* color_control_update_received() */
diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.c b/src/gtk+-2.x/ctkdisplayconfig-utils.c
index 4199429..42755e3 100644
--- a/src/gtk+-2.x/ctkdisplayconfig-utils.c
+++ b/src/gtk+-2.x/ctkdisplayconfig-utils.c
@@ -1064,7 +1064,6 @@ static void display_free(nvDisplayPtr display)
void renumber_xscreens(nvLayoutPtr layout)
{
- nvGpuPtr gpu;
nvScreenPtr screen;
nvScreenPtr lowest;
int scrnum;
@@ -1074,12 +1073,13 @@ void renumber_xscreens(nvLayoutPtr layout)
/* Find screen w/ lowest # >= current screen index being assigned */
lowest = NULL;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- if ((screen->scrnum >= scrnum) &&
- (!lowest || (lowest->scrnum > screen->scrnum))) {
- lowest = screen;
- }
+ for (screen = layout->screens;
+ screen;
+ screen = screen->next_in_layout) {
+
+ if ((screen->scrnum >= scrnum) &&
+ (!lowest || (lowest->scrnum > screen->scrnum))) {
+ lowest = screen;
}
}
@@ -1095,6 +1095,72 @@ void renumber_xscreens(nvLayoutPtr layout)
+/** screen_link_display() ********************************************
+ *
+ * Makes the given display part of the screen
+ *
+ **/
+void screen_link_display(nvScreenPtr screen, nvDisplayPtr display)
+{
+ if (!display || !screen || (display->screen == screen)) return;
+
+ display->screen = screen;
+ display->next_in_screen = NULL;
+
+ /* Add the display at the end of the screen's display list */
+ if (!screen->displays) {
+ screen->displays = display;
+ } else {
+ nvDisplayPtr last = screen->displays;
+ while (last) {
+ if (!last->next_in_screen) {
+ last->next_in_screen = display;
+ break;
+ }
+ }
+ }
+ screen->displays_mask |= display->device_mask;
+ screen->num_displays++;
+
+} /* screen_link_display() */
+
+
+
+/** screen_unlink_display() ******************************************
+ *
+ * Removes the display from the screen's list of displays
+ *
+ **/
+void screen_unlink_display(nvDisplayPtr display)
+{
+ nvScreenPtr screen;
+
+ if (!display || !display->screen) return;
+
+ screen = display->screen;
+
+ /* Remove the display from the screen */
+ if (screen->displays == display) {
+ screen->displays = display->next_in_screen;
+ } else {
+ nvDisplayPtr cur = screen->displays;
+ while (cur) {
+ if (cur->next_in_screen == display) {
+ cur->next_in_screen = display->next_in_screen;
+ break;
+ }
+ cur = cur->next_in_screen;
+ }
+ }
+ screen->displays_mask &= ~(display->device_mask);
+ screen->num_displays--;
+
+ display->screen = NULL;
+
+} /* screen_unlink_display() */
+
+
+
/** screen_remove_display() ******************************************
*
* Removes a display device from the screen
@@ -1102,43 +1168,38 @@ void renumber_xscreens(nvLayoutPtr layout)
**/
void screen_remove_display(nvDisplayPtr display)
{
- nvGpuPtr gpu;
nvScreenPtr screen;
nvDisplayPtr other;
nvModePtr mode;
+ if (!display || !display->screen) return;
- if (display && display->screen) {
- screen = display->screen;
- gpu = display->gpu;
- /* Make any display relative to this one use absolute position */
- for (other = gpu->displays; other; other = other->next) {
+ screen = display->screen;
- if (other == display) continue;
- if (other->screen != screen) continue;
+ /* Make any display relative to this one use absolute position */
+ for (other = screen->displays; other; other = other->next_in_screen) {
- for (mode = other->modes; mode; mode = mode->next) {
- if (mode->relative_to == display) {
- mode->position_type = CONF_ADJ_ABSOLUTE;
- mode->relative_to = NULL;
- }
+ if (other == display) continue;
+
+ for (mode = other->modes; mode; mode = mode->next) {
+ if (mode->relative_to == display) {
+ mode->position_type = CONF_ADJ_ABSOLUTE;
+ mode->relative_to = NULL;
}
}
+ }
- /* Remove the display from the screen */
- screen->displays_mask &= ~(display->device_mask);
- screen->num_displays--;
-
- if (screen->primaryDisplay == display) {
- screen->primaryDisplay = NULL;
- }
+ /* Remove the display from the screen */
+ screen_unlink_display(display);
- /* Clean up old references to the screen in the display */
- display_remove_modes(display);
- display->screen = NULL;
+ /* Clean up old references */
+ if (screen->primaryDisplay == display) {
+ screen->primaryDisplay = NULL;
}
+ display_remove_modes(display);
+
} /* screen_remove_display() */
@@ -1151,18 +1212,10 @@ void screen_remove_display(nvDisplayPtr display)
**/
static void screen_remove_displays(nvScreenPtr screen)
{
- nvGpuPtr gpu;
- nvDisplayPtr display;
+ if (!screen) return;
- if (screen && screen->gpu) {
- gpu = screen->gpu;
-
- for (display = gpu->displays; display; display = display->next) {
-
- if (display->screen != screen) continue;
-
- screen_remove_display(display);
- }
+ while (screen->displays) {
+ screen_remove_display(screen->displays);
}
} /* screen_remove_displays() */
@@ -1186,10 +1239,10 @@ gchar *screen_get_metamode_str(nvScreenPtr screen, int metamode_idx,
gchar *mode_str;
gchar *tmp;
- for (display = screen->gpu->displays; display; display = display->next) {
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
- if (display->screen != screen) continue; /* Display not in screen */
-
mode_str = display_get_mode_str(display, metamode_idx, be_generic);
if (!mode_str) continue;
@@ -1217,35 +1270,29 @@ gchar *screen_get_metamode_str(nvScreenPtr screen, int metamode_idx,
**/
static void screen_remove_metamodes(nvScreenPtr screen)
{
- nvGpuPtr gpu;
nvDisplayPtr display;
nvMetaModePtr metamode;
- if (screen) {
- gpu = screen->gpu;
-
- /* Remove the modes from this screen's displays */
- if (gpu) {
- for (display = gpu->displays; display; display = display->next) {
-
- if (display->screen != screen) continue;
+ if (!screen) return;
- display_remove_modes(display);
- }
- }
+ /* Remove the modes from this screen's displays */
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
+ display_remove_modes(display);
+ }
- /* Clear the screen's metamode list */
- while (screen->metamodes) {
- metamode = screen->metamodes;
- screen->metamodes = metamode->next;
- free(metamode->string);
- free(metamode);
- }
- screen->num_metamodes = 0;
- screen->cur_metamode = NULL;
- screen->cur_metamode_idx = -1;
+ /* Clear the screen's metamode list */
+ while (screen->metamodes) {
+ metamode = screen->metamodes;
+ screen->metamodes = metamode->next;
+ free(metamode->string);
+ free(metamode);
}
-
+ screen->num_metamodes = 0;
+ screen->cur_metamode = NULL;
+ screen->cur_metamode_idx = -1;
+
} /* screen_remove_metamodes() */
@@ -1367,7 +1414,7 @@ static Bool screen_add_metamode(nvScreenPtr screen, const char *metamode_str,
/* Make the display part of the screen */
- display->screen = screen;
+ screen_link_display(screen, display);
/* Set the panning offset */
@@ -1415,9 +1462,9 @@ static Bool screen_check_metamodes(nvScreenPtr screen)
nvModePtr last_mode = NULL;
- for (display = screen->gpu->displays; display; display = display->next) {
-
- if (display->screen != screen) continue;
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
if (display->num_modes == screen->num_metamodes) continue;
@@ -1480,11 +1527,12 @@ void screen_assign_dummy_metamode_positions(nvScreenPtr screen)
nvDisplayPtr display;
nvModePtr ok_mode;
nvModePtr mode;
-
- for (display = screen->gpu->displays; display; display = display->next) {
- if (display->screen != screen) continue;
-
+
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
+
/* Get the first non-dummy mode */
for (ok_mode = display->modes; ok_mode; ok_mode = ok_mode->next) {
if (!ok_mode->dummy) break;
@@ -1500,7 +1548,7 @@ void screen_assign_dummy_metamode_positions(nvScreenPtr screen)
}
}
}
-
+
} /* screen_assign_dummy_metamode_positions() */
@@ -1599,18 +1647,12 @@ static Bool screen_add_metamodes(nvScreenPtr screen, gchar **err_str)
for (i = 0; i < screen->cur_metamode_idx; i++) {
screen->cur_metamode = screen->cur_metamode->next;
}
-
- /* Make each display within the screen point to the current mode.
- * Also, count the number of displays on the screen
- */
- screen->num_displays = 0;
- for (display = screen->gpu->displays; display; display = display->next) {
-
- if (display->screen != screen) continue; /* Display not in screen */
- screen->num_displays++;
- screen->displays_mask |= display->device_mask;
+ /* Make each display within the screen point to the current mode */
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
display->cur_mode = display->modes;
for (i = 0; i < screen->cur_metamode_idx; i++) {
@@ -1623,12 +1665,12 @@ static Bool screen_add_metamodes(nvScreenPtr screen, gchar **err_str)
/* Failure case */
fail:
-
+
/* Remove modes we may have added */
screen_remove_metamodes(screen);
XFree(metamode_strs);
- return FALSE;
+ return FALSE;
} /* screen_add_metamodes() */
@@ -1673,7 +1715,7 @@ nvDisplayPtr gpu_get_display(nvGpuPtr gpu, unsigned int device_mask)
{
nvDisplayPtr display;
- for (display = gpu->displays; display; display = display->next) {
+ for (display = gpu->displays; display; display = display->next_on_gpu) {
if (display->device_mask == device_mask) return display;
}
@@ -1693,27 +1735,33 @@ void gpu_remove_and_free_display(nvDisplayPtr display)
nvGpuPtr gpu;
nvScreenPtr screen;
+ if (!display || !display->gpu) return;
+
+ gpu = display->gpu;
+ screen = display->screen;
- if (display && display->gpu) {
- gpu = display->gpu;
- screen = display->screen;
+ /* Remove the display from the X screen */
+ if (screen) {
+ screen_remove_display(display);
- /* Remove the display from the screen it may be in */
- if (screen) {
- screen_remove_display(display);
+ if (!screen->num_displays) {
+ layout_remove_and_free_screen(screen);
+ }
+ }
- /* If the screen is empty, remove it too */
- if (!screen->num_displays) {
- gpu_remove_and_free_screen(screen);
+ /* Remove the display from the GPU */
+ if (gpu->displays == display) {
+ gpu->displays = display->next_on_gpu;
+ } else {
+ nvDisplayPtr cur;
+ for (cur = gpu->displays; cur; cur = cur->next_on_gpu) {
+ if (cur->next_on_gpu == display) {
+ cur->next_on_gpu = display->next_on_gpu;
+ break;
}
}
-
- /* Remove the display from the GPU */
- xconfigRemoveListItem((GenericListPtr *)(&gpu->displays),
- (GenericListPtr)display);
- gpu->connected_displays &= ~(display->device_mask);
- gpu->num_displays--;
}
+ gpu->num_displays--;
display_free(display);
@@ -1728,23 +1776,47 @@ void gpu_remove_and_free_display(nvDisplayPtr display)
**/
static void gpu_remove_displays(nvGpuPtr gpu)
{
- nvDisplayPtr display;
+ if (!gpu) return;
- if (gpu) {
- while (gpu->displays) {
- display = gpu->displays;
- screen_remove_display(display);
- gpu->displays = display->next;
- display_free(display);
- }
- //gpu->connected_displays = 0;
- gpu->num_displays = 0;
+ while (gpu->displays) {
+ gpu_remove_and_free_display(gpu->displays);
}
} /* gpu_remove_displays() */
+/** gpu_add_display() ************************************************
+ *
+ * Adds the display to (the end of) the GPU display list.
+ *
+ **/
+static void gpu_add_display(nvGpuPtr gpu, nvDisplayPtr display)
+{
+
+ if (!display || !gpu || (display->gpu == gpu)) return;
+
+ display->gpu = gpu;
+ display->next_on_gpu = NULL;
+
+ /* Add the display at the end of the GPU's display list */
+ if (!gpu->displays) {
+ gpu->displays = display;
+ } else {
+ nvDisplayPtr last;
+ for (last = gpu->displays; last; last = last->next_on_gpu) {
+ if (!last->next_on_gpu) {
+ last->next_on_gpu = display;
+ break;
+ }
+ }
+ }
+ gpu->num_displays++;
+
+} /* gpu_add_display() */
+
+
+
/** gpu_query_gvo_mode_info() ****************************************
*
* Adds GVO mode information to the GPU's gvo mode data table at
@@ -1797,19 +1869,18 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu,
gchar **err_str)
{
ReturnStatus ret;
- nvDisplayPtr display = NULL;
+ nvDisplayPtr display;
+
-
/* Create the display structure */
display = (nvDisplayPtr)calloc(1, sizeof(nvDisplay));
if (!display) goto fail;
/* Init the display structure */
- display->gpu = gpu;
display->device_mask = device_mask;
-
+
/* Query the display information */
ret = NvCtrlGetStringDisplayAttribute(gpu->handle,
device_mask,
@@ -1920,6 +1991,10 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu,
}
+ /* Add the display at the end of gpu's display list */
+ gpu_add_display(gpu, display);
+
+
/* Query the modelines for the display device */
if (!display_add_modelines_from_server(display, err_str)) {
nv_warning_msg("Failed to add modelines to display device 0x%08x "
@@ -1930,11 +2005,6 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu,
}
- /* Add the display at the end of gpu's display list */
- xconfigAddListItem((GenericListPtr *)(&gpu->displays),
- (GenericListPtr)display);
- gpu->connected_displays |= device_mask;
- gpu->num_displays++;
return display;
@@ -1954,6 +2024,7 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu,
**/
static Bool gpu_add_displays_from_server(nvGpuPtr gpu, gchar **err_str)
{
+ ReturnStatus ret;
unsigned int mask;
@@ -1961,14 +2032,23 @@ static Bool gpu_add_displays_from_server(nvGpuPtr gpu, gchar **err_str)
gpu_remove_displays(gpu);
- // XXX Query connected_displays here...
+ /* Get the list of connected displays */
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_CONNECTED_DISPLAYS,
+ (int *)&(gpu->connected_displays));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query connected display "
+ "devices on GPU-%d '%s'.",
+ NvCtrlGetTargetId(gpu), gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
/* Add each connected display */
for (mask = 1; mask; mask <<= 1) {
if (!(mask & (gpu->connected_displays))) continue;
-
+
if (!gpu_add_display_from_server(gpu, mask, err_str)) {
nv_warning_msg("Failed to add display device 0x%08x to GPU-%d "
"'%s'.",
@@ -1979,8 +2059,6 @@ static Bool gpu_add_displays_from_server(nvGpuPtr gpu, gchar **err_str)
return TRUE;
-
- /* Failure case */
fail:
gpu_remove_displays(gpu);
return FALSE;
@@ -1989,339 +2067,179 @@ static Bool gpu_add_displays_from_server(nvGpuPtr gpu, gchar **err_str)
-/** gpu_remove_and_free_screen() *************************************
+/** gpu_add_screenless_modes_to_displays() ***************************
*
- * Removes a screen from its GPU and frees it.
+ * Adds fake modes to display devices that have no screens so we
+ * can show them on the layout page.
*
**/
-void gpu_remove_and_free_screen(nvScreenPtr screen)
+Bool gpu_add_screenless_modes_to_displays(nvGpuPtr gpu)
{
- nvGpuPtr gpu;
- nvScreenPtr other;
-
- if (screen && screen->gpu) {
-
- /* Remove the screen from the GPU */
- gpu = screen->gpu;
-
- xconfigRemoveListItem((GenericListPtr *)(&gpu->screens),
- (GenericListPtr)screen);
- gpu->num_screens--;
-
- /* Make sure other screens in the layout aren't relative
- * to this screen
- */
- for (gpu = screen->gpu->layout->gpus; gpu; gpu = gpu->next) {
- for (other = gpu->screens; other; other = other->next) {
- if (other->relative_to == screen) {
- other->position_type = CONF_ADJ_ABSOLUTE;
- other->relative_to = NULL;
- }
- }
- }
- }
-
- screen_free(screen);
+ nvDisplayPtr display;
+ nvModePtr mode;
-} /* gpu_remove_and_free_screen() */
+ for (display = gpu->displays; display; display = display->next_on_gpu) {
+ if (display->screen) continue;
+ if (display->modes) continue;
+ /* Create a fake mode */
+ mode = (nvModePtr)calloc(1, sizeof(nvMode));
+ if (!mode) return FALSE;
+ mode->display = display;
+ mode->dummy = 1;
-/** gpu_remove_screens() *********************************************
- *
- * Removes all screens from a gpu and frees them
- *
- **/
-static void gpu_remove_screens(nvGpuPtr gpu)
-{
- nvScreenPtr screen;
+ mode->dim[W] = 800;
+ mode->dim[H] = 600;
+ mode->pan[W] = mode->dim[W];
+ mode->pan[H] = mode->dim[H];
- if (gpu) {
- while (gpu->screens) {
- screen = gpu->screens;
- gpu->screens = screen->next;
- screen_free(screen);
- }
- gpu->num_screens = 0;
+ /* Add the mode to the display */
+ display->modes = mode;
+ display->cur_mode = mode;
+ display->num_modes = 1;
}
-} /* gpu_remove_screens() */
+ return TRUE;
+
+} /* gpu_add_screenless_modes_to_displays() */
-/** gpu_add_screen_from_server() *************************************
+/** gpu_free() *******************************************************
*
- * Adds screen 'screen_id' that is connected to the gpu.
+ * Frees memory used by the gpu.
*
**/
-static int gpu_add_screen_from_server(nvGpuPtr gpu, int screen_id,
- gchar **err_str)
+static void gpu_free(nvGpuPtr gpu)
{
- Display *display;
- nvScreenPtr screen;
- int val, tmp;
- ReturnStatus ret;
- gchar *primary_str = NULL;
-
- /* Create the screen structure */
- screen = (nvScreenPtr)calloc(1, sizeof(nvScreen));
- if (!screen) goto fail;
-
- screen->gpu = gpu;
- screen->scrnum = screen_id;
-
-
- /* Make an NV-CONTROL handle to talk to the screen */
- display = NvCtrlGetDisplayPtr(gpu->handle);
- screen->handle =
- NvCtrlAttributeInit(display,
- NV_CTRL_TARGET_TYPE_X_SCREEN,
- screen_id,
- NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM |
- NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM);
- if (!screen->handle) {
- *err_str = g_strdup_printf("Failed to create NV-CONTROL handle for\n"
- "screen %d (on GPU-%d).",
- screen_id, NvCtrlGetTargetId(gpu->handle));
- nv_error_msg(*err_str);
- goto fail;
- }
-
-
- /* See if the screen supports dynamic twinview */
- ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_DYNAMIC_TWINVIEW, &val);
- if (ret != NvCtrlSuccess) {
- *err_str = g_strdup_printf("Failed to query Dynamic TwinView for "
- "screen %d.",
- screen_id);
- nv_warning_msg(*err_str);
- goto fail;
- }
- screen->dynamic_twinview = !!val;
-
-
- /* See if the screen is set to not scanout */
- ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_NO_SCANOUT, &val);
- if (ret != NvCtrlSuccess) {
- *err_str = g_strdup_printf("Failed to query NoScanout for "
- "screen %d.",
- screen_id);
- nv_warning_msg(*err_str);
- goto fail;
- }
- screen->no_scanout = (val == NV_CTRL_NO_SCANOUT_ENABLED);
-
-
- /* XXX Currently there is no support for screens that are scanning
- * out but have TwinView disabled.
- */
- if (!screen->dynamic_twinview && !screen->no_scanout) {
- *err_str = g_strdup_printf("nvidia-settings currently does not "
- "support scanout screens (%d) that have "
- "dynamic twinview disabled.",
- screen_id);
- nv_warning_msg(*err_str);
- goto fail;
- }
+ if (gpu) {
+ gpu_remove_displays(gpu);
+ XFree(gpu->name);
+ g_free(gpu->pci_bus_id);
+ free(gpu->gvo_mode_data);
- /* The display owner GPU gets the screen(s) */
- ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_MULTIGPU_DISPLAY_OWNER,
- &val);
- if (ret != NvCtrlSuccess || val != NvCtrlGetTargetId(gpu->handle)) {
- screen_free(screen);
- return TRUE;
+ if (gpu->handle) {
+ NvCtrlAttributeClose(gpu->handle);
+ }
+ free(gpu);
}
- ret = NvCtrlGetAttribute(screen->handle,
- NV_CTRL_SHOW_SLI_VISUAL_INDICATOR,
- &tmp);
+} /* gpu_free() */
- screen->sli = (ret == NvCtrlSuccess);
- /* Listen to NV-CONTROL events on this screen handle */
- screen->ctk_event = CTK_EVENT(ctk_event_new(screen->handle));
+/*****************************************************************************/
+/** LAYOUT FUNCTIONS *********************************************************/
+/*****************************************************************************/
- /* Query the depth of the screen */
- screen->depth = NvCtrlGetScreenPlanes(screen->handle);
- /* Initialize the virtual X screen size */
- screen->dim[W] = NvCtrlGetScreenWidth(screen->handle);
- screen->dim[H] = NvCtrlGetScreenHeight(screen->handle);
+/** layout_add_gpu() *************************************************
+ *
+ * Adds a GPU to the (end of the) layout's list of GPUs.
+ *
+ **/
+static void layout_add_gpu(nvLayoutPtr layout, nvGpuPtr gpu)
+{
+ gpu->layout = layout;
+ gpu->next_in_layout = NULL;
- /* Parse the screen's metamodes (ties displays on the gpu to the screen) */
- if (!screen->no_scanout) {
- if (!screen_add_metamodes(screen, err_str)) {
- nv_warning_msg("Failed to add metamodes to screen %d (on GPU-%d).",
- screen_id, NvCtrlGetTargetId(gpu->handle));
- goto fail;
- }
-
- /* Query & parse the screen's primary display */
- screen->primaryDisplay = NULL;
- ret = NvCtrlGetStringDisplayAttribute
- (screen->handle,
- 0,
- NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER,
- &primary_str);
-
- if (ret == NvCtrlSuccess) {
- nvDisplayPtr d;
- unsigned int device_mask;
-
- /* Parse the device mask */
- parse_read_display_name(primary_str, &device_mask);
-
- /* Find the matching primary display */
- for (d = gpu->displays; d; d = d->next) {
- if (d->screen == screen &&
- d->device_mask & device_mask) {
- screen->primaryDisplay = d;
- break;
- }
+ if (!layout->gpus) {
+ layout->gpus = gpu;
+ } else {
+ nvGpuPtr last;
+ for (last = layout->gpus; last; last = last->next_in_layout) {
+ if (!last->next_in_layout) {
+ last->next_in_layout = gpu;
+ break;
}
}
}
+ layout->num_gpus++;
- /* Add the screen at the end of the gpu's screen list */
- xconfigAddListItem((GenericListPtr *)(&gpu->screens),
- (GenericListPtr)screen);
- gpu->num_screens++;
- return TRUE;
-
-
- fail:
- screen_free(screen);
- return FALSE;
-
-} /* gpu_add_screen_from_server() */
+} /* layout_add_gpu() */
-/** gpu_add_screens_from_server() ************************************
+/** layout_add_screen() **********************************************
*
- * Queries the list of screens on the gpu.
+ * Adds a screen to the (end of the) layout's list of screens.
*
- */
-static Bool gpu_add_screens_from_server(nvGpuPtr gpu, gchar **err_str)
+ **/
+void layout_add_screen(nvLayoutPtr layout, nvScreenPtr screen)
{
- ReturnStatus ret;
- int *pData;
- int len;
- int i;
-
-
- /* Clean up the GPU list */
- gpu_remove_screens(gpu);
-
+ screen->layout = layout;
+ screen->next_in_layout = NULL;
- /* Query the list of X screens this GPU is driving */
- ret = NvCtrlGetBinaryAttribute(gpu->handle, 0,
- NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU,
- (unsigned char **)(&pData), &len);
- if (ret != NvCtrlSuccess) {
- *err_str = g_strdup_printf("Failed to query list of screens driven\n"
- "by GPU-%d '%s'.",
- NvCtrlGetTargetId(gpu->handle), gpu->name);
- nv_error_msg(*err_str);
- goto fail;
- }
-
-
- /* Add each X screen */
- for (i = 1; i <= pData[0]; i++) {
- if (!gpu_add_screen_from_server(gpu, pData[i], err_str)) {
- nv_warning_msg("Failed to add screen %d to GPU-%d '%s'.",
- pData[i], NvCtrlGetTargetId(gpu->handle),
- gpu->name);
- XFree(pData);
- goto fail;
+ if (!layout->screens) {
+ layout->screens = screen;
+ } else {
+ nvScreenPtr last;
+ for (last = layout->screens; last; last = last->next_in_layout) {
+ if (!last->next_in_layout) {
+ last->next_in_layout = screen;
+ break;
+ }
}
}
- XFree(pData);
- return TRUE;
-
-
- /* Failure case */
- fail:
- gpu_remove_screens(gpu);
- return FALSE;
+ layout->num_screens++;
-} /* gpu_add_screens_from_server() */
+} /* layout_add_screen() */
-/** gpu_add_screenless_modes_to_displays() ***************************
+/** layout_remove_and_free_screen() **********************************
*
- * Adds fake modes to display devices that have no screens so we
- * can show them on the layout page.
+ * Removes a screen from the layout and frees it.
*
**/
-Bool gpu_add_screenless_modes_to_displays(nvGpuPtr gpu)
+
+void layout_remove_and_free_screen(nvScreenPtr screen)
{
- nvDisplayPtr display;
- nvModePtr mode;
+ nvLayoutPtr layout = screen->layout;
+ nvScreenPtr other;
- for (display = gpu->displays; display; display = display->next) {
- if (display->screen) continue;
+ if (!screen) return;
- /* Create a fake mode */
- mode = (nvModePtr)calloc(1, sizeof(nvMode));
- if (!mode) return FALSE;
- mode->display = display;
- mode->dummy = 1;
-
- mode->dim[W] = 800;
- mode->dim[H] = 600;
- mode->pan[W] = mode->dim[W];
- mode->pan[H] = mode->dim[H];
+ /* Make sure other screens in the layout aren't relative
+ * to this screen
+ */
+ for (other = layout->screens;
+ other;
+ other = other->next_in_layout) {
- /* Add the mode to the display */
- display->modes = mode;
- display->cur_mode = mode;
- display->num_modes = 1;
+ if (other->relative_to == screen) {
+ other->position_type = CONF_ADJ_ABSOLUTE;
+ other->relative_to = NULL;
+ }
}
- return TRUE;
-
-} /* gpu_add_screenless_modes_to_displays() */
-
-
-
-/** gpu_free() *******************************************************
- *
- * Frees memory used by the gpu.
- *
- **/
-static void gpu_free(nvGpuPtr gpu)
-{
- if (gpu) {
- gpu_remove_screens(gpu);
- gpu_remove_displays(gpu);
- XFree(gpu->name);
- g_free(gpu->pci_bus_id);
- if (gpu->handle) {
- NvCtrlAttributeClose(gpu->handle);
+ /* Remove the screen from the layout */
+ if (layout->screens == screen) {
+ layout->screens = screen->next_in_layout;
+ } else {
+ nvScreenPtr cur;
+ for (cur = layout->screens; cur; cur = cur->next_in_layout) {
+ if (cur->next_in_layout == screen) {
+ cur->next_in_layout = screen->next_in_layout;
+ break;
+ }
}
- free(gpu);
}
+ layout->num_screens--;
-} /* gpu_free() */
+ screen_free(screen);
+} /* layout_remove_and_free_screen() */
-/*****************************************************************************/
-/** LAYOUT FUNCTIONS *********************************************************/
-/*****************************************************************************/
-
-
/** layout_remove_gpus() *********************************************
*
* Removes all GPUs from the layout structure.
@@ -2329,14 +2247,16 @@ static void gpu_free(nvGpuPtr gpu)
**/
static void layout_remove_gpus(nvLayoutPtr layout)
{
- if (layout) {
- while (layout->gpus) {
- nvGpuPtr gpu = layout->gpus;
- layout->gpus = gpu->next;
- gpu_free(gpu);
- }
- layout->num_gpus = 0;
+ nvGpuPtr gpu;
+
+ if (!layout) return;
+
+ while (layout->gpus) {
+ gpu = layout->gpus;
+ layout->gpus = gpu->next_in_layout;
+ gpu_free(gpu);
}
+ layout->num_gpus = 0;
} /* layout_remove_gpus() */
@@ -2385,16 +2305,6 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id,
goto fail;
}
- ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_CONNECTED_DISPLAYS,
- (int *)&(gpu->connected_displays));
- if (ret != NvCtrlSuccess) {
- *err_str = g_strdup_printf("Failed to query connected display "
- "devices on GPU-%d '%s'.",
- gpu_id, gpu->name);
- nv_error_msg(*err_str);
- goto fail;
- }
-
get_bus_id_str(gpu->handle, &(gpu->pci_bus_id));
ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_MAX_SCREEN_WIDTH,
@@ -2438,27 +2348,9 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id,
goto fail;
}
-
- /* Add the X screens to the GPU */
- if (!gpu_add_screens_from_server(gpu, err_str)) {
- nv_warning_msg("Failed to add screens to GPU-%d '%s'.",
- gpu_id, gpu->name);
- goto fail;
- }
-
-
- /* Add fake modes to screenless display devices */
- if (!gpu_add_screenless_modes_to_displays(gpu)) {
- nv_warning_msg("Failed to add screenless modes to GPU-%d '%s'.",
- gpu_id, gpu->name);
- goto fail;
- }
-
-
/* Add the GPU at the end of the layout's GPU list */
- xconfigAddListItem((GenericListPtr *)(&layout->gpus),
- (GenericListPtr)gpu);
- layout->num_gpus++;
+ layout_add_gpu(layout, gpu);
+
return TRUE;
@@ -2518,6 +2410,253 @@ static int layout_add_gpus_from_server(nvLayoutPtr layout, gchar **err_str)
+/** layout_remove_screens() ******************************************
+ *
+ * Removes all X screens from the layout structure.
+ *
+ **/
+static void layout_remove_screens(nvLayoutPtr layout)
+{
+ if (!layout) return;
+
+ while (layout->screens) {
+ layout_remove_and_free_screen(layout->screens);
+ }
+
+} /* layout_remove_screens() */
+
+
+
+/** layout_add_screen_from_server() **********************************
+ *
+ * Adds an X screen to the layout structure.
+ *
+ **/
+static Bool layout_add_screen_from_server(nvLayoutPtr layout,
+ unsigned int screen_id,
+ gchar **err_str)
+{
+ Display *display;
+ nvScreenPtr screen;
+ int val, tmp;
+ ReturnStatus ret;
+ gchar *primary_str = NULL;
+ nvGpuPtr gpu;
+
+
+ screen = (nvScreenPtr)calloc(1, sizeof(nvScreen));
+ if (!screen) goto fail;
+
+ screen->scrnum = screen_id;
+
+
+ /* Make an NV-CONTROL handle to talk to the screen (use the
+ * first gpu's display)
+ */
+ display = NvCtrlGetDisplayPtr(layout->gpus->handle);
+ screen->handle =
+ NvCtrlAttributeInit(display,
+ NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen_id,
+ NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM |
+ NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM);
+ if (!screen->handle) {
+ *err_str = g_strdup_printf("Failed to create NV-CONTROL handle for\n"
+ "screen %d.",
+ screen_id);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* See if the screen supports dynamic twinview */
+ ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_DYNAMIC_TWINVIEW, &val);
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query Dynamic TwinView for "
+ "screen %d.",
+ screen_id);
+ nv_warning_msg(*err_str);
+ goto fail;
+ }
+ screen->dynamic_twinview = !!val;
+
+
+ /* See if the screen is set to not scanout */
+ ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_NO_SCANOUT, &val);
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query NoScanout for "
+ "screen %d.",
+ screen_id);
+ nv_warning_msg(*err_str);
+ goto fail;
+ }
+ screen->no_scanout = (val == NV_CTRL_NO_SCANOUT_ENABLED);
+
+
+ /* XXX Currently there is no support for screens that are scanning
+ * out but have TwinView disabled.
+ */
+ if (!screen->dynamic_twinview && !screen->no_scanout) {
+ *err_str = g_strdup_printf("nvidia-settings currently does not "
+ "support scanout screens (%d) that have "
+ "dynamic twinview disabled.",
+ screen_id);
+ nv_warning_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* The display owner GPU gets the screen(s) */
+ ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_MULTIGPU_DISPLAY_OWNER,
+ &val);
+ if (ret != NvCtrlSuccess) {
+ screen_free(screen);
+ return TRUE;
+ }
+
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ if (val == NvCtrlGetTargetId(gpu->handle)) {
+ screen->gpu = gpu;
+ }
+ }
+ if (!screen->gpu) {
+ *err_str = g_strdup_printf("Failed to find GPU that drives screen %d.",
+ screen_id);
+ nv_warning_msg(*err_str);
+ goto fail;
+ }
+
+ /* Query SLI status */
+ ret = NvCtrlGetAttribute(screen->handle,
+ NV_CTRL_SHOW_SLI_VISUAL_INDICATOR,
+ &tmp);
+
+ screen->sli = (ret == NvCtrlSuccess);
+
+
+ /* Listen to NV-CONTROL events on this screen handle */
+ screen->ctk_event = CTK_EVENT(ctk_event_new(screen->handle));
+
+
+ /* Query the depth of the screen */
+ screen->depth = NvCtrlGetScreenPlanes(screen->handle);
+
+ /* Initialize the virtual X screen size */
+ screen->dim[W] = NvCtrlGetScreenWidth(screen->handle);
+ screen->dim[H] = NvCtrlGetScreenHeight(screen->handle);
+
+
+
+ /* Add the screen at the end of the gpu's screen list */
+ layout_add_screen(layout, screen);
+
+
+ /* Parse the screen's metamodes (ties displays on the gpu to the screen) */
+ if (!screen->no_scanout) {
+ if (!screen_add_metamodes(screen, err_str)) {
+ nv_warning_msg("Failed to add metamodes to screen %d.",
+ screen_id);
+ goto fail;
+ }
+
+ /* Query & parse the screen's primary display */
+ screen->primaryDisplay = NULL;
+ ret = NvCtrlGetStringDisplayAttribute
+ (screen->handle,
+ 0,
+ NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER,
+ &primary_str);
+
+ if (ret == NvCtrlSuccess) {
+ unsigned int device_mask;
+
+ /* Parse the device mask */
+ parse_read_display_name(primary_str, &device_mask);
+
+ /* Find the matching primary display */
+ screen->primaryDisplay = gpu_get_display(screen->gpu, device_mask);
+ }
+ }
+
+ return TRUE;
+
+ fail:
+ screen_free(screen);
+
+ return FALSE;
+
+} /* layout_add_screen_from_server() */
+
+
+
+/** layout_add_screens_from_server() *********************************
+ *
+ * Adds the screens found on the server to the layout structure.
+ *
+ **/
+static int layout_add_screens_from_server(nvLayoutPtr layout, gchar **err_str)
+{
+ ReturnStatus ret;
+ int i, nscreens;
+
+
+ layout_remove_screens(layout);
+
+
+ ret = NvCtrlQueryTargetCount(layout->handle, NV_CTRL_TARGET_TYPE_X_SCREEN,
+ &nscreens);
+ if (ret != NvCtrlSuccess || !nscreens) {
+ *err_str = g_strdup("Failed to query number of X screens (or no X "
+ "screens found) in the system.");
+ nv_error_msg(*err_str);
+ nscreens = 0;
+ goto fail;
+ }
+
+ for (i = 0; i < nscreens; i++) {
+ if (!layout_add_screen_from_server(layout, i, err_str)) {
+ nv_warning_msg("Failed to add X screen %d to layout.", i);
+ goto fail;
+ }
+ }
+
+ return nscreens;
+
+
+ fail:
+ layout_remove_screens(layout);
+ return 0;
+
+} /* layout_add_screens_from_server() */
+
+
+
+/** layout_add_screenless_modes_to_displays()*************************
+ *
+ * Adds fake modes to display devices that are currently not
+ * associated with an X screen so we can see them on the layout.
+ *
+ **/
+static Bool layout_add_screenless_modes_to_displays(nvLayoutPtr layout)
+{
+ nvGpuPtr gpu;
+
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+
+ /* Add fake modes to screenless display devices */
+ if (!gpu_add_screenless_modes_to_displays(gpu)) {
+ nv_warning_msg("Failed to add screenless modes to GPU-%d '%s'.",
+ NvCtrlGetTargetId(gpu->handle), gpu->name);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+
+} /* layout_add_screenless_modes_to_displays() */
+
+
+
/** layout_free() ****************************************************
*
* Frees a layout structure.
@@ -2553,7 +2692,7 @@ nvLayoutPtr layout_load_from_server(NvCtrlAttributeHandle *handle,
/* Cache the handle for talking to the X server */
layout->handle = handle;
-
+
/* Is Xinerma enabled? */
ret = NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA,
@@ -2564,14 +2703,24 @@ nvLayoutPtr layout_load_from_server(NvCtrlAttributeHandle *handle,
goto fail;
}
-
- /* Add GPUs to the layout */
if (!layout_add_gpus_from_server(layout, err_str)) {
nv_warning_msg("Failed to add GPU(s) to layout for display "
"configuration page.");
goto fail;
}
+ if (!layout_add_screens_from_server(layout, err_str)) {
+ nv_warning_msg("Failed to add Screens(s) to layout for display "
+ "configuration page.");
+ goto fail;
+ }
+
+ if (!layout_add_screenless_modes_to_displays(layout)) {
+ nv_warning_msg("Failed to add Screenless modes to layout for "
+ "display configuration page.");
+ goto fail;
+ }
+
return layout;
@@ -2593,28 +2742,22 @@ nvLayoutPtr layout_load_from_server(NvCtrlAttributeHandle *handle,
**/
nvScreenPtr layout_get_a_screen(nvLayoutPtr layout, nvGpuPtr preferred_gpu)
{
- nvGpuPtr gpu;
nvScreenPtr screen = NULL;
- nvScreenPtr other;
-
- if (!layout) return NULL;
+ nvScreenPtr cur;
- if (preferred_gpu && preferred_gpu->screens) {
- gpu = preferred_gpu;
- } else {
- preferred_gpu = NULL;
- gpu = layout->gpus;
- }
+ if (!layout || !layout->screens) return NULL;
- for (; gpu; gpu = gpu->next) {
- for (other = gpu->screens; other; other = other->next) {
- if (!screen || screen->scrnum > other->scrnum) {
- screen = other;
+ screen = layout->screens;
+ for (cur = screen->next_in_layout; cur; cur = cur->next_in_layout) {
+ if (cur->gpu == preferred_gpu) {
+ if (screen->gpu != preferred_gpu) {
+ screen = cur;
+ continue;
}
}
-
- /* We found a preferred screen */
- if (gpu == preferred_gpu) break;
+ if (screen->scrnum > cur->scrnum) {
+ screen = cur;
+ }
}
return screen;
diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.h b/src/gtk+-2.x/ctkdisplayconfig-utils.h
index fc62337..847654e 100644
--- a/src/gtk+-2.x/ctkdisplayconfig-utils.h
+++ b/src/gtk+-2.x/ctkdisplayconfig-utils.h
@@ -78,6 +78,8 @@ void display_remove_modes(nvDisplayPtr display);
/* Screen functions */
void renumber_xscreens(nvLayoutPtr layout);
+void screen_unlink_display(nvDisplayPtr display);
+void screen_link_display(nvScreenPtr screen, nvDisplayPtr display);
void screen_remove_display(nvDisplayPtr display);
gchar * screen_get_metamode_str(nvScreenPtr screen, int metamode_idx,
int be_generic);
@@ -91,17 +93,17 @@ nvDisplayPtr gpu_add_display_from_server(nvGpuPtr gpu,
unsigned int device_mask,
gchar **err_str);
-void gpu_remove_and_free_screen(nvScreenPtr screen);
Bool gpu_add_screenless_modes_to_displays(nvGpuPtr gpu);
/* Layout functions */
void layout_free(nvLayoutPtr layout);
+void layout_add_screen(nvLayoutPtr layout, nvScreenPtr screen);
nvLayoutPtr layout_load_from_server(NvCtrlAttributeHandle *handle,
gchar **err_str);
nvScreenPtr layout_get_a_screen(nvLayoutPtr layout, nvGpuPtr preferred_gpu);
-
+void layout_remove_and_free_screen(nvScreenPtr screen);
diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c
index f9e1600..c848bad 100644
--- a/src/gtk+-2.x/ctkdisplayconfig.c
+++ b/src/gtk+-2.x/ctkdisplayconfig.c
@@ -55,8 +55,7 @@ static void setup_layout_frame(CtkDisplayConfig *ctk_object);
static void setup_display_page(CtkDisplayConfig *ctk_object);
-static void display_config_clicked(GtkWidget *widget, gpointer user_data);
-
+static void display_config_changed(GtkWidget *widget, gpointer user_data);
static void display_resolution_changed(GtkWidget *widget, gpointer user_data);
static void display_refresh_changed(GtkWidget *widget, gpointer user_data);
static void display_modelname_changed(GtkWidget *widget, gpointer user_data);
@@ -138,7 +137,10 @@ typedef struct SwitchModeCallbackInfoRec {
#define VALIDATE_APPLY 0
#define VALIDATE_SAVE 1
-
+/* Display configuration index */
+#define DPY_CFG_DISABLED 0
+#define DPY_CFG_SEPARATE_X_SCREEN 1
+#define DPY_CFG_TWINVIEW 2
/*** G L O B A L S ***********************************************************/
@@ -166,6 +168,10 @@ static const char * __layout_xinerama_button_help =
static const char * __dpy_model_help =
"The Display drop-down allows you to select a desired display device.";
+static const char * __dpy_configuration_mnu_help =
+"The Configure drop-down allows you to select the desired configuration "
+"for the currently selected display device.";
+
static const char * __dpy_resolution_mnu_help =
"The Resolution drop-down allows you to select a desired resolution "
"for the currently selected display device.";
@@ -322,17 +328,19 @@ static void check_screen_pos_changed(CtkDisplayConfig *ctk_object)
/** layout_supports_depth_30() ***************************************
*
- * Returns TRUE if all the GPUs in the layout that have screens
- * support depth 30.
+ * Returns TRUE if all the screens in the layout are driven by GPUs
+ * that support depth 30.
*
**/
static gboolean layout_supports_depth_30(nvLayoutPtr layout)
{
+ nvScreenPtr screen;
nvGpuPtr gpu;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- if ((gpu->num_screens) && (!gpu->allow_depth_30)) {
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+ gpu = screen->gpu;
+ if (!gpu->allow_depth_30) {
return FALSE;
}
}
@@ -354,11 +362,10 @@ static void register_layout_events(CtkDisplayConfig *ctk_object)
nvLayoutPtr layout = ctk_object->layout;
nvScreenPtr screen;
nvGpuPtr gpu;
-
- /* Register all Screen/Gpu events. */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ /* Register for GPU events */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
if (!gpu->handle) continue;
@@ -371,31 +378,32 @@ static void register_layout_events(CtkDisplayConfig *ctk_object)
CTK_EVENT_NAME(NV_CTRL_MODE_SET_EVENT),
G_CALLBACK(display_config_attribute_changed),
(gpointer) ctk_object);
+ }
- for (screen = gpu->screens; screen; screen = screen->next) {
+ /* Register for X screen events */
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
- if (!screen->handle) continue;
-
- g_signal_connect(G_OBJECT(screen->ctk_event),
- CTK_EVENT_NAME(NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER),
- G_CALLBACK(display_config_attribute_changed),
- (gpointer) ctk_object);
-
- g_signal_connect(G_OBJECT(screen->ctk_event),
- CTK_EVENT_NAME(NV_CTRL_ASSOCIATED_DISPLAY_DEVICES),
- G_CALLBACK(display_config_attribute_changed),
- (gpointer) ctk_object);
-
- g_signal_connect(G_OBJECT(screen->ctk_event),
- CTK_EVENT_NAME(NV_CTRL_STRING_MOVE_METAMODE),
- G_CALLBACK(display_config_attribute_changed),
- (gpointer) ctk_object);
-
- g_signal_connect(G_OBJECT(screen->ctk_event),
- CTK_EVENT_NAME(NV_CTRL_STRING_DELETE_METAMODE),
- G_CALLBACK(display_config_attribute_changed),
- (gpointer) ctk_object);
- }
+ if (!screen->handle) continue;
+
+ g_signal_connect(G_OBJECT(screen->ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER),
+ G_CALLBACK(display_config_attribute_changed),
+ (gpointer) ctk_object);
+
+ g_signal_connect(G_OBJECT(screen->ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_ASSOCIATED_DISPLAY_DEVICES),
+ G_CALLBACK(display_config_attribute_changed),
+ (gpointer) ctk_object);
+
+ g_signal_connect(G_OBJECT(screen->ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_STRING_MOVE_METAMODE),
+ G_CALLBACK(display_config_attribute_changed),
+ (gpointer) ctk_object);
+
+ g_signal_connect(G_OBJECT(screen->ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_STRING_DELETE_METAMODE),
+ G_CALLBACK(display_config_attribute_changed),
+ (gpointer) ctk_object);
}
} /* register_layout_events() */
@@ -416,15 +424,13 @@ static void unregister_layout_events(CtkDisplayConfig *ctk_object)
nvLayoutPtr layout = ctk_object->layout;
nvScreenPtr screen;
nvGpuPtr gpu;
-
- /* Unregister all Screen/Gpu events. */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ /* Unregister GPU events */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
if (!gpu->handle) continue;
- /* Unregister all GPU events for this GPU */
g_signal_handlers_disconnect_matched(G_OBJECT(gpu->ctk_event),
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
0, // Signal ID
@@ -432,20 +438,20 @@ static void unregister_layout_events(CtkDisplayConfig *ctk_object)
NULL, // Closure
G_CALLBACK(display_config_attribute_changed),
(gpointer) ctk_object);
+ }
- for (screen = gpu->screens; screen; screen = screen->next) {
+ /* Unregister X screen events */
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
- if (!screen->handle) continue;
-
- /* Unregister all screen events for this screen */
- g_signal_handlers_disconnect_matched(G_OBJECT(screen->ctk_event),
- G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
- 0, // Signal ID
- 0, // Signal Detail
- NULL, // Closure
- G_CALLBACK(display_config_attribute_changed),
- (gpointer) ctk_object);
- }
+ if (!screen->handle) continue;
+
+ g_signal_handlers_disconnect_matched(G_OBJECT(screen->ctk_event),
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, // Signal ID
+ 0, // Signal Detail
+ NULL, // Closure
+ G_CALLBACK(display_config_attribute_changed),
+ (gpointer) ctk_object);
}
} /* unregister_layout_events() */
@@ -463,7 +469,6 @@ static void consolidate_xinerama(CtkDisplayConfig *ctk_object,
nvScreenPtr screen)
{
nvLayoutPtr layout = ctk_object->layout;
- nvGpuPtr gpu;
nvScreenPtr other;
if (!layout->xinerama_enabled) return;
@@ -484,11 +489,11 @@ static void consolidate_xinerama(CtkDisplayConfig *ctk_object,
}
/* If Xinerama is enabled, all screens must have the same depth. */
- for (gpu = screen->gpu->layout->gpus; gpu; gpu = gpu->next) {
- for (other = gpu->screens; other; other = other->next) {
- if (other == screen) continue;
- other->depth = screen->depth;
- }
+ for (other = layout->screens; other; other = other->next_in_layout) {
+
+ if (other == screen) continue;
+
+ other->depth = screen->depth;
}
} /* consolidate_xinerama() */
@@ -504,21 +509,19 @@ static void consolidate_xinerama(CtkDisplayConfig *ctk_object,
void update_btn_apply(CtkDisplayConfig *ctk_object, Bool sensitive)
{
Bool xrandr_available = FALSE;
- nvGpuPtr gpu;
+ nvLayoutPtr layout = ctk_object->layout;
nvScreenPtr screen;
if (sensitive) {
- /* If XRandR is disabled (for all screens), we can't apply */
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
-
- for (screen = gpu->screens; screen; screen = screen->next) {
- if (NvCtrlGetXrandrEventBase(screen->handle) >= 0) {
- xrandr_available = TRUE;
- break;
- }
+ /* If none of the screens support XRandR, we can't apply */
+ for (screen = layout->screens;
+ screen;
+ screen = screen->next_in_layout) {
+ if (NvCtrlGetXrandrEventBase(screen->handle) >= 0) {
+ xrandr_available = TRUE;
+ break;
}
- if (xrandr_available) break;
}
if (!xrandr_available && !ctk_object->primary_display_changed) {
@@ -754,7 +757,7 @@ static int generate_xconf_metamode_str(CtkDisplayConfig *ctk_object,
static void assign_screen_positions(CtkDisplayConfig *ctk_object)
{
- nvGpuPtr gpu;
+ nvLayoutPtr layout = ctk_object->layout;
nvScreenPtr prev_screen = NULL;
nvScreenPtr screen;
int xinerama;
@@ -770,64 +773,87 @@ static void assign_screen_positions(CtkDisplayConfig *ctk_object)
if (ret != NvCtrlSuccess) {
initialize = 1; /* Fallback to right-of positioning */
}
-
/* Setup screen positions */
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
-
- screen_info = NULL;
- if (screen->handle && !initialize) {
- ret = NvCtrlGetStringAttribute
- (screen->handle,
- NV_CTRL_STRING_XINERAMA_SCREEN_INFO,
- &screen_info);
-
- if (ret != NvCtrlSuccess) {
- screen_info = NULL;
- }
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+
+ screen_info = NULL;
+ if (screen->handle && !initialize) {
+ ret = NvCtrlGetStringAttribute
+ (screen->handle,
+ NV_CTRL_STRING_XINERAMA_SCREEN_INFO,
+ &screen_info);
+
+ if (ret != NvCtrlSuccess) {
+ screen_info = NULL;
}
+ }
- if (screen_info) {
+ if (screen_info) {
- /* Parse the positioning information */
+ /* Parse the positioning information */
- screen_parsed_info.x = -1;
- screen_parsed_info.y = -1;
- screen_parsed_info.width = -1;
- screen_parsed_info.height = -1;
+ screen_parsed_info.x = -1;
+ screen_parsed_info.y = -1;
+ screen_parsed_info.width = -1;
+ screen_parsed_info.height = -1;
- parse_token_value_pairs(screen_info, apply_screen_info_token,
- &screen_parsed_info);
+ parse_token_value_pairs(screen_info, apply_screen_info_token,
+ &screen_parsed_info);
- if (screen_parsed_info.x >= 0 &&
- screen_parsed_info.y >= 0 &&
- screen_parsed_info.width >= 0 &&
- screen_parsed_info.height) {
+ if (screen_parsed_info.x >= 0 &&
+ screen_parsed_info.y >= 0 &&
+ screen_parsed_info.width >= 0 &&
+ screen_parsed_info.height) {
- ctk_display_layout_set_screen_position
- (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
- screen, CONF_ADJ_ABSOLUTE, NULL,
- screen_parsed_info.x,
- screen_parsed_info.y);
- }
- XFree(screen_info);
-
- } else if (prev_screen) {
- /* Set this screen right of the previous */
ctk_display_layout_set_screen_position
(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
- screen, CONF_ADJ_RIGHTOF, prev_screen, 0, 0);
+ screen, CONF_ADJ_ABSOLUTE, NULL,
+ screen_parsed_info.x,
+ screen_parsed_info.y);
}
+ XFree(screen_info);
- prev_screen = screen;
+ } else if (prev_screen) {
+ /* Set this screen right of the previous */
+ ctk_display_layout_set_screen_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, CONF_ADJ_RIGHTOF, prev_screen, 0, 0);
}
+
+ prev_screen = screen;
}
} /* assign_screen_positions() */
+/** find_first_screen_on_gpu() ***************************************
+ *
+ * Returns the X screen with the lowest screen number on the given
+ * GPU.
+ *
+ **/
+
+static nvScreenPtr find_first_screen_on_gpu(nvGpuPtr gpu)
+{
+ nvLayoutPtr layout = gpu->layout;
+ nvScreenPtr first = NULL;
+ nvScreenPtr screen;
+
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+ if (screen->gpu != gpu) continue;
+ if (!first ||
+ (first->scrnum > screen->scrnum)) {
+ first = screen;
+ }
+ }
+
+ return first;
+
+} /* find_first_screen_on_gpu() */
+
+
/* Widget creation functions *****************************************/
@@ -1273,41 +1299,22 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
G_CALLBACK(display_modelname_changed),
(gpointer) ctk_object);
- /* Display configuration (Disabled, TwinView, Separate X screen */
- ctk_object->btn_display_config =
- gtk_button_new_with_label("Configure...");
- g_signal_connect(G_OBJECT(ctk_object->btn_display_config), "clicked",
- G_CALLBACK(display_config_clicked),
+ /* Display configuration (Disabled, TwinView, Separate X screen) */
+ ctk_object->mnu_display_config = gtk_option_menu_new();
+ menu = gtk_menu_new();
+ ctk_object->mnu_display_config_disabled = gtk_menu_item_new_with_label("Disabled");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), ctk_object->mnu_display_config_disabled);
+ ctk_object->mnu_display_config_xscreen = gtk_menu_item_new_with_label("Separate X screen (requires X restart)");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), ctk_object->mnu_display_config_xscreen);
+ ctk_object->mnu_display_config_twinview = gtk_menu_item_new_with_label("TwinView");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), ctk_object->mnu_display_config_twinview);
+ gtk_option_menu_set_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_display_config), menu);
+ ctk_config_set_tooltip(ctk_config, ctk_object->mnu_display_config,
+ __dpy_configuration_mnu_help);
+ g_signal_connect(G_OBJECT(ctk_object->mnu_display_config), "changed",
+ G_CALLBACK(display_config_changed),
(gpointer) ctk_object);
- ctk_object->txt_display_config = gtk_label_new("Disabled");
- gtk_misc_set_alignment(GTK_MISC(ctk_object->txt_display_config), 0.0f, 0.5f);
-
-
- /* Display configuration dialog */
- ctk_object->dlg_display_config = gtk_dialog_new_with_buttons
- ("Configure Display Device",
- GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
- | GTK_DIALOG_NO_SEPARATOR,
- GTK_STOCK_OK,
- GTK_RESPONSE_ACCEPT,
- NULL);
- ctk_object->btn_display_config_cancel =
- gtk_dialog_add_button(GTK_DIALOG(ctk_object->dlg_display_config),
- GTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL);
- ctk_object->rad_display_config_disabled =
- gtk_radio_button_new_with_label(NULL, "Disabled");
- ctk_object->rad_display_config_xscreen =
- gtk_radio_button_new_with_label_from_widget
- (GTK_RADIO_BUTTON(ctk_object->rad_display_config_disabled),
- "Separate X screen");
- ctk_object->rad_display_config_twinview =
- gtk_radio_button_new_with_label_from_widget
- (GTK_RADIO_BUTTON(ctk_object->rad_display_config_disabled),
- "TwinView");
- gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_display_config),
- FALSE);
/* Display disable dialog */
ctk_object->txt_display_disable = gtk_label_new("");
@@ -1631,8 +1638,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
{ /* Display page */
- GtkWidget *longest_hbox;
-
/* Generate the major vbox for the display section */
vbox = gtk_vbox_new(FALSE, 5);
ctk_object->display_page = vbox;
@@ -1640,16 +1645,15 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
/* Display Configuration */
hbox = gtk_hbox_new(FALSE, 5);
- /* XXX Pack widget later. Create it here so we can get its size */
- longest_hbox = hbox;
+ /* Pack widget into major vbox later.
+ * Create it here so we can get its size */
label = gtk_label_new("Configuration:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
gtk_widget_size_request(label, &req);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
- gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_config,
- FALSE, FALSE, 0);
- gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_display_config,
- FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->mnu_display_config,
+ TRUE, TRUE, 0);
+ ctk_object->box_display_config = hbox;
/* Display model name */
hbox = gtk_hbox_new(FALSE, 5);
@@ -1662,7 +1666,8 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
TRUE, TRUE, 0);
/* Pack the display configuration line */
- gtk_box_pack_start(GTK_BOX(vbox), longest_hbox, FALSE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), ctk_object->box_display_config,
+ FALSE, TRUE, 0);
/* Display resolution and refresh dropdowns */
hbox = gtk_hbox_new(FALSE, 5);
@@ -1851,24 +1856,6 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
{ /* Dialogs */
- /* Display Configuration Dialog */
- label = gtk_label_new("How should this display device be configured?");
- hbox = gtk_hbox_new(TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 20);
- gtk_box_pack_start
- (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox),
- hbox, TRUE, TRUE, 20);
- gtk_box_pack_start
- (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox),
- ctk_object->rad_display_config_disabled, FALSE, FALSE, 0);
- gtk_box_pack_start
- (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox),
- ctk_object->rad_display_config_xscreen, FALSE, FALSE, 0);
- gtk_box_pack_start
- (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox),
- ctk_object->rad_display_config_twinview, FALSE, FALSE, 0);
- gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_display_config)->vbox);
-
/* Display Disable Dialog */
hbox = gtk_hbox_new(TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_disable,
@@ -2059,8 +2046,6 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
static void setup_layout_frame(CtkDisplayConfig *ctk_object)
{
nvLayoutPtr layout = ctk_object->layout;
- nvGpuPtr gpu;
- int num_screens;
GdkScreen *s;
/*
@@ -2071,14 +2056,8 @@ static void setup_layout_frame(CtkDisplayConfig *ctk_object)
s = gtk_widget_get_screen(GTK_WIDGET(ctk_object));
screen_size_changed(s, ctk_object);
- /* Only allow Xinerama when there are multiple X screens */
- num_screens = 0;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- num_screens += gpu->num_screens;
- }
-
- /* Unselect Xinerama if only one (or no) X screen */
- if (num_screens <= 1) {
+ /* Xinerama requires 2 or more X screens */
+ if (layout->num_screens < 2) {
layout->xinerama_enabled = 0;
gtk_widget_hide(ctk_object->chk_xinerama_enabled);
return;
@@ -2146,20 +2125,68 @@ static void setup_display_config(CtkDisplayConfig *ctk_object)
{
nvDisplayPtr display = ctk_display_layout_get_selected_display
(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ nvScreenPtr screen = NULL;
+ int num_screens_on_gpu = 0;
if (!display) return;
- if (!display->screen) {
- gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_config),
- "Disabled");
- } else if (display->screen->num_displays == 1) {
- gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_config),
- "Separate X screen");
+ /* Don't allow disabling the last display device */
+ if (ctk_object->layout->num_screens == 1 &&
+ display->screen &&
+ display->screen->num_displays == 1) {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_config_disabled,
+ FALSE);
} else {
- gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_config),
- "TwinView");
+ gtk_widget_set_sensitive(ctk_object->mnu_display_config_disabled,
+ TRUE);
+ }
+
+
+ /* We can only have as many X screens on the GPU as it supports outputs */
+ for (screen = ctk_object->layout->screens;
+ screen;
+ screen = screen->next_in_layout) {
+ if (screen->gpu == display->gpu) {
+ num_screens_on_gpu++;
+ }
}
+ if (!display->screen &&
+ (num_screens_on_gpu >= display->gpu->max_displays)) {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_config_xscreen,
+ FALSE);
+ } else {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_config_xscreen,
+ TRUE);
+ }
+
+
+ /* We can't setup TwinView if there is only one display connected,
+ * there are no existing X screens on the GPU, or this display is
+ * the only enabled device on the GPU, or when SLI is enabled.
+ */
+ if (display->gpu->num_displays == 1 ||
+ !num_screens_on_gpu ||
+ (num_screens_on_gpu == 1 && display->screen) ||
+ (display->screen && display->screen->sli)) {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_config_twinview,
+ FALSE);
+ } else {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_config_twinview,
+ TRUE);
+ }
+
+ /* Select the current configuration option */
+ if (!display->screen) {
+ gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_object->mnu_display_config),
+ DPY_CFG_DISABLED); // Disabled
+ } else if (display->screen->num_displays > 1) {
+ gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_object->mnu_display_config),
+ DPY_CFG_TWINVIEW); // TwinView
+ } else {
+ gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_object->mnu_display_config),
+ DPY_CFG_SEPARATE_X_SCREEN); // XScreen
+ }
} /* setup_display_config() */
@@ -2570,22 +2597,24 @@ static void setup_display_resolution_dropdown(CtkDisplayConfig *ctk_object)
*
**/
-static GtkWidget* generate_display_modelname_dropdown
- (CtkDisplayConfig *ctk_object, int *cur_idx)
+static GtkWidget* generate_display_modelname_dropdown(CtkDisplayConfig *ctk_object,
+ int *cur_idx)
{
GtkWidget *menu;
GtkWidget *menu_item;
+ nvLayoutPtr layout = ctk_object->layout;
nvGpuPtr gpu;
nvDisplayPtr display;
int display_count = 0;
nvDisplayPtr d = ctk_display_layout_get_selected_display
(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
/* Create the display modelname lookup table for the dropdown */
if (ctk_object->display_model_table) {
free(ctk_object->display_model_table);
}
ctk_object->display_model_table_len = 0;
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
display_count += gpu->num_displays;
}
@@ -2601,8 +2630,11 @@ static GtkWidget* generate_display_modelname_dropdown
/* Generate the popup menu */
menu = gtk_menu_new();
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- for (display = gpu->displays; display; display = display->next) {
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ for (display = gpu->displays;
+ display;
+ display = display->next_on_gpu) {
+
gchar *str, *type;
if (d == display) {
*cur_idx = ctk_object->display_model_table_len;
@@ -2760,20 +2792,18 @@ static void setup_display_position_relative(CtkDisplayConfig *ctk_object)
idx = 0;
selected_idx = 0;
menu = gtk_menu_new();
- for (relative_to = display->gpu->displays;
+ for (relative_to = display->screen->displays;
relative_to;
- relative_to = relative_to->next) {
+ relative_to = relative_to->next_in_screen) {
- if (relative_to == display || relative_to->screen != display->screen) {
- continue;
- }
+ if (relative_to == display) continue;
if (relative_to == display->cur_mode->relative_to) {
selected_idx = idx;
}
ctk_object->display_position_table[idx] = relative_to;
-
+
menu_item = gtk_menu_item_new_with_label(relative_to->name);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
gtk_widget_show(menu_item);
@@ -2883,8 +2913,8 @@ static void setup_display_position(CtkDisplayConfig *ctk_object)
(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
- /* Hide the position box if this screen only has one display */
- if (!display || !display->screen || display->screen->num_displays <= 1) {
+ /* Need at least 2 displays in the X screen to configure position */
+ if (!display || !display->screen || (display->screen->num_displays < 2)) {
gtk_widget_hide(ctk_object->box_display_position);
return;
}
@@ -3282,9 +3312,9 @@ static void setup_screen_position_type(CtkDisplayConfig *ctk_object)
static void setup_screen_position_relative(CtkDisplayConfig *ctk_object)
{
+ nvLayoutPtr layout = ctk_object->layout;
nvScreenPtr screen;
nvScreenPtr relative_to;
- nvGpuPtr gpu;
int idx;
int selected_idx;
GtkWidget *menu;
@@ -3299,14 +3329,9 @@ static void setup_screen_position_relative(CtkDisplayConfig *ctk_object)
}
- /* Count the number of screens */
- ctk_object->screen_position_table_len = 0;
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- ctk_object->screen_position_table_len += gpu->num_screens;
- }
-
- /* Don't count the current screen */
- if (ctk_object->screen_position_table_len >= 1) {
+ /* Count the number of screens, not including the current one */
+ ctk_object->screen_position_table_len = layout->num_screens;
+ if (ctk_object->screen_position_table_len > 0) {
ctk_object->screen_position_table_len--;
}
@@ -3326,29 +3351,28 @@ static void setup_screen_position_relative(CtkDisplayConfig *ctk_object)
idx = 0;
selected_idx = 0;
menu = gtk_menu_new();
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- for (relative_to = gpu->screens;
- relative_to;
- relative_to = relative_to->next) {
- gchar *tmp_str;
+ for (relative_to = layout->screens;
+ relative_to;
+ relative_to = relative_to->next_in_layout) {
- if (relative_to == screen) continue;
+ gchar *tmp_str;
- if (relative_to == screen->relative_to) {
- selected_idx = idx;
- }
-
- ctk_object->screen_position_table[idx] = relative_to;
+ if (relative_to == screen) continue;
- tmp_str = g_strdup_printf("X screen %d",
- relative_to->scrnum);
- menu_item = gtk_menu_item_new_with_label(tmp_str);
- g_free(tmp_str);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
- gtk_widget_show(menu_item);
- idx++;
+ if (relative_to == screen->relative_to) {
+ selected_idx = idx;
}
+
+ ctk_object->screen_position_table[idx] = relative_to;
+
+ tmp_str = g_strdup_printf("X screen %d",
+ relative_to->scrnum);
+ menu_item = gtk_menu_item_new_with_label(tmp_str);
+ g_free(tmp_str);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ idx++;
}
@@ -3444,21 +3468,13 @@ static void setup_screen_position_offset(CtkDisplayConfig *ctk_object)
static void setup_screen_position(CtkDisplayConfig *ctk_object)
{
- nvGpuPtr gpu;
+ nvLayoutPtr layout = ctk_object->layout;
nvScreenPtr screen = ctk_display_layout_get_selected_screen
(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
- int num_screens;
- /* Count the number of screens */
- num_screens = 0;
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- num_screens += gpu->num_screens;
- }
-
-
- /* Hide the position box if there is only one screen */
- if (!screen || num_screens <= 1) {
+ /* Need at least 2 X screens to configure position */
+ if (!screen || (layout->num_screens < 2)) {
gtk_widget_hide(ctk_object->box_screen_position);
return;
}
@@ -3617,7 +3633,7 @@ static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object,
/* Verify each metamode with the metamodes that come before it */
for (i = 0; i < screen->num_metamodes; i++) {
-
+
/* Keep track of the first mode in case we need to assign
* a default resolution
*/
@@ -3629,18 +3645,16 @@ static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object,
* that have a (non NULL) mode set.
*/
num = 0;
- for (display = screen->gpu->displays;
+ for (display = screen->displays;
display;
- display = display->next) {
-
- if (display->screen != screen) continue;
+ display = display->next_in_screen) {
/* Check the mode that corresponds with the metamode */
mode = display->modes;
for (j = 0; j < i; j++) {
mode = mode->next;
}
-
+
if (!first_mode) {
first_mode = mode;
}
@@ -3787,18 +3801,18 @@ static gint validation_auto_fix_screen(CtkDisplayConfig *ctk_object,
static gint validation_auto_fix(CtkDisplayConfig *ctk_object)
{
nvLayoutPtr layout = ctk_object->layout;
- nvGpuPtr gpu;
nvScreenPtr screen;
gint success = 1;
/* Auto fix each screen */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- if (!validation_auto_fix_screen(ctk_object, screen)) {
- success = 0;
- break;
- }
+ for (screen = layout->screens;
+ screen;
+ screen = screen->next_in_layout) {
+
+ if (!validation_auto_fix_screen(ctk_object, screen)) {
+ success = 0;
+ break;
}
}
@@ -3861,12 +3875,10 @@ static gchar * validate_screen(nvScreenPtr screen)
/* Count the number of display devices used in the metamode */
num_displays = 0;
- for (display = screen->gpu->displays;
+ for (display = screen->displays;
display;
- display = display->next) {
+ display = display->next_in_screen) {
- if (display->screen != screen) continue;
-
mode = display->modes;
for (j = 0; j < i; j++) {
mode = mode->next;
@@ -3943,7 +3955,6 @@ static gchar * validate_screen(nvScreenPtr screen)
static int validate_layout(CtkDisplayConfig *ctk_object, int validation_type)
{
nvLayoutPtr layout = ctk_object->layout;
- nvGpuPtr gpu;
nvScreenPtr screen;
gchar *err_strs = NULL;
gchar *err_str;
@@ -3953,18 +3964,16 @@ static int validate_layout(CtkDisplayConfig *ctk_object, int validation_type)
/* Validate each screen and count the number of screens using abs. pos. */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- err_str = validate_screen(screen);
- if (err_str) {
- tmp = g_strconcat((err_strs ? err_strs : ""), err_str, NULL);
- g_free(err_strs);
- g_free(err_str);
- err_strs = tmp;
- }
- if (screen->position_type == CONF_ADJ_ABSOLUTE) {
- num_absolute++;
- }
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+ err_str = validate_screen(screen);
+ if (err_str) {
+ tmp = g_strconcat((err_strs ? err_strs : ""), err_str, NULL);
+ g_free(err_strs);
+ g_free(err_str);
+ err_strs = tmp;
+ }
+ if (screen->position_type == CONF_ADJ_ABSOLUTE) {
+ num_absolute++;
}
}
@@ -4172,28 +4181,11 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object,
nvDisplayPtr display)
{
nvLayoutPtr layout = ctk_object->layout;
- nvGpuPtr gpu;
nvScreenPtr screen;
nvScreenPtr rightmost = NULL;
nvScreenPtr other;
nvMetaModePtr metamode;
nvModePtr mode;
- int scrnum = 0;
-
-
- /* Get the next available screen number and the right-most screen */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- scrnum++;
-
- /* Compute the right-most screen */
- if (!rightmost ||
- ((screen->dim[X] + screen->dim[W]) >
- (rightmost->dim[X] + rightmost->dim[W]))) {
- rightmost = screen;
- }
- }
- }
/* Get resources */
@@ -4207,7 +4199,7 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object,
/* Setup the display */
- display->screen = screen;
+ screen_link_display(screen, display);
/* Setup the mode */
@@ -4231,19 +4223,25 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object,
/* Setup the screen */
- screen->scrnum = scrnum;
+ screen->scrnum = layout->num_screens;
screen->gpu = display->gpu;
-
+
other = layout_get_a_screen(layout, display->gpu);
screen->depth = other ? other->depth : 24;
- screen->displays_mask = display->device_mask;
- screen->num_displays = 1;
screen->metamodes = metamode;
screen->num_metamodes = 1;
screen->cur_metamode = metamode;
screen->cur_metamode_idx = 0;
+ /* Compute the right-most screen */
+ for (other = layout->screens; other; other = other->next_in_layout) {
+ if (!rightmost ||
+ ((other->dim[X] + other->dim[W]) >
+ (rightmost->dim[X] + rightmost->dim[W]))) {
+ rightmost = other;
+ }
+ }
/* Make the screen right-of the right-most screen */
if (rightmost) {
@@ -4257,15 +4255,11 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object,
screen->relative_to = NULL;
screen->dim[X] = mode->dim[X];
screen->dim[Y] = mode->dim[Y];
- }
-
+ }
- /* Add the screen at the end of the gpu's screen list */
- gpu = display->gpu;
- xconfigAddListItem((GenericListPtr *)(&gpu->screens),
- (GenericListPtr)screen);
- gpu->num_screens++;
+ /* Add the screen at the end of the layout's screen list */
+ layout_add_screen(layout, screen);
/* We can't dynamically add new X screens */
ctk_object->apply_possible = FALSE;
@@ -4283,27 +4277,29 @@ void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object,
* - Deleting all the implicit metamodes from the X screens that the
* GPU is driving.
*
- * - Making all X screens that are relative to displays on this GPU
- * relative to the first X screen instead. XXX This assumes we are
- * using the first X screen as the X screen to use for TwinView.
+ * - Making all the X screens in the layout that are relative to
+ * X screens driven by this GPU relative to 'use_screen' instead.
*
**/
static void prepare_gpu_for_twinview(CtkDisplayConfig *ctk_object,
- nvGpuPtr gpu)
+ nvGpuPtr gpu,
+ nvScreenPtr use_screen)
{
+ nvLayoutPtr layout = ctk_object->layout;
nvMetaModePtr metamode;
nvScreenPtr screen;
- nvGpuPtr other;
int m;
if (!gpu) return;
/* Delete implicit metamodes from all screens involved */
- for (screen = gpu->screens; screen; screen = screen->next) {
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
nvMetaModePtr next;
Bool updated = FALSE;
+ if (screen->gpu != gpu) continue;
+
m = 0;
metamode = screen->metamodes;
while (metamode) {
@@ -4334,17 +4330,33 @@ static void prepare_gpu_for_twinview(CtkDisplayConfig *ctk_object,
}
/* Make all other X screens in the layout relative to the GPU's
- * first X screen if they are relative to any display driven
- * by the GPU.
+ * 'use_screen' X screen if they are relative to any X screen driven
+ * by the GPU. Also, make the 'use_screen' inherit any primary
+ * device specified by other screens on the same GPU, as well as
+ * the NV-CONTROL handle and event objects so we can apply changes
+ * to the screen later on.
*/
- for (other = ctk_object->layout->gpus; other; other = other->next) {
-
- if (other == gpu) continue;
+ if (use_screen) {
+ for (screen = layout->screens;
+ screen;
+ screen = screen->next_in_layout) {
+
+ if (screen->gpu == gpu) {
+ if (!use_screen->primaryDisplay && screen->primaryDisplay) {
+ use_screen->primaryDisplay = screen->primaryDisplay;
+ }
+ if (!use_screen->handle && screen->handle) {
+ use_screen->handle = screen->handle;
+ screen->handle = NULL;
+ use_screen->ctk_event = screen->ctk_event;
+ screen->ctk_event = NULL;
+ }
+ continue;
+ }
- for (screen = other->screens; screen; screen = screen->next) {
if (screen->relative_to &&
screen->relative_to->gpu == gpu) {
- screen->relative_to = gpu->screens;
+ screen->relative_to = use_screen;
}
}
}
@@ -4374,7 +4386,7 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object,
/* Make sure a screen exists */
gpu = display->gpu;
- screen = gpu->screens;
+ screen = find_first_screen_on_gpu(gpu);
if (!screen) return;
@@ -4435,7 +4447,7 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object,
}
/* Delete implicit metamodes on all X Screens driven by the GPU */
- prepare_gpu_for_twinview(ctk_object, gpu);
+ prepare_gpu_for_twinview(ctk_object, gpu, screen);
/* Fix up the display's metamode list */
display_remove_modes(display);
@@ -4445,10 +4457,9 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object,
nvDisplayPtr other;
nvModePtr rightmost = NULL;
-
+
/* Get the right-most mode of the metamode */
- for (other = screen->gpu->displays; other; other = other->next) {
- if (other->screen != screen) continue;
+ for (other = screen->displays; other; other = other->next_in_screen) {
for (mode = other->modes; mode; mode = mode->next) {
if (!rightmost ||
((mode->dim[X] + mode->dim[W]) >
@@ -4496,9 +4507,7 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object,
/* Link the screen and display together */
- screen->displays_mask = new_mask;
- screen->num_displays++;
- display->screen = screen;
+ screen_link_display(screen, display);
} /* do_enable_display_for_twinview() */
@@ -4525,18 +4534,13 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object,
/* Get the next available screen number */
- scrnum = 0;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- scrnum++;
- }
- }
+ scrnum = layout->num_screens;
gpu = display->gpu;
/* Make sure there is just one display device per X screen */
- for (display = gpu->displays; display; display = display->next) {
+ for (display = gpu->displays; display; display = display->next_on_gpu) {
nvScreenPtr new_screen;
@@ -4552,9 +4556,6 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object,
new_screen->depth = screen->depth;
- new_screen->displays_mask = display->device_mask;
- new_screen->num_displays = 1;
-
/* Create a metamode for each mode on the display */
new_screen->num_metamodes = 0;
for (mode = display->modes; mode; mode = mode->next) {
@@ -4581,20 +4582,13 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object,
}
/* Move the display to the new screen */
- screen->num_displays--;
- screen->displays_mask &= ~(display->device_mask);
-
- display->screen = new_screen;
+ screen_unlink_display(display);
+ screen_link_display(new_screen, display);
if (display == screen->primaryDisplay) {
new_screen->primaryDisplay = display;
screen->primaryDisplay = NULL;
}
-
- /* Append the screen to the gpu */
- xconfigAddListItem((GenericListPtr *)(&gpu->screens),
- (GenericListPtr)new_screen);
- gpu->num_screens++;
/* Earlier display devices get first dibs on low screen numbers */
new_screen->handle = screen->handle;
@@ -4604,14 +4598,17 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object,
screen->ctk_event = NULL;
screen->scrnum = scrnum -1;
+ /* Add the screen to the layout */
+ layout_add_screen(layout, new_screen);
+
/* Can't apply creation of new screens */
ctk_object->apply_possible = FALSE;
}
/* Translate mode positional relationships to screen relationships */
- for (display = gpu->displays; display; display = display->next) {
-
+ for (display = gpu->displays; display; display = display->next_on_gpu) {
+
if (!display->screen) continue;
for (mode = display->modes; mode; mode = mode->next) {
@@ -4631,14 +4628,15 @@ static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object,
/** do_configure_display_for_twinview() ******************************
*
- * Configures the display's GPU for TwinView
+ * Configures the display's GPU for TwinView.
*
**/
static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object,
nvDisplayPtr display)
{
- nvScreenPtr screen;
+ nvLayoutPtr layout = ctk_object->layout;
+ nvScreenPtr use_screen; /* Screen that inherits all displays */
nvMetaModePtr metamode;
nvModePtr mode;
nvModePtr last_mode;
@@ -4646,33 +4644,39 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object,
int m;
- /* We need at least one screen to activate TwinView */
- if (!gpu || !gpu->screens) return;
+ if (!gpu) return;
+ /* Find screen on GPU with the lowest screen number */
+ use_screen = find_first_screen_on_gpu(gpu);
- /* Delete implicit metamodes on all X Screens driven by the GPU */
- prepare_gpu_for_twinview(ctk_object, gpu);
+ /* Need at least one screen to toggle into TwinView */
+ if (!use_screen) return;
- /* Make sure the screen has enough metamodes */
- screen = gpu->screens;
- for (display = gpu->displays; display; display = display->next) {
+ /* Delete implicit metamodes on all X screens driven by the GPU */
+ prepare_gpu_for_twinview(ctk_object, gpu, use_screen);
- /* Only add enabled displays to TwinView setup */
+
+ /* Make sure the screen has enough metamodes to accomodate all
+ * the displays.
+ */
+ for (display = gpu->displays; display; display = display->next_on_gpu) {
+
+ /* Only consider enabled displays for TwinView setup */
if (!display->screen) continue;
/* Make sure the screen has enough metamodes */
- for (m = display->num_modes - screen->num_metamodes; m > 0; m--) {
+ for (m = display->num_modes - use_screen->num_metamodes; m > 0; m--) {
metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode));
if (!metamode) break; // XXX Sigh.
-
+
metamode->source = METAMODE_SOURCE_NVCONTROL;
-
+
/* Add the metamode at the end of the screen's metamode list */
- xconfigAddListItem((GenericListPtr *)(&screen->metamodes),
+ xconfigAddListItem((GenericListPtr *)(&use_screen->metamodes),
(GenericListPtr)metamode);
- screen->num_metamodes++;
+ use_screen->num_metamodes++;
}
}
@@ -4680,18 +4684,18 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object,
/* Make sure each display has the right number of modes and that
* the modes point to the right metamode in the screen.
*/
- for (display = gpu->displays; display; display = display->next) {
+ for (display = gpu->displays; display; display = display->next_on_gpu) {
/* Only add enabled displays to TwinView setup */
if (!display->screen) continue;
/* Make the display mode point to the right metamode */
- metamode = screen->metamodes;
+ metamode = use_screen->metamodes;
mode = display->modes;
last_mode = NULL;
while (metamode && mode) {
- if (metamode == screen->cur_metamode) {
+ if (metamode == use_screen->cur_metamode) {
display->cur_mode = mode;
}
@@ -4706,7 +4710,9 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object,
nvDisplayPtr other;
/* Make the display relative to the other display */
- for (other = gpu->displays; other; other = other->next) {
+ for (other = gpu->displays;
+ other;
+ other = other->next_on_gpu) {
if (other->screen == display->screen->relative_to) {
mode->position_type = display->screen->position_type;
mode->relative_to = other;
@@ -4730,7 +4736,7 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object,
mode->dummy = 1;
mode->metamode = metamode;
- if (metamode == screen->cur_metamode) {
+ if (metamode == use_screen->cur_metamode) {
display->cur_mode = mode;
}
@@ -4753,66 +4759,36 @@ static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object,
}
- /* Make the displays part of the screen */
- for (display = gpu->displays; display; display = display->next) {
+ /* Make the GPU's active displays part of the screen */
+ for (display = gpu->displays; display; display = display->next_on_gpu) {
- /* Only add enabled displays to TwinView setup */
if (!display->screen) continue;
+ if (display->screen == use_screen) continue;
- if (display->screen != screen) {
- display->screen = screen;
- screen->displays_mask |= display->device_mask;
- screen->num_displays++;
- }
+ screen_unlink_display(display);
+ screen_link_display(use_screen, display);
}
/* Delete extra screens on the GPU */
- while (gpu->screens->next) {
+ {
nvScreenPtr other;
+ nvScreenPtr next;
- /* Delete screens that come before 'screen' */
- if (gpu->screens != screen) {
- other = gpu->screens;
- gpu->screens = other->next;
+ other = layout->screens;
+ next = layout->screens;
+ while (next) {
+ other = next;
+ next = other->next_in_layout;
- /* Delete screens that comes after 'screen' */
- } else {
- other = gpu->screens->next;
- gpu->screens->next = other->next;
- }
-
- /* Handle positional relationships going away */
- if (screen->relative_to == other) {
- screen->position_type = CONF_ADJ_ABSOLUTE;
- screen->relative_to = NULL;
- }
+ if (other->gpu != gpu) continue;
+ if (other == use_screen) continue;
- /* Clean up memory used by the screen */
- while (other->metamodes) {
- nvMetaModePtr metamode = other->metamodes;
- other->metamodes = metamode->next;
- free(metamode);
+ layout_remove_and_free_screen(other);
}
-
- /* Keep the lowest screen number */
- if (other->scrnum < screen->scrnum) {
- if (screen->handle) {
- NvCtrlAttributeClose(screen->handle);
- }
- screen->scrnum = other->scrnum;
- screen->handle = other->handle;
- screen->ctk_event = other->ctk_event;
- } else {
- if (other->handle) {
- NvCtrlAttributeClose(other->handle);
- }
- }
-
- free(other);
- gpu->num_screens--;
}
+
/* Make sure screen numbering is consistent */
renumber_xscreens(ctk_object->layout);
@@ -4903,139 +4879,31 @@ void do_disable_display(CtkDisplayConfig *ctk_object, nvDisplayPtr display)
-/** display_config_clicked() *****************************************
+/** display_config_changed() *****************************************
*
- * Called when user clicks on the display configuration button.
+ * Called when user selects an option in the display configuration menu.
*
**/
-static void display_config_clicked(GtkWidget *widget, gpointer user_data)
+static void display_config_changed(GtkWidget *widget, gpointer user_data)
{
CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvLayoutPtr layout = ctk_object->layout;
nvDisplayPtr display = ctk_display_layout_get_selected_display
- (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
- gint result;
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ nvScreenPtr screen;
gboolean update = FALSE;
- nvGpuPtr gpu;
- int num_screens;
-
-
- if (!display) return;
-
-
- /* Don't allow disabling the last display device */
- num_screens = 0;
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- num_screens += gpu->num_screens;
- }
- if (num_screens == 1 && display->screen &&
- display->screen->num_displays == 1) {
- gtk_widget_set_sensitive(ctk_object->rad_display_config_disabled,
- FALSE);
- } else {
- gtk_widget_set_sensitive(ctk_object->rad_display_config_disabled,
- TRUE);
- }
-
-
- /* We can only enable as many X screens as the GPU supports */
- if (!display->screen &&
- (display->gpu->num_screens >= display->gpu->max_displays)) {
- gtk_widget_set_sensitive(ctk_object->rad_display_config_xscreen,
- FALSE);
- } else {
- gtk_widget_set_sensitive(ctk_object->rad_display_config_xscreen,
- TRUE);
- }
-
-
- /* We can't setup TwinView if there is only one display connected,
- * there are no existing X screens on the GPU, or this display is
- * the only enabled device on the GPU, or when SLI is enabled.
- */
- if (display->gpu->num_displays == 1 || !display->gpu->num_screens ||
- display->gpu->screens->sli ||
- (display->gpu->num_screens == 1 &&
- display->gpu->screens->num_displays == 1 &&
- display->screen == display->gpu->screens)) {
- gtk_widget_set_sensitive(ctk_object->rad_display_config_twinview,
- FALSE);
- } else {
- gtk_widget_set_sensitive(ctk_object->rad_display_config_twinview,
- TRUE);
- }
-
-
- /* Setup the button state */
- if (!display->screen) {
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_disabled),
- TRUE);
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_disabled),
- "Disabled");
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_xscreen),
- "Separate X screen (requires X restart)");
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_twinview),
- "TwinView");
-
- } else if (display->screen->num_displays > 1) {
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview),
- TRUE);
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_disabled),
- "Disabled");
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_xscreen),
- "Separate X screen (requires X restart)");
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_twinview),
- "TwinView");
-
- } else {
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen),
- TRUE);
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_disabled),
- "Disabled (requires X restart)");
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_xscreen),
- "Separate X screen");
- gtk_button_set_label
- (GTK_BUTTON(ctk_object->rad_display_config_twinview),
- "TwinView (requires X restart)");
- }
-
+ gint position_idx;
- /* Show the display config dialog */
- gtk_window_set_transient_for
- (GTK_WINDOW(ctk_object->dlg_display_config),
- GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
- gtk_widget_show_all(ctk_object->dlg_display_config);
- gtk_widget_grab_focus(ctk_object->btn_display_config_cancel);
- result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_display_config));
- gtk_widget_hide(ctk_object->dlg_display_config);
-
- switch (result)
- {
- case GTK_RESPONSE_ACCEPT:
- /* OK */
- break;
-
- case GTK_RESPONSE_CANCEL:
- default:
- /* Cancel */
+ if (!display) {
return;
}
+ position_idx = gtk_option_menu_get_history(GTK_OPTION_MENU(
+ ctk_object->mnu_display_config));
-
- if (gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_disabled))) {
+ /* Disabled was selected. */
+ if (position_idx == DPY_CFG_DISABLED) {
if (display->screen) {
do_disable_display(ctk_object, display);
update = TRUE;
@@ -5061,15 +4929,14 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data)
if (!display->screen) {
/* Enable display as a separate X screen */
- if (gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen))) {
+ if (position_idx == DPY_CFG_SEPARATE_X_SCREEN) {
+
do_enable_display_for_xscreen(ctk_object, display);
update = TRUE;
}
/* Enable display in TwinView with an existing screen */
- if (gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview))) {
+ if (position_idx == DPY_CFG_TWINVIEW) {
do_enable_display_for_twinview(ctk_object, display);
update = TRUE;
}
@@ -5078,16 +4945,14 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data)
/* Move display to a new X screen */
if (display->screen->num_displays > 1 &&
- gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen))) {
+ position_idx == DPY_CFG_SEPARATE_X_SCREEN) {
do_configure_display_for_xscreen(ctk_object, display);
update = TRUE;
}
/* Setup TwinView on the first X screen */
if (display->screen->num_displays == 1 &&
- gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview))) {
+ position_idx == DPY_CFG_TWINVIEW) {
do_configure_display_for_twinview(ctk_object, display);
update = TRUE;
}
@@ -5109,13 +4974,11 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data)
ctk_display_layout_update(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
/* Auto fix all screens on the gpu */
- {
- nvGpuPtr gpu = display->gpu;
- nvScreenPtr screen;
-
- for (screen = gpu->screens; screen; screen = screen->next) {
- validation_auto_fix_screen(ctk_object, screen);
- }
+ for (screen = layout->screens;
+ screen;
+ screen = screen->next_in_layout) {
+ if (screen->gpu != display->gpu) continue;
+ validation_auto_fix_screen(ctk_object, screen);
}
/* Redraw */
@@ -5129,7 +4992,7 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data)
user_changed_attributes(ctk_object);
}
-} /* display_config_clicked() */
+} /* display_config_changed() */
@@ -5367,7 +5230,7 @@ static void display_position_relative_changed(GtkWidget *widget,
/* Get the new display to be relative to */
position_idx = gtk_option_menu_get_history
- (GTK_OPTION_MENU(ctk_object->mnu_display_position_type));
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_type));
position_type = __position_table[position_idx];
@@ -6493,7 +6356,7 @@ static int update_screen_metamodes(CtkDisplayConfig *ctk_object,
static void apply_clicked(GtkWidget *widget, gpointer user_data)
{
CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
- nvGpuPtr gpu;
+ nvScreenPtr screen;
ReturnStatus ret;
gboolean clear_apply = TRUE;
@@ -6511,58 +6374,55 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data)
/* Temporarily unregister events */
unregister_layout_events(ctk_object);
- /* Update all GPUs */
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- nvScreenPtr screen;
+ /* Update all X screens */
+ for (screen = ctk_object->layout->screens;
+ screen;
+ screen = screen->next_in_layout) {
- /* Update all X screens */
- for (screen = gpu->screens; screen; screen = screen->next) {
+ if (!screen->handle) continue;
+ if (screen->no_scanout) continue;
- if (!screen->handle) continue;
- if (screen->no_scanout) continue;
+ if (!update_screen_metamodes(ctk_object, screen)) {
+ clear_apply = FALSE;
+ } else {
+ ReturnStatus ret;
- if (!update_screen_metamodes(ctk_object, screen)) {
- clear_apply = FALSE;
- } else {
- ReturnStatus ret;
+ ret = NvCtrlSetDisplayAttributeWithReply
+ (screen->handle, 0,
+ NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
+ screen->displays_mask);
- ret = NvCtrlSetDisplayAttributeWithReply
- (screen->handle, 0,
- NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
- screen->displays_mask);
-
- if (ret != NvCtrlSuccess) {
- nv_error_msg("Failed to set screen %d's association mask "
- "to: 0x%08x",
- screen->scrnum, screen->displays_mask);
- } else {
- /* Make sure other parts of nvidia-settings get updated */
- ctk_event_emit(screen->ctk_event, 0,
- NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
- screen->displays_mask);
- }
+ if (ret != NvCtrlSuccess) {
+ nv_error_msg("Failed to set screen %d's association mask "
+ "to: 0x%08x",
+ screen->scrnum, screen->displays_mask);
+ } else {
+ /* Make sure other parts of nvidia-settings get updated */
+ ctk_event_emit(screen->ctk_event, 0,
+ NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
+ screen->displays_mask);
}
-
- if (screen->primaryDisplay && ctk_object->primary_display_changed) {
- gchar *primary_str =
- display_get_type_str(screen->primaryDisplay->device_mask,
- 0);
-
- ret = NvCtrlSetStringAttribute(screen->handle,
- NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER,
- primary_str, NULL);
- g_free(primary_str);
-
- if (ret != NvCtrlSuccess) {
- nv_error_msg("Failed to set primary display"
- "for screen %d (GPU:%s)", screen->scrnum,
- screen->gpu->name);
- } else {
- /* Make sure other parts of nvidia-settings get updated */
- ctk_event_emit_string(screen->ctk_event, 0,
- NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER);
- ctk_object->primary_display_changed = FALSE;
- }
+ }
+
+ if (screen->primaryDisplay && ctk_object->primary_display_changed) {
+ gchar *primary_str =
+ display_get_type_str(screen->primaryDisplay->device_mask,
+ 0);
+
+ ret = NvCtrlSetStringAttribute(screen->handle,
+ NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER,
+ primary_str, NULL);
+ g_free(primary_str);
+
+ if (ret != NvCtrlSuccess) {
+ nv_error_msg("Failed to set primary display"
+ "for screen %d (GPU:%s)", screen->scrnum,
+ screen->gpu->name);
+ } else {
+ /* Make sure other parts of nvidia-settings get updated */
+ ctk_event_emit_string(screen->ctk_event, 0,
+ NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER);
+ ctk_object->primary_display_changed = FALSE;
}
}
}
@@ -6959,18 +6819,15 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object,
/* Configure screen for scanout */
/* Find the first display on the screen */
- for (display = screen->gpu->displays; display; display = display->next) {
- if (display->screen == screen) {
- break;
- }
- }
+ display = screen->displays;;
+
if (!display) {
nv_error_msg("Unable to find a display device for screen %d!",
screen->scrnum);
goto fail;
}
-
+
/* Create the screen's only Monitor section from the first display */
if (!add_monitor_to_xconfig(display, config, screen->scrnum)) {
nv_error_msg("Failed to add display device '%s' to screen %d!",
@@ -6986,24 +6843,22 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object,
/* Add the modelines of all other connected displays to the monitor */
- for (other = screen->gpu->displays; other; other = other->next) {
- if (other->screen != screen) continue;
- if (other == display) continue;
-
- /* Add modelines used by this display */
+ for (other = display->next_in_screen;
+ other;
+ other = other->next_in_screen) {
add_modelines_to_monitor(display->conf_monitor, other->modes);
}
/* Set the TwinView option */
xconfigAddNewOption(&conf_screen->options, "TwinView",
((screen->num_displays > 1) ? "1" : "0" ));
-
+
/* Set the TwinviewXineramaInfoOrder option */
-
+
if (screen->primaryDisplay) {
gchar *primary_str =
display_get_type_str(screen->primaryDisplay->device_mask, 0);
-
+
xconfigAddNewOption(&conf_screen->options, "TwinViewXineramaInfoOrder",
primary_str);
g_free(primary_str);
@@ -7070,34 +6925,40 @@ static int add_screen_to_xconfig(CtkDisplayConfig *ctk_object,
*/
static int get_device_screen_id(nvGpuPtr gpu, nvScreenPtr screen)
{
+ nvLayoutPtr layout = gpu->layout;
nvScreenPtr other;
int device_screen_id;
+ int num_screens_on_gpu;
/* Go through the GPU's screens and figure out what the
* GPU-relative screen number should be for the given
* screen's device section.
+ *
+ * This is done by counting the number of screens that
+ * have a screen number that is lower than the given
+ * screen, and that's the relative position of this
+ * screen wrt the GPU.
*/
- /* If there is one screen, the device section shouldn't
- * specify a "Screen #"
- */
-
- if (gpu->num_screens < 2) return -1;
+ device_screen_id = 0;
+ num_screens_on_gpu = 0;
+ for (other = layout->screens; other; other = other->next_in_layout) {
+ if (other->gpu != gpu) continue;
+ num_screens_on_gpu++;
- /* Count the number of screens that have a screen number
- * that is lower than the given screen, and that's the
- * relative position of this screen wrt the GPU.
- */
-
- device_screen_id = 0;
- for (other = gpu->screens; other; other = other->next) {
if (other == screen) continue;
+
if (screen->scrnum > other->scrnum) {
device_screen_id++;
}
}
+ /* If there is only one screen on the GPU, the device
+ * section shouldn't specify a "Screen #"
+ */
+ if (num_screens_on_gpu < 2) return -1;
+
return device_screen_id;
} /* get_device_screen_id() */
@@ -7112,7 +6973,6 @@ static int get_device_screen_id(nvGpuPtr gpu, nvScreenPtr screen)
static int add_screens_to_xconfig(CtkDisplayConfig *ctk_object,
nvLayoutPtr layout, XConfigPtr config)
{
- nvGpuPtr gpu;
nvScreenPtr screen;
int device_screen_id;
int print_bus_ids;
@@ -7127,8 +6987,8 @@ static int add_screens_to_xconfig(CtkDisplayConfig *ctk_object,
/* Don't print the bus ID in the case where we have a single
* GPU driving a single X screen
*/
- if (layout->num_gpus == 1 &&
- layout->gpus->num_screens == 1) {
+ if ((layout->num_gpus == 1) &&
+ (layout->num_screens == 1)) {
print_bus_ids = 0;
} else {
print_bus_ids = 1;
@@ -7136,37 +6996,35 @@ static int add_screens_to_xconfig(CtkDisplayConfig *ctk_object,
/* Generate the Device sections and Screen sections */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
-
- for (screen = gpu->screens; screen; screen = screen->next) {
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+ nvGpuPtr gpu = screen->gpu;
- /* Figure out what screen number to use for the device section. */
- device_screen_id = get_device_screen_id(gpu, screen);
+ /* Figure out what screen number to use for the device section. */
+ device_screen_id = get_device_screen_id(gpu, screen);
- /* Each screen needs a unique device section
- *
- * Note that the device id used to name the
- * device section is the same as the screen
- * number such that the name of the two sections
- * match.
- */
- screen->conf_device = add_device_to_xconfig(gpu, config,
- screen->scrnum,
- device_screen_id,
- print_bus_ids);
- if (!screen->conf_device) {
- nv_error_msg("Failed to add device '%s' to X config.",
- gpu->name);
- goto fail;
- }
+ /* Each screen needs a unique device section
+ *
+ * Note that the device id used to name the
+ * device section is the same as the screen
+ * number such that the name of the two sections
+ * match.
+ */
+ screen->conf_device = add_device_to_xconfig(gpu, config,
+ screen->scrnum,
+ device_screen_id,
+ print_bus_ids);
+ if (!screen->conf_device) {
+ nv_error_msg("Failed to add device '%s' to X config.",
+ gpu->name);
+ goto fail;
+ }
- ret = add_screen_to_xconfig(ctk_object, screen, config);
- if (ret == XCONFIG_GEN_ERROR) {
- nv_error_msg("Failed to add X screen %d to X config.",
- screen->scrnum);
- }
- if (ret != XCONFIG_GEN_OK) goto bail;
+ ret = add_screen_to_xconfig(ctk_object, screen, config);
+ if (ret == XCONFIG_GEN_ERROR) {
+ nv_error_msg("Failed to add X screen %d to X config.",
+ screen->scrnum);
}
+ if (ret != XCONFIG_GEN_OK) goto bail;
}
return XCONFIG_GEN_OK;
@@ -7235,7 +7093,6 @@ static Bool add_adjacency_to_xconfig(nvScreenPtr screen, XConfigPtr config)
static Bool add_layout_to_xconfig(nvLayoutPtr layout, XConfigPtr config)
{
XConfigLayoutPtr conf_layout;
- nvGpuPtr gpu;
nvScreenPtr screen;
int scrnum;
@@ -7251,20 +7108,21 @@ static Bool add_layout_to_xconfig(nvLayoutPtr layout, XConfigPtr config)
/* Clean up the adjacencies */
xconfigFreeAdjacencyList(&conf_layout->adjacencies);
-
+
/* Assign the adjacencies (in order) */
scrnum = 0;
do {
+ /* Find the next screen to write */
screen = NULL;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- if (screen->scrnum == scrnum) break;
- }
- if (screen) {
- if (!add_adjacency_to_xconfig(screen, config)) goto fail;
- break;
- }
+ for (screen = layout->screens;
+ screen;
+ screen = screen->next_in_layout) {
+ if (screen->scrnum == scrnum) break;
+ }
+ if (screen) {
+ if (!add_adjacency_to_xconfig(screen, config)) goto fail;
}
+
scrnum++;
} while (screen);
@@ -7478,6 +7336,7 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data)
CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
unsigned int probed_displays;
unsigned int mask;
+ nvLayoutPtr layout = ctk_object->layout;
nvGpuPtr gpu;
nvDisplayPtr display;
nvDisplayPtr selected_display = ctk_display_layout_get_selected_display
@@ -7487,7 +7346,7 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data)
gchar *str;
/* Probe each GPU for display changes */
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
if (!gpu->handle) continue;
diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h
index 03919ca..c6f88fc 100644
--- a/src/gtk+-2.x/ctkdisplayconfig.h
+++ b/src/gtk+-2.x/ctkdisplayconfig.h
@@ -83,9 +83,12 @@ typedef struct _CtkDisplayConfig
int display_model_table_len;
GtkWidget *txt_display_gpu;
- GtkWidget *btn_display_config;
- GtkWidget *txt_display_config;
-
+ GtkWidget *box_display_config;
+ GtkWidget *mnu_display_config;
+ GtkWidget *mnu_display_config_disabled;
+ GtkWidget *mnu_display_config_xscreen;
+ GtkWidget *mnu_display_config_twinview;
+
/* Display - Settings */
GtkWidget *box_display_resolution;
GtkWidget *mnu_display_resolution;
@@ -138,12 +141,6 @@ typedef struct _CtkDisplayConfig
int screen_depth_table_len;
/* Dialogs */
- GtkWidget *dlg_display_config;
- GtkWidget *rad_display_config_disabled;
- GtkWidget *rad_display_config_xscreen;
- GtkWidget *rad_display_config_twinview;
- GtkWidget *btn_display_config_cancel;
-
GtkWidget *dlg_display_disable;
GtkWidget *txt_display_disable;
GtkWidget *btn_display_disable_off;
diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c
index c116b59..010a559 100644
--- a/src/gtk+-2.x/ctkdisplaylayout.c
+++ b/src/gtk+-2.x/ctkdisplaylayout.c
@@ -170,7 +170,7 @@ static void zorder_layout(CtkDisplayLayout *ctk_object)
nvGpuPtr gpu;
nvScreenPtr screen;
nvDisplayPtr display;
- int i;
+ int z;
/* Clean up */
@@ -183,8 +183,9 @@ static void zorder_layout(CtkDisplayLayout *ctk_object)
/* Count the number of Z-orderable elements in the layout */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- ctk_object->Zcount += gpu->num_displays + gpu->num_screens;
+ ctk_object->Zcount = layout->num_screens;
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ ctk_object->Zcount += gpu->num_displays;
}
@@ -203,31 +204,35 @@ static void zorder_layout(CtkDisplayLayout *ctk_object)
/* Populate the Z-order list */
- i = 0;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- // Add screens
- for (screen = gpu->screens; screen; screen = screen->next) {
- // Add displays that belong to the screen
- for (display = gpu->displays; display; display = display->next) {
- if (display->screen == screen) {
- ctk_object->Zorder[i].type = ZNODE_TYPE_DISPLAY;
- ctk_object->Zorder[i].u.display = display;
- i++;
- }
- }
+ z = 0;
+
+ /* Add screens */
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
- // Add the screen
- ctk_object->Zorder[i].type = ZNODE_TYPE_SCREEN;
- ctk_object->Zorder[i].u.screen = screen;
- i++;
+ /* Add displays that belong to the screen */
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
+ ctk_object->Zorder[z].type = ZNODE_TYPE_DISPLAY;
+ ctk_object->Zorder[z].u.display = display;
+ z++;
}
- // Add displays that don't have screens.
- for (display = gpu->displays; display; display = display->next) {
- if (!display->screen) {
- ctk_object->Zorder[i].type = ZNODE_TYPE_DISPLAY;
- ctk_object->Zorder[i].u.display = display;
- i++;
- }
+
+ /* Add the screen */
+ ctk_object->Zorder[z].type = ZNODE_TYPE_SCREEN;
+ ctk_object->Zorder[z].u.screen = screen;
+ z++;
+ }
+
+ /* Add displays that don't have screens */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ for (display = gpu->displays;
+ display;
+ display = display->next_on_gpu) {
+ if (display->screen) continue;
+ ctk_object->Zorder[z].type = ZNODE_TYPE_DISPLAY;
+ ctk_object->Zorder[z].u.display = display;
+ z++;
}
}
@@ -378,9 +383,9 @@ static Bool get_modify_info(CtkDisplayLayout *ctk_object)
* relative positioning.
*/
use_screen_instead = TRUE;
- for (display = info->display->gpu->displays; display;
- display = display->next) {
- if (display->screen != info->screen) continue;
+ for (display = info->display->screen->displays;
+ display;
+ display = display->next_in_screen) {
if (display == info->display) continue;
if (!display->cur_mode) continue;
if (display->cur_mode->position_type == CONF_ADJ_ABSOLUTE) {
@@ -588,15 +593,16 @@ static void offset_layout(nvLayoutPtr layout, int x, int y)
layout->dim[X] += x;
layout->dim[Y] += y;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
-
- /* Offset screens */
- for (screen = gpu->screens; screen; screen = screen->next) {
- offset_screen(screen, x, y);
- }
+ /* Offset screens */
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+ offset_screen(screen, x, y);
+ }
- /* Offset displays */
- for (display = gpu->displays; display; display = display->next) {
+ /* Offset displays */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ for (display = gpu->displays;
+ display;
+ display = display->next_on_gpu) {
offset_display(display, x, y);
}
}
@@ -700,9 +706,9 @@ static void resolve_displays_in_screen(nvScreenPtr screen,
}
/* Resolve the current mode of each display in the screen */
- for (display = screen->gpu->displays; display; display = display->next) {
-
- if (display->screen != screen) continue;
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
for (mode_idx = first_idx; mode_idx <= last_idx; mode_idx++) {
if (resolve_display(display, mode_idx, pos)) {
@@ -808,24 +814,21 @@ static void resolve_screen_in_layout(nvScreenPtr screen)
int x, y;
int *sdim;
-
+
/* Resolve the current screen location */
if (resolve_screen(screen, pos)) {
/* Move the screen and the displays by offsetting */
sdim = get_screen_dim(screen, 0);
-
+
x = pos[X] - sdim[X];
y = pos[Y] - sdim[Y];
offset_screen(screen, x, y);
- for (display = screen->gpu->displays;
+ for (display = screen->displays;
display;
- display = display->next) {
-
- if (display->screen != screen) continue;
-
+ display = display->next_in_screen) {
offset_mode(display->cur_mode, x, y);
}
}
@@ -843,23 +846,18 @@ static void resolve_screen_in_layout(nvScreenPtr screen)
static void resolve_layout(nvLayoutPtr layout)
{
- nvGpuPtr gpu;
nvScreenPtr screen;
/* First, resolve TwinView relationships */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- resolve_displays_in_screen(screen, 0);
- }
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+ resolve_displays_in_screen(screen, 0);
}
/* Next, resolve X screen relationships */
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- resolve_screen_in_layout(screen);
- }
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+ resolve_screen_in_layout(screen);
}
-
+
} /* resolve_layout() */
@@ -896,9 +894,9 @@ static void calc_metamode(nvScreenPtr screen, nvMetaModePtr metamode)
dim[H] = edim[H] = 0;
/* Calculate its dimensions */
- for (display = screen->gpu->displays; display; display = display->next) {
-
- if (display->screen != screen) continue;
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
/* Get the display's mode that is part of the metamode. */
for (mode = display->modes; mode; mode = mode->next) {
@@ -1001,12 +999,11 @@ static void calc_screen(nvScreenPtr screen)
/** calc_layout() ****************************************************
*
* Calculates the dimensions (width & height) of the layout. This is
- * the smallest bounding box that holds all the gpu's X screen's
- * display device's (current) modes in the layout. (Bounding box of
- * all the current metamodes of all X screens.)
- *
- * As a side effect, all other screen/metamode dimensions are
- * calculated.
+ * the smallest bounding box that holds all the metamodes of all X
+ * screens as well as dummy modes for disabled displays.
+
+ * As a side effect, the dimensions of all metamodes for all X
+ * screens are (re)calculated.
*
**/
@@ -1030,28 +1027,25 @@ static void calc_layout(nvLayoutPtr layout)
dim[W] = 0;
dim[H] = 0;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+ int *sdim;
- for (screen = gpu->screens; screen; screen = screen->next) {
- int *sdim;
-
- calc_screen(screen);
- sdim = get_screen_dim(screen, 0);
-
- if (init) {
- dim[X] = sdim[X];
- dim[Y] = sdim[Y];
- dim[W] = sdim[X] +sdim[W];
- dim[H] = sdim[Y] +sdim[H];
- init = 0;
- continue;
- }
-
- dim[X] = MIN(dim[X], sdim[X]);
- dim[Y] = MIN(dim[Y], sdim[Y]);
- dim[W] = MAX(dim[W], sdim[X] +sdim[W]);
- dim[H] = MAX(dim[H], sdim[Y] +sdim[H]);
+ calc_screen(screen);
+ sdim = get_screen_dim(screen, 0);
+
+ if (init) {
+ dim[X] = sdim[X];
+ dim[Y] = sdim[Y];
+ dim[W] = sdim[X] +sdim[W];
+ dim[H] = sdim[Y] +sdim[H];
+ init = 0;
+ continue;
}
+
+ dim[X] = MIN(dim[X], sdim[X]);
+ dim[Y] = MIN(dim[Y], sdim[Y]);
+ dim[W] = MAX(dim[W], sdim[X] +sdim[W]);
+ dim[H] = MAX(dim[H], sdim[Y] +sdim[H]);
}
dim[W] = dim[W] - dim[X];
@@ -1061,8 +1055,10 @@ static void calc_layout(nvLayoutPtr layout)
/* Position disabled display devices off to the top right */
x = dim[W] + dim[X];
y = dim[Y];
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (display = gpu->displays; display; display = display->next) {
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ for (display = gpu->displays;
+ display;
+ display = display->next_on_gpu) {
if (display->screen) continue;
display->cur_mode->dim[X] = x;
@@ -1092,10 +1088,10 @@ static void recenter_screen(nvScreenPtr screen)
{
nvDisplayPtr display;
- for (display = screen->gpu->displays; display; display = display->next) {
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
nvModePtr mode;
-
- if (display->screen != screen) continue;
for (mode = display->modes; mode; mode = mode->next) {
int offset_x = (screen->dim[X] - mode->metamode->dim[X]);
@@ -1103,7 +1099,7 @@ static void recenter_screen(nvScreenPtr screen)
offset_mode(mode, offset_x, offset_y);
}
}
-
+
/* Recalculate the screen's dimensions */
calc_screen(screen);
@@ -1129,10 +1125,9 @@ static void set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen,
screen->cur_metamode = get_metamode(screen, new_metamode_idx);
/* Make each display within the screen point to the new mode */
- for (display = screen->gpu->displays; display; display = display->next) {
-
- if (display->screen != screen) continue; /* Display not in screen */
-
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
display->cur_mode = get_mode(display, new_metamode_idx);
}
@@ -1154,28 +1149,24 @@ static void set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen,
static void recenter_layout(nvLayoutPtr layout)
{
- nvGpuPtr gpu;
nvScreenPtr screen;
int real_metamode_idx;
int metamode_idx;
-
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
-
- real_metamode_idx = screen->cur_metamode_idx;
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
- for (metamode_idx = 0;
- metamode_idx < screen->num_metamodes;
- metamode_idx++) {
-
- if (metamode_idx == real_metamode_idx) continue;
+ real_metamode_idx = screen->cur_metamode_idx;
- set_screen_metamode(layout, screen, metamode_idx);
- }
+ for (metamode_idx = 0;
+ metamode_idx < screen->num_metamodes;
+ metamode_idx++) {
+
+ if (metamode_idx == real_metamode_idx) continue;
- set_screen_metamode(layout, screen, real_metamode_idx);
+ set_screen_metamode(layout, screen, metamode_idx);
}
+
+ set_screen_metamode(layout, screen, real_metamode_idx);
}
} /* recenter_layout() */
@@ -1425,7 +1416,7 @@ static void snap_move(CtkDisplayLayout *ctk_object)
int *bh;
int i;
int dist;
- nvGpuPtr gpu;
+ nvLayoutPtr layout = ctk_object->layout;
nvScreenPtr screen;
nvDisplayPtr other;
int *sdim;
@@ -1500,69 +1491,68 @@ static void snap_move(CtkDisplayLayout *ctk_object)
} /* Done snapping to other displays */
- /* Snap to other screen dimensions */
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- if (screen == info->screen) continue;
+ /* Snap to dimensions of other X screens */
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
- /* NOTE: When the (display devices's) screens are relative to
- * each other, we may still want to allow snapping of the
- * non-related edges. This is useful, for example, when
- * two screens have a right of/left of relationtship and
- * one of them is taller.
- */
+ if (screen == info->screen) continue;
- bv = &info->best_snap_v;
- bh = &info->best_snap_h;
+ /* NOTE: When the (display devices's) screens are relative to
+ * each other, we may still want to allow snapping of the
+ * non-related edges. This is useful, for example, when
+ * two screens have a right of/left of relationtship and
+ * one of them is taller.
+ */
- if (((screen->position_type == CONF_ADJ_RIGHTOF) ||
- (screen->position_type == CONF_ADJ_LEFTOF)) &&
- (screen->relative_to == info->screen)) {
- bh = NULL;
- }
- if (((info->screen->position_type == CONF_ADJ_RIGHTOF) ||
- (info->screen->position_type == CONF_ADJ_LEFTOF)) &&
- (info->screen->relative_to == screen)) {
- bh = NULL;
- }
+ bv = &info->best_snap_v;
+ bh = &info->best_snap_h;
- /* If we aren't snapping horizontally with the other screen,
- * we shouldn't snap vertically either if we are moving the
- * top-most display in the screen.
- */
- if (!bh &&
- info->display &&
- info->display->cur_mode->dim[Y] == info->screen->dim[Y]) {
- bv = NULL;
- }
-
- if (((screen->position_type == CONF_ADJ_ABOVE) ||
- (screen->position_type == CONF_ADJ_BELOW)) &&
- (screen->relative_to == info->screen)) {
- bv = NULL;
- }
- if (((info->screen->position_type == CONF_ADJ_ABOVE) ||
- (info->screen->position_type == CONF_ADJ_BELOW)) &&
- (info->screen->relative_to == screen)) {
- bv = NULL;
- }
+ if (((screen->position_type == CONF_ADJ_RIGHTOF) ||
+ (screen->position_type == CONF_ADJ_LEFTOF)) &&
+ (screen->relative_to == info->screen)) {
+ bh = NULL;
+ }
+ if (((info->screen->position_type == CONF_ADJ_RIGHTOF) ||
+ (info->screen->position_type == CONF_ADJ_LEFTOF)) &&
+ (info->screen->relative_to == screen)) {
+ bh = NULL;
+ }
- /* If we aren't snapping vertically with the other screen,
- * we shouldn't snap horizontally either if this is the
- * left-most display in the screen.
- */
- if (!bv &&
- info->display &&
- info->display->cur_mode->dim[X] == info->screen->dim[X]) {
- bh = NULL;
- }
+ /* If we aren't snapping horizontally with the other screen,
+ * we shouldn't snap vertically either if we are moving the
+ * top-most display in the screen.
+ */
+ if (!bh &&
+ info->display &&
+ info->display->cur_mode->dim[Y] == info->screen->dim[Y]) {
+ bv = NULL;
+ }
- sdim = get_screen_dim(screen, 0);
- snap_dim_to_dim(info->dst_dim,
- info->src_dim,
- sdim,
- ctk_object->snap_strength, bv, bh);
+ if (((screen->position_type == CONF_ADJ_ABOVE) ||
+ (screen->position_type == CONF_ADJ_BELOW)) &&
+ (screen->relative_to == info->screen)) {
+ bv = NULL;
}
+ if (((info->screen->position_type == CONF_ADJ_ABOVE) ||
+ (info->screen->position_type == CONF_ADJ_BELOW)) &&
+ (info->screen->relative_to == screen)) {
+ bv = NULL;
+ }
+
+ /* If we aren't snapping vertically with the other screen,
+ * we shouldn't snap horizontally either if this is the
+ * left-most display in the screen.
+ */
+ if (!bv &&
+ info->display &&
+ info->display->cur_mode->dim[X] == info->screen->dim[X]) {
+ bh = NULL;
+ }
+
+ sdim = get_screen_dim(screen, 0);
+ snap_dim_to_dim(info->dst_dim,
+ info->src_dim,
+ sdim,
+ ctk_object->snap_strength, bv, bh);
}
/* Snap to the maximum screen dimensions */
@@ -1610,7 +1600,7 @@ static void snap_pan(CtkDisplayLayout *ctk_object)
int *bh;
int i;
int dist;
- nvGpuPtr gpu;
+ nvLayoutPtr layout = ctk_object->layout;
nvScreenPtr screen;
nvDisplayPtr other;
int *sdim;
@@ -1729,46 +1719,45 @@ static void snap_pan(CtkDisplayLayout *ctk_object)
}
- /* Snap to other screen dimensions */
- for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
- for (screen = gpu->screens; screen; screen = screen->next) {
- if (screen == info->screen) continue;
+ /* Snap to dimensions of other X screens */
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
- bv = &info->best_snap_v;
- bh = &info->best_snap_h;
+ if (screen == info->screen) continue;
- /* Don't snap horizontally to other screens that are somehow
- * related on the right edge of the (display's) screen being
- * panned.
- */
- if ((screen->position_type == CONF_ADJ_RIGHTOF) &&
- (screen->relative_to == info->screen)) {
- bh = NULL;
- }
- if ((info->screen->position_type == CONF_ADJ_LEFTOF) &&
- (info->screen->relative_to == screen)) {
- bh = NULL;
- }
+ bv = &info->best_snap_v;
+ bh = &info->best_snap_h;
- /* Don't snap vertically to other screens that are somehow
- * related on the bottom edge of the (display's) screen being
- * panned.
- */
- if ((screen->position_type == CONF_ADJ_BELOW) &&
- (screen->relative_to == info->screen)) {
- bv = NULL;
- }
- if ((info->screen->position_type == CONF_ADJ_ABOVE) &&
- (info->screen->relative_to == screen)) {
- bv = NULL;
- }
+ /* Don't snap horizontally to other screens that are somehow
+ * related on the right edge of the (display's) screen being
+ * panned.
+ */
+ if ((screen->position_type == CONF_ADJ_RIGHTOF) &&
+ (screen->relative_to == info->screen)) {
+ bh = NULL;
+ }
+ if ((info->screen->position_type == CONF_ADJ_LEFTOF) &&
+ (info->screen->relative_to == screen)) {
+ bh = NULL;
+ }
- sdim = get_screen_dim(screen, 0);
- snap_side_to_dim(info->dst_dim,
- info->src_dim,
- sdim,
- bv, bh);
+ /* Don't snap vertically to other screens that are somehow
+ * related on the bottom edge of the (display's) screen being
+ * panned.
+ */
+ if ((screen->position_type == CONF_ADJ_BELOW) &&
+ (screen->relative_to == info->screen)) {
+ bv = NULL;
+ }
+ if ((info->screen->position_type == CONF_ADJ_ABOVE) &&
+ (info->screen->relative_to == screen)) {
+ bv = NULL;
}
+
+ sdim = get_screen_dim(screen, 0);
+ snap_side_to_dim(info->dst_dim,
+ info->src_dim,
+ sdim,
+ bv, bh);
}
bh = &(info->best_snap_h);
@@ -1962,9 +1951,9 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap)
/* Offset the screen and all its displays */
offset_screen(info->screen, x, y);
- for (display = info->gpu->displays; display;
- display = display->next) {
- if (display->screen != info->screen) continue;
+ for (display = info->screen->displays;
+ display;
+ display = display->next_in_screen) {
offset_display(display, x, y);
}
@@ -1991,23 +1980,22 @@ static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap)
calc_metamode(info->screen, info->screen->cur_metamode);
x = info->screen->cur_metamode->dim[X] - info->orig_screen_dim[X];
y = info->screen->cur_metamode->dim[Y] - info->orig_screen_dim[Y];
-
+
if (x || y) {
nvDisplayPtr other;
nvModePtr mode;
- for (other = info->gpu->displays; other; other = other->next) {
-
- /* Other display must be in the same screen */
- if (other->screen != info->screen) continue;
-
+ for (other = info->screen->displays;
+ other;
+ other = other->next_in_screen) {
+
for (mode = other->modes; mode; mode = mode->next) {
-
+
/* Only move non-current modes */
if (mode == other->cur_mode) continue;
-
+
/* Don't move modes that are relative */
if (mode->position_type != CONF_ADJ_ABSOLUTE) continue;
-
+
offset_mode(mode, x, y);
}
}
@@ -3239,7 +3227,7 @@ static void draw_screen(CtkDisplayLayout *ctk_object,
gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_SOLID,
GDK_CAP_NOT_LAST, GDK_JOIN_ROUND);
- /* Show the name of the scree if no-scanout is selected */
+ /* Show the name of the screen if no-scanout is selected */
if (screen->no_scanout) {
tmp_str = g_strdup_printf("X Screen %d", screen->scrnum);
@@ -3656,11 +3644,11 @@ void ctk_display_layout_add_screen_metamode(CtkDisplayLayout *ctk_object,
/* Add a mode to each display */
- for (display = screen->gpu->displays; display; display = display->next) {
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
nvModePtr mode;
- if (display->screen != screen) continue; /* Display not in screen */
-
/* Create the mode */
mode = (nvModePtr)calloc(1, sizeof(nvMode));
if (!mode) goto fail;
@@ -3768,10 +3756,10 @@ void ctk_display_layout_delete_screen_metamode(CtkDisplayLayout *ctk_object,
/* Delete the mode from each display in the screen */
- for (display = screen->gpu->displays; display; display = display->next) {
+ for (display = screen->displays;
+ display;
+ display = display->next_in_screen) {
- if (display->screen != screen) continue;
-
/* Find the mode */
mode_prev = NULL;
mode = display->modes;
@@ -3779,7 +3767,7 @@ void ctk_display_layout_delete_screen_metamode(CtkDisplayLayout *ctk_object,
mode_prev = mode;
mode = mode->next;
}
-
+
/* Remove the mode from the list */
if (!mode_prev) {
display->modes = display->modes->next;
@@ -3823,7 +3811,7 @@ void ctk_display_layout_disable_display(CtkDisplayLayout *ctk_object,
/* If the screen is empty, remove it */
if (!screen->num_displays) {
- gpu_remove_and_free_screen(screen);
+ layout_remove_and_free_screen(screen);
/* Unselect the screen if it was selected */
if (screen == ctk_object->first_selected_screen) {
@@ -3838,7 +3826,7 @@ void ctk_display_layout_disable_display(CtkDisplayLayout *ctk_object,
}
/* Add the fake mode to the display */
- gpu_add_screenless_modes_to_displays(display->gpu);
+ gpu_add_screenless_modes_to_displays(display->gpu);
} /* ctk_display_layout_disable_display() */
@@ -3955,9 +3943,9 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object,
nvDisplayPtr other;
nvModePtr mode;
- for (other = display->gpu->displays; other; other = other->next) {
-
- if (other->screen != display->screen) continue;
+ for (other = display->screen->displays;
+ other;
+ other = other->next_in_screen) {
if (!resolve_all_modes) {
mode = other->cur_mode;
@@ -4225,7 +4213,6 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object,
GdkGCValues old_gc_values;
int modified = 0;
nvLayoutPtr layout = ctk_object->layout;
- nvGpuPtr gpu;
if (!screen) return;
@@ -4247,15 +4234,15 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object,
*/
if (position_type != CONF_ADJ_ABSOLUTE) {
-
+
nvScreenPtr other;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (other = gpu->screens; other; other = other->next) {
- if (other->relative_to == screen) {
- /* Make this screen use absolute positioning */
- switch_screen_to_absolute(other);
- }
+ for (other = layout->screens;
+ other;
+ other = other->next_in_layout) {
+
+ if (other->relative_to == screen) {
+ switch_screen_to_absolute(other);
}
}
}
@@ -4275,14 +4262,15 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object,
/* Do the move by offsetting */
offset_screen(screen, x_offset, y_offset);
- for (other = screen->gpu->displays; other; other = other->next) {
- if (other->screen != screen) continue;
+ for (other = screen->displays;
+ other;
+ other = other->next_in_screen) {
offset_display(other, x_offset, y_offset);
}
-
+
/* Recalculate the layout */
ctk_display_layout_update(ctk_object);
-
+
/* Report back result of move */
sdim = get_screen_dim(screen, 1);
if (x != sdim[X] || y != sdim[Y]) {
diff --git a/src/gtk+-2.x/ctkdisplaylayout.h b/src/gtk+-2.x/ctkdisplaylayout.h
index 784094a..d6cae85 100644
--- a/src/gtk+-2.x/ctkdisplaylayout.h
+++ b/src/gtk+-2.x/ctkdisplaylayout.h
@@ -178,7 +178,8 @@ typedef struct nvModeRec {
/* Display Device (CRT, DFP, TV, Projector ...) */
typedef struct nvDisplayRec {
- struct nvDisplayRec *next;
+ struct nvDisplayRec *next_on_gpu;
+ struct nvDisplayRec *next_in_screen;
XConfigMonitorPtr conf_monitor;
struct nvGpuRec *gpu; /* GPU the display belongs to */
@@ -221,7 +222,8 @@ typedef struct nvMetaModeRec {
/* X Screen */
typedef struct nvScreenRec {
- struct nvScreenRec *next;
+ struct nvScreenRec *next_in_layout;
+
XConfigScreenPtr conf_screen;
XConfigDevicePtr conf_device;
@@ -237,11 +239,13 @@ typedef struct nvScreenRec {
CtkEvent *ctk_event;
int scrnum;
+ struct nvLayoutRec *layout; /* Layout this X screen belongs to */
struct nvGpuRec *gpu; /* GPU driving this X screen */
int depth; /* Depth of the screen */
unsigned int displays_mask; /* Display devices on this X screen */
+ nvDisplayPtr displays; /* List of displays using this screen */
int num_displays; /* # of displays using this screen */
nvMetaModePtr metamodes; /* List of metamodes */
@@ -276,11 +280,11 @@ typedef struct GvoModeDataRec {
/* GPU (Device) */
typedef struct nvGpuRec {
- struct nvGpuRec *next;
+ struct nvGpuRec *next_in_layout; /* List of all GPUs */
NvCtrlAttributeHandle *handle; /* NV-CONTROL handle to GPU */
CtkEvent *ctk_event;
-
+
struct nvLayoutRec *layout; /* Layout this GPU belongs to */
int max_width;
@@ -289,7 +293,7 @@ typedef struct nvGpuRec {
Bool allow_depth_30;
char *name; /* Name of the GPU */
-
+
unsigned int connected_displays; /* Bitmask of connected displays */
gchar *pci_bus_id;
@@ -297,10 +301,7 @@ typedef struct nvGpuRec {
GvoModeData *gvo_mode_data; /* Information about GVO modes available */
unsigned int num_gvo_modes;
- nvScreenPtr screens; /* List of screens this GPU drives */
- int num_screens;
-
- nvDisplayPtr displays; /* List of displays attached to screen */
+ nvDisplayPtr displays; /* Linked list of displays connected to GPU */
int num_displays;
} nvGpu, *nvGpuPtr;
@@ -314,10 +315,13 @@ typedef struct nvLayoutRec {
NvCtrlAttributeHandle *handle;
- nvGpuPtr gpus; /* List of GPUs in the layout */
+ nvGpuPtr gpus; /* Linked list of GPUs (next_in_layout) */
int num_gpus;
- // Used for drawing the layout.
+ nvScreenPtr screens; /* Linked list of X screens (next_in_layout) */
+ int num_screens;
+
+ /* Used for drawing the layout */
int dim[4]; /* Bounding box of All X screens (Absolute coords) */
int xinerama_enabled;
diff --git a/src/gtk+-2.x/ctkditheringcontrols.c b/src/gtk+-2.x/ctkditheringcontrols.c
index 3ff91e0..473a9f4 100644
--- a/src/gtk+-2.x/ctkditheringcontrols.c
+++ b/src/gtk+-2.x/ctkditheringcontrols.c
@@ -384,18 +384,6 @@ GtkWidget* ctk_dithering_controls_new(NvCtrlAttributeHandle *handle,
CTK_EVENT_NAME(NV_CTRL_DITHERING_DEPTH),
G_CALLBACK(dithering_update_received),
(gpointer) ctk_dithering_controls);
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING),
- G_CALLBACK(dithering_update_received),
- (gpointer) ctk_dithering_controls);
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING_MODE),
- G_CALLBACK(dithering_update_received),
- (gpointer) ctk_dithering_controls);
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_CURRENT_DITHERING_DEPTH),
- G_CALLBACK(dithering_update_received),
- (gpointer) ctk_dithering_controls);
return GTK_WIDGET(object);
@@ -603,6 +591,7 @@ void post_dithering_config_update(CtkDitheringControls *ctk_dithering_controls,
return;
}
+ gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE);
ctk_config_statusbar_message(ctk_dithering_controls->ctk_config,
"Dithering set to %s for %s.",
dither_config_table[dithering_config],
@@ -625,6 +614,7 @@ void post_dithering_mode_update(CtkDitheringControls *ctk_dithering_controls,
return;
}
+ gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE);
ctk_config_statusbar_message(ctk_dithering_controls->ctk_config,
"Dithering mode set to %s for %s.",
dither_mode_table[dithering_mode],
@@ -646,6 +636,7 @@ void post_dithering_depth_update(CtkDitheringControls *ctk_dithering_controls,
return;
}
+ gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE);
ctk_config_statusbar_message(ctk_dithering_controls->ctk_config,
"Dithering depth set to %s for %s.",
dither_depth_table[dithering_depth],
@@ -696,7 +687,6 @@ static void dithering_config_menu_changed(GtkOptionMenu *dithering_config_menu,
/* reflecting the change in configuration to other widgets & reset button */
ctk_dithering_controls_setup(ctk_dithering_controls);
post_dithering_config_update(ctk_dithering_controls, dithering_config);
- gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE);
} /* dithering_config_menu_changed() */
@@ -736,7 +726,6 @@ static void dithering_mode_menu_changed(GtkOptionMenu *dithering_mode_menu,
/* reflecting the change in mode to other widgets & reset button */
ctk_dithering_controls_setup(ctk_dithering_controls);
post_dithering_mode_update(ctk_dithering_controls, dithering_mode);
- gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE);
} /* dithering_mode_menu_changed() */
@@ -784,7 +773,6 @@ static void dithering_depth_menu_changed(GtkOptionMenu *dithering_depth_menu,
/* reflecting the change in configuration to other widgets & reset button */
ctk_dithering_controls_setup(ctk_dithering_controls);
post_dithering_depth_update(ctk_dithering_controls, dithering_depth);
- gtk_widget_set_sensitive(ctk_dithering_controls->reset_button, TRUE);
} /* dithering_depth_menu_changed() */
@@ -847,6 +835,16 @@ static void dithering_update_received(GtkObject *object, gpointer arg1,
}
ctk_dithering_controls_setup(ctk_object);
+
+ /* update status bar message */
+ switch (event_struct->attribute) {
+ case NV_CTRL_DITHERING:
+ post_dithering_config_update(ctk_object, event_struct->value); break;
+ case NV_CTRL_DITHERING_MODE:
+ post_dithering_mode_update(ctk_object, event_struct->value); break;
+ case NV_CTRL_DITHERING_DEPTH:
+ post_dithering_depth_update(ctk_object, event_struct->value); break;
+ }
} /* dithering_update_received() */
diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c
index c175a8c..42584cc 100644
--- a/src/gtk+-2.x/ctkevent.c
+++ b/src/gtk+-2.x/ctkevent.c
@@ -406,10 +406,12 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU);
MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN);
MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU);
+ MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_DISPLAY_TARGETS);
+ MAKE_BINARY_SIGNAL(NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU);
#undef MAKE_BINARY_SIGNAL
-
-#if NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE != NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER
+
+#if NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE != NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU
#warning "There are attributes that do not emit signals!"
#endif
diff --git a/src/gtk+-2.x/ctkimagesliders.c b/src/gtk+-2.x/ctkimagesliders.c
index 5450436..10c29a2 100644
--- a/src/gtk+-2.x/ctkimagesliders.c
+++ b/src/gtk+-2.x/ctkimagesliders.c
@@ -260,8 +260,8 @@ static GtkWidget * add_scale(CtkConfig *ctk_config,
*/
static void post_scale_value_changed(GtkAdjustment *adjustment,
- CtkImageSliders *ctk_image_sliders,
- gint value)
+ CtkImageSliders *ctk_image_sliders,
+ gint value)
{
char *name = g_object_get_data(G_OBJECT(adjustment), "attribute name");
@@ -417,6 +417,12 @@ static void scale_value_received(GtkObject *object, gpointer arg1,
g_object_set_data(G_OBJECT(CTK_SCALE(scale)->gtk_adjustment),
"attribute active",
GINT_TO_POINTER(1));
+ /* In case of image sharpening slider here we are syncing to the
+ * recent image sharpening value, so updating status bar message */
+ post_scale_value_changed(CTK_SCALE(scale)->gtk_adjustment,
+ ctk_image_sliders,
+ gtk_adjustment_get_value(
+ CTK_SCALE(scale)->gtk_adjustment));
}
break;
default:
diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c
index 1939795..cf529c9 100644
--- a/src/gtk+-2.x/ctkpowermizer.c
+++ b/src/gtk+-2.x/ctkpowermizer.c
@@ -91,9 +91,7 @@ static const char *__powermizer_menu_help =
"utilization. 'Prefer Maximum Performance' hints to the driver to prefer "
"higher GPU clocks, when possible. If a single X server is running, the "
"mode selected in nvidia-settings is what the system will be using; if two or "
-"more X servers are running, the behavior is undefined. If any CUDA "
-"application is running, the system will always be in the 'Prefer Maximum "
-"Performance' mode.";
+"more X servers are running, the behavior is undefined.";
GType ctk_powermizer_get_type(void)
{
diff --git a/src/gtk+-2.x/ctkslimm.c b/src/gtk+-2.x/ctkslimm.c
index 5c7ff84..cb3fac6 100644
--- a/src/gtk+-2.x/ctkslimm.c
+++ b/src/gtk+-2.x/ctkslimm.c
@@ -1149,8 +1149,8 @@ static Bool other_displays_have_modeline(nvLayoutPtr layout,
nvGpuPtr gpu;
nvDisplayPtr d;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (d = gpu->displays; d; d = d->next) {
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ for (d = gpu->displays; d; d = d->next_on_gpu) {
if (display == d) continue;
if (d->modelines == NULL) continue;
if (!display_has_modeline(d, modeline)) {
@@ -1167,8 +1167,11 @@ static nvDisplayPtr find_active_display(nvLayoutPtr layout)
{
nvGpuPtr gpu;
nvDisplayPtr display;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
- for (display = gpu->displays; display; display = display->next) {
+
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ for (display = gpu->displays;
+ display;
+ display = display->next_on_gpu) {
if (display->modelines) return display;
}
}
@@ -1338,7 +1341,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
GridConfig *grid;
int num_valid = 0;
- for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
num_displays += gpu->num_displays;
}
diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h
index 5ee1b56..f712ec4 100644
--- a/src/libXNVCtrl/NVCtrl.h
+++ b/src/libXNVCtrl/NVCtrl.h
@@ -47,6 +47,7 @@
#define NV_CTRL_TARGET_TYPE_COOLER 5 /* e.g., fan */
#define NV_CTRL_TARGET_TYPE_THERMAL_SENSOR 6
#define NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER 7
+#define NV_CTRL_TARGET_TYPE_DISPLAY 8
/**************************************************************************/
@@ -78,6 +79,10 @@
* designated with "D" below. For attributes that do not require the
* display mask, the argument is ignored.
*
+ * Alternatively, NV-CONTROL versions 1.27 and greater allow these
+ * attributes to be accessed via display target types, in which case
+ * the display_mask is ignored.
+ *
* G: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GPU
* target type via XNVCTRLQueryTargetAttribute().
*
@@ -97,19 +102,18 @@
* Q: The attribute is a 64-bit integer attribute; use the 64-bit versions
* of the appropriate query interfaces.
*
- *
* C: The attribute may be queried using an NV_CTRL_TARGET_TYPE_COOLER target
* type via XNVCTRLQueryTargetAttribute().
- *
+ *
* S: The attribute may be queried using an NV_CTRL_TARGET_TYPE_THERMAL_SENSOR
* target type via XNVCTRLQueryTargetAttribute().
*
* T: The attribute may be queried using an
* NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER target type
* via XNVCTRLQueryTargetAttribute().
- *
+ *
* NOTE: Unless mentioned otherwise, all attributes may be queried using
- * an NV_CTRL_TARGET_TYPE_X_SCREEN target type via
+ * an NV_CTRL_TARGET_TYPE_X_SCREEN target type via
* XNVCTRLQueryTargetAttribute().
*/
@@ -699,8 +703,7 @@
/*
* NV_CTRL_FLIPPING_ALLOWED - when TRUE, OpenGL will swap by flipping
- * when possible; when FALSE, OpenGL will alway swap by blitting. XXX
- * can this be enabled dynamically?
+ * when possible; when FALSE, OpenGL will alway swap by blitting.
*/
#define NV_CTRL_FLIPPING_ALLOWED 40 /* RW-X */
@@ -1340,7 +1343,8 @@
* NV_CTRL_GVO_DATA_FORMAT
* NV_CTRL_GVO_FLIP_QUEUE_SIZE
*
- * XXX This is deprecated, please see NV_CTRL_GVO_LOCK_OWNER
+ * This attribute is deprecated and may be removed in a future release. Its
+ * functionality has been replaced by NV_CTRL_GVO_LOCK_OWNER.
*/
#define NV_CTRL_GVO_GLX_LOCKED 82 /* R-- */
@@ -4120,8 +4124,38 @@
*/
#define NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER 13 /* R--T */
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAY_TARGETS - Returns all the display devices
+ * currently connected to any GPU on the X server.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of display devices
+ * 4 * n CARD32 display device indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData().
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAY_TARGETS 14 /* R--- */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU - Returns the list of
+ * display devices that are connected to the GPU target.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of display devices
+ * 4 * n CARD32 display device indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU 15 /* R--G */
+
+
#define NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE \
- NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER
+ NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU
/**************************************************************************/
@@ -4365,7 +4399,9 @@
*
* ATTRIBUTE_TYPE_READ - Attribute may be read (queried.)
* ATTRIBUTE_TYPE_WRITE - Attribute may be written to (set.)
- * ATTRIBUTE_TYPE_DISPLAY - Attribute requires a display mask.
+ * ATTRIBUTE_TYPE_DISPLAY - Attribute is valid for display target types
+ * (requires a display_mask if queried via
+ * a GPU or X screen.)
* ATTRIBUTE_TYPE_GPU - Attribute is valid for GPU target types.
* ATTRIBUTE_TYPE_FRAMELOCK - Attribute is valid for Frame Lock target types.
* ATTRIBUTE_TYPE_X_SCREEN - Attribute is valid for X Screen target types.
@@ -4407,6 +4443,17 @@
#define ATTRIBUTE_TYPE_THERMAL_SENSOR 0x400
#define ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER 0x800
+#define ATTRIBUTE_TYPE_ALL_TARGETS \
+ ((ATTRIBUTE_TYPE_DISPLAY) | \
+ (ATTRIBUTE_TYPE_GPU) | \
+ (ATTRIBUTE_TYPE_FRAMELOCK) | \
+ (ATTRIBUTE_TYPE_X_SCREEN) | \
+ (ATTRIBUTE_TYPE_VCSC) | \
+ (ATTRIBUTE_TYPE_GVI) | \
+ (ATTRIBUTE_TYPE_COOLER) | \
+ (ATTRIBUTE_TYPE_THERMAL_SENSOR) | \
+ (ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER))
+
typedef struct _NVCTRLAttributeValidValues {
int type;
union {
diff --git a/src/libXNVCtrl/nv_control.h b/src/libXNVCtrl/nv_control.h
index d944b3c..914d83a 100644
--- a/src/libXNVCtrl/nv_control.h
+++ b/src/libXNVCtrl/nv_control.h
@@ -52,6 +52,7 @@
* report false positives via the GPU and X screen target types
* 1.25 Added 3D_VISION_PRO_TRANSCEIVER TargetType
* 1.26 Added XNVCTRLQueryXXXAttributePermissions.
+ * 1.27 Added DISPLAY TargetType
*/
#ifndef __NVCONTROL_H
@@ -62,7 +63,7 @@
#define NV_CONTROL_NAME "NV-CONTROL"
#define NV_CONTROL_MAJOR 1
-#define NV_CONTROL_MINOR 26
+#define NV_CONTROL_MINOR 27
#define X_nvCtrlQueryExtension 0
#define X_nvCtrlIsNv 1
diff --git a/src/parse.c b/src/parse.c
index a8fc02e..9b3ae8c 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -450,7 +450,15 @@ TargetTypeEntry targetTypeTable[] = {
ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER, /* permission_bit */
NV_FALSE, /* uses_display_devices */
1, 25 }, /* required major,minor protocol rev */
-
+
+ { "Display Device", /* name */
+ "dpy", /* parsed_name */
+ DISPLAY_TARGET, /* target_index */
+ NV_CTRL_TARGET_TYPE_DISPLAY, /* nvctrl */
+ ATTRIBUTE_TYPE_DISPLAY, /* permission_bit */
+ NV_FALSE, /* uses_display_devices */
+ 1, 27 }, /* required major,minor protocol rev */
+
{ NULL, NULL, 0, 0, 0 },
};
diff --git a/src/parse.h b/src/parse.h
index 9ba725e..c0dc4dd 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -153,7 +153,8 @@ extern AttributeTableEntry attributeTable[];
#define COOLER_TARGET 5
#define THERMAL_SENSOR_TARGET 6
#define NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET 7
-#define MAX_TARGET_TYPES 8
+#define DISPLAY_TARGET 8
+#define MAX_TARGET_TYPES 9
diff --git a/src/query-assign.c b/src/query-assign.c
index 0d3e11b..d3d961d 100644
--- a/src/query-assign.c
+++ b/src/query-assign.c
@@ -104,6 +104,7 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display)
NvCtrlAttributeHandle *handle;
int target, i, j, val, d, c, len;
char *tmp;
+ int *pData = NULL;
/* allocate the CtrlHandles struct */
@@ -176,9 +177,23 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display)
((major == targetTypeTable[j].major) &&
(minor >= targetTypeTable[j].minor)))) {
- status = NvCtrlQueryTargetCount
- (pQueryHandle, targetTypeTable[j].nvctrl,
- &val);
+ if (target != DISPLAY_TARGET) {
+ status = NvCtrlQueryTargetCount
+ (pQueryHandle, targetTypeTable[j].nvctrl,
+ &val);
+ } else {
+ /* For targets that aren't simply enumerated,
+ * query the list of valid IDs in pData which
+ * will be used below
+ */
+ status =
+ NvCtrlGetBinaryAttribute(pQueryHandle, 0,
+ NV_CTRL_BINARY_DATA_DISPLAY_TARGETS,
+ (unsigned char **)(&pData), &len);
+ if (status == NvCtrlSuccess) {
+ val = pData[0];
+ }
+ }
} else {
status = NvCtrlMissingExtension;
}
@@ -199,8 +214,14 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display)
/* if there are no targets of this type, skip */
- if (h->targets[target].n == 0) continue;
-
+ if (h->targets[target].n == 0) {
+ if (pData) {
+ XFree(pData);
+ pData = NULL;
+ }
+ continue;
+ }
+
/* allocate an array of CtrlHandleTarget's */
h->targets[target].t =
@@ -212,11 +233,29 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display)
*/
for (i = 0; i < h->targets[target].n; i++) {
-
+ int targetId;
+
+ switch (target) {
+ case DISPLAY_TARGET:
+ /* Grab the target Id from the pData list */
+ targetId = pData[i+1];
+ break;
+ case X_SCREEN_TARGET:
+ case GPU_TARGET:
+ case FRAMELOCK_TARGET:
+ case VCS_TARGET:
+ case GVI_TARGET:
+ case COOLER_TARGET:
+ case THERMAL_SENSOR_TARGET:
+ case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET:
+ default:
+ targetId = i;
+ }
+
/* allocate the handle */
handle = NvCtrlAttributeInit(h->dpy,
- targetTypeTable[j].nvctrl, i,
+ targetTypeTable[j].nvctrl, targetId,
NV_CTRL_ATTRIBUTES_ALL_SUBSYSTEMS);
h->targets[target].t[i].h = handle;
@@ -225,9 +264,15 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display)
* silently fail: this might happen if not all X screens
* are NVIDIA X screens
*/
-
- if (!handle) continue;
-
+
+ if (!handle) {
+ if (pData) {
+ XFree(pData);
+ pData = NULL;
+ }
+ continue;
+ }
+
/*
* get a name for this target; in the case of
* X_SCREEN_TARGET targets, just use the string returned
@@ -294,6 +339,11 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display)
if (!pQueryHandle) pQueryHandle = handle;
}
+
+ if (pData) {
+ XFree(pData);
+ pData = NULL;
+ }
}
return h;
@@ -429,6 +479,11 @@ static int process_attribute_queries(int num, char **queries,
continue;
}
+ if (nv_strcasecmp(queries[query], "dpys")) {
+ query_all_targets(display_name, DISPLAY_TARGET);
+ continue;
+ }
+
/* call the parser to parse queries[query] */
ret = nv_parse_attribute_string(queries[query], NV_PARSER_QUERY, &a);
@@ -1147,44 +1202,22 @@ static int print_target_display_connections(CtrlHandleTarget *t)
/*
- * get_vcs_name() Returns the VCS product name of the given
- * VCS target.
+ * get_product_name() Returns the (GPU, X screen, display device or VCS)
+ * product name of the given target.
*/
-static char * get_vcs_name(NvCtrlAttributeHandle *h)
+static char * get_product_name(NvCtrlAttributeHandle *h, int attr)
{
char *product_name;
ReturnStatus status;
- status = NvCtrlGetStringAttribute(h, NV_CTRL_STRING_VCSC_PRODUCT_NAME,
- &product_name);
-
- if (status != NvCtrlSuccess) return strdup("Unknown");
-
- return product_name;
-
-} /* get_vcs_name() */
-
-
-
-/*
- * get_gpu_name() Returns the GPU product name of the given
- * GPU target.
- */
-
-static char * get_gpu_name(NvCtrlAttributeHandle *h)
-{
- char *product_name;
- ReturnStatus status;
+ status = NvCtrlGetStringAttribute(h, attr, &product_name);
- status = NvCtrlGetStringAttribute(h, NV_CTRL_STRING_PRODUCT_NAME,
- &product_name);
-
if (status != NvCtrlSuccess) return strdup("Unknown");
-
+
return product_name;
-} /* get_gpu_name() */
+} /* get_product_name() */
@@ -1240,12 +1273,20 @@ static int print_target_connections(CtrlHandles *h,
switch (target_index) {
case GPU_TARGET:
product_name =
- get_gpu_name(h->targets[target_index].t[ pData[i] ].h);
+ get_product_name(h->targets[target_index].t[ pData[i] ].h,
+ NV_CTRL_STRING_PRODUCT_NAME);
break;
case VCS_TARGET:
product_name =
- get_vcs_name(h->targets[target_index].t[ pData[i] ].h);
+ get_product_name(h->targets[target_index].t[ pData[i] ].h,
+ NV_CTRL_STRING_VCSC_PRODUCT_NAME);
+ break;
+
+ case DISPLAY_TARGET:
+ product_name =
+ get_product_name(h->targets[target_index].t[ pData[i] ].h,
+ NV_CTRL_STRING_DISPLAY_DEVICE_NAME);
break;
case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET:
@@ -1299,7 +1340,6 @@ static int query_all_targets(const char *display_name, const int target_index)
{
CtrlHandles *h;
CtrlHandleTarget *t;
- ReturnStatus status;
int i, table_index;
char *str, *name, *product_name;
@@ -1379,31 +1419,31 @@ static int query_all_targets(const char *display_name, const int target_index)
product_name = malloc(32);
snprintf(product_name, 32, "G-Sync %d", i);
-
+
} else if (target_index == VCS_TARGET) {
- status = NvCtrlGetStringAttribute
- (t->h, NV_CTRL_STRING_VCSC_PRODUCT_NAME, &product_name);
-
- if (status != NvCtrlSuccess) product_name = strdup("Unknown");
-
+ product_name = get_product_name(t->h,
+ NV_CTRL_STRING_VCSC_PRODUCT_NAME);
+
} else if (target_index == GVI_TARGET) {
/* for gvi, create the product name */
product_name = malloc(32);
snprintf(product_name, 32, "SDI Input %d", i);
+
+ } else if (target_index == DISPLAY_TARGET) {
+
+ product_name = get_product_name(t->h,
+ NV_CTRL_STRING_DISPLAY_DEVICE_NAME);
+
} else {
/* for X_SCREEN_TARGET or GPU_TARGET, query the product name */
+ product_name = get_product_name(t->h, NV_CTRL_STRING_PRODUCT_NAME);
- status = NvCtrlGetStringAttribute
- (t->h, NV_CTRL_STRING_PRODUCT_NAME, &product_name);
-
- if (status != NvCtrlSuccess) product_name = strdup("Unknown");
-
}
-
+
/*
* use the name for the target handle, or "Unknown" if we
* don't have a target handle name (this can happen for a
@@ -1444,6 +1484,9 @@ static int query_all_targets(const char *display_name, const int target_index)
print_target_connections
(h, t, NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU,
THERMAL_SENSOR_TARGET);
+ print_target_connections
+ (h, t, NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU,
+ GPU_TARGET);
break;
case X_SCREEN_TARGET:
@@ -1469,13 +1512,13 @@ static int query_all_targets(const char *display_name, const int target_index)
(h, t, NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU,
COOLER_TARGET);
break;
-
+
case THERMAL_SENSOR_TARGET:
print_target_connections
(h, t, NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU,
THERMAL_SENSOR_TARGET);
break;
-
+
default:
break;
}
diff --git a/version.mk b/version.mk
index ac06417..f15c207 100644
--- a/version.mk
+++ b/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 270.41.19
+NVIDIA_VERSION = 275.09