diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2008-08-21 10:41:30 -0700 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2008-08-21 10:41:30 -0700 |
commit | 2359725ef2dae040185b353d4ce57f40d6452b5c (patch) | |
tree | 3ac5709694e979dae2876954b71190146b55e5cd | |
parent | 96fec7cf078d5becbd17f0f99a61b5c2f560c797 (diff) |
177.67177.67
33 files changed, 2365 insertions, 997 deletions
diff --git a/doc/nvidia-settings.1.m4 b/doc/nvidia-settings.1.m4 index d21eff5..c968846 100644 --- a/doc/nvidia-settings.1.m4 +++ b/doc/nvidia-settings.1.m4 @@ -578,12 +578,6 @@ There are many things still to be added to some of which include: .TP - -configurability of TwinView (NVIDIA is planning to implement this) -.TP -- -configurability of multiple X screens (NVIDIA is planning to implement this) -.TP -- different toolkits? The GUI for .B nvidia\-settings diff --git a/src/Makefile.inc b/src/Makefile.inc index 1e0f2a8..2dfee54 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -33,7 +33,8 @@ SRC += \ parse.c \ query-assign.c \ nvgetopt.c \ - glxinfo.c + glxinfo.c \ + lscf.c EXTRA_DIST += \ Makefile.inc \ @@ -43,7 +44,8 @@ EXTRA_DIST += \ parse.h \ query-assign.h \ nvgetopt.h \ - glxinfo.h + glxinfo.h \ + lscf.h dist_list:: @ echo $(SRC) $(EXTRA_DIST) diff --git a/src/XF86Config-parser/Generate.c b/src/XF86Config-parser/Generate.c index 0b6c9bd..22ce212 100644 --- a/src/XF86Config-parser/Generate.c +++ b/src/XF86Config-parser/Generate.c @@ -48,7 +48,6 @@ static int is_file(const char *filename); -static void add_files(GenerateOptions *gop, XConfigPtr config); static void add_font_path(GenerateOptions *gop, XConfigPtr config); static void add_modules(GenerateOptions *gop, XConfigPtr config); @@ -72,7 +71,7 @@ XConfigPtr xconfigGenerate(GenerateOptions *gop) /* add files, fonts, and modules */ - add_files(gop, config); + config->files = xconfigAlloc(sizeof(XConfigFilesRec)); add_font_path(gop, config); add_modules(gop, config); @@ -255,22 +254,6 @@ static char *find_libdir(GenerateOptions *gop) /* - * add_files() - - */ - -static void add_files(GenerateOptions *gop, XConfigPtr config) -{ - char *libdir = find_libdir(gop); - - config->files = xconfigAlloc(sizeof(XConfigFilesRec)); - config->files->rgbpath = xconfigStrcat(libdir, "/X11/rgb", NULL); - - free(libdir); - -} /* add_files() */ - - -/* * add_font_path() - scan through the __font_paths[] array, * temporarily chop off the ":unscaled" appendage, and check for the * file "fonts.dir" in the directory. If fonts.dir exists, append the diff --git a/src/XF86Config-parser/Merge.c b/src/XF86Config-parser/Merge.c index aaf66bc..7d8ab98 100644 --- a/src/XF86Config-parser/Merge.c +++ b/src/XF86Config-parser/Merge.c @@ -479,6 +479,7 @@ static int xconfigMergeDisplays(XConfigScreenPtr dstScreen, /* Free all the displays in the destination screen */ xconfigFreeDisplayList(dstScreen->displays); + dstScreen->displays = NULL; /* Copy all te displays */ @@ -530,6 +531,10 @@ static int xconfigMergeDisplays(XConfigScreenPtr dstScreen, srcMode = srcMode->next; } + + dstScreen->displays = + (XConfigDisplayPtr)xconfigAddListItem((GenericListPtr)(dstScreen->displays), + (GenericListPtr)dstDisplay); } return 1; diff --git a/src/command-line.c b/src/command-line.c index b83d706..67616a5 100644 --- a/src/command-line.c +++ b/src/command-line.c @@ -73,7 +73,7 @@ static void print_version(void) nv_msg(TAB, "This program is used to configure the " "NVIDIA Linux graphics driver."); nv_msg(NULL, ""); - nv_msg(TAB, "Copyright (C) 2004 NVIDIA Corporation."); + nv_msg(TAB, "Copyright (C) 2004 - 2008 NVIDIA Corporation."); nv_msg(NULL, ""); } /* print_version() */ diff --git a/src/glxinfo.c b/src/glxinfo.c index 64199eb..23c322b 100644 --- a/src/glxinfo.c +++ b/src/glxinfo.c @@ -182,17 +182,17 @@ print_fbconfig_attribs(GLXFBConfigAttr *fbca) return; } - printf("-fc- -vi- vt buf lv rgb d s colorbuffer ax dp st " + printf("--fc- -vi- vt buf lv rgb d s colorbuffer ax dp st " "accumbuffer ---ms---- cav -----pbuffer----- ---transparent----\n"); - printf(" id id siz l ci b t r g b a bf th en " + printf(" id id siz l ci b t r g b a bf th en " " r g b a mvs mcs b eat widt hght max-pxs typ r g b a i\n"); - printf("-------------------------------------------------" + printf("--------------------------------------------------" "--------------------------------------------------------------\n"); i = 0; while ( fbca[i].fbconfig_id != 0 ) { - printf("0x%2.2x ", fbca[i].fbconfig_id); + printf("0x%03x ", fbca[i].fbconfig_id); if ( fbca[i].visual_id ) { printf("0x%2.2x ", fbca[i].visual_id); } else { diff --git a/src/gtk+-2.x/ctkbanner.c b/src/gtk+-2.x/ctkbanner.c index 8e59031..baef5e6 100644 --- a/src/gtk+-2.x/ctkbanner.c +++ b/src/gtk+-2.x/ctkbanner.c @@ -429,6 +429,7 @@ GtkWidget* ctk_banner_new(BannerArtworkType artwork) Background.w = gdk_pixbuf_get_width(Background.pixbuf); Background.h = gdk_pixbuf_get_height(Background.pixbuf); } + g_object_ref(Background.pixbuf); if (!TallBackground.pixbuf) { TallBackground.pixbuf = @@ -436,12 +437,14 @@ GtkWidget* ctk_banner_new(BannerArtworkType artwork) TallBackground.w = gdk_pixbuf_get_width(TallBackground.pixbuf); TallBackground.h = gdk_pixbuf_get_height(TallBackground.pixbuf); } + g_object_ref(TallBackground.pixbuf); if (!Logo.pixbuf) { Logo.pixbuf = gdk_pixbuf_from_pixdata(&logo_pixdata, TRUE, NULL); Logo.w = gdk_pixbuf_get_width(Logo.pixbuf); Logo.h = gdk_pixbuf_get_height(Logo.pixbuf); } + g_object_ref(Logo.pixbuf); if (!TallLogo.pixbuf) { TallLogo.pixbuf = @@ -449,8 +452,8 @@ GtkWidget* ctk_banner_new(BannerArtworkType artwork) TallLogo.w = gdk_pixbuf_get_width(TallLogo.pixbuf); TallLogo.h = gdk_pixbuf_get_height(TallLogo.pixbuf); } - - + g_object_ref(TallLogo.pixbuf); + /* * assign fields based on whether the artwork is tall; XXX these * may need to be tweaked diff --git a/src/gtk+-2.x/ctkcolorcorrection.c b/src/gtk+-2.x/ctkcolorcorrection.c index 44722b0..5b2b629 100644 --- a/src/gtk+-2.x/ctkcolorcorrection.c +++ b/src/gtk+-2.x/ctkcolorcorrection.c @@ -51,6 +51,13 @@ static const char *__active_color_help = "The Active Color Channel drop-down " static const char *__resest_button_help = "The Reset Hardware Defaults " "button restores the color correction settings to their default values."; +static const char *__confirm_button_help = "Some color correction settings " +"can yield an unusable display " +"(e.g., making the display unreadably dark or light). When you " +"change the color correction values, the '10 Seconds to Confirm' " +"button will count down to zero. If you have not clicked the " +"button by then to accept the changes, it will restore your previous values."; + static const char *__color_curve_help = "The color curve graph changes to " "reflect your adjustments made with the Brightness, Constrast, and Gamma " "sliders."; @@ -62,17 +69,22 @@ static void set_button_sensitive (GtkButton *); static void -button_clicked (GtkButton *, gpointer); +reset_button_clicked (GtkButton *, gpointer); static void -adjustment_value_changed (GtkAdjustment *, gpointer); +set_color_state (CtkColorCorrection *, gint, gint, gfloat, gboolean); + +static void +confirm_button_clicked (GtkButton *, gpointer); +static void +adjustment_value_changed (GtkAdjustment *, gpointer); static gfloat get_attribute_channel_value (CtkColorCorrection *, gint, gint); static void -set_attribute_channel_value (CtkColorCorrection *, gint, gint, gfloat); +flush_attribute_channel_values (CtkColorCorrection *, gint, gint, gfloat); static void ctk_color_correction_class_init(CtkColorCorrectionClass *); @@ -80,6 +92,12 @@ ctk_color_correction_class_init(CtkColorCorrectionClass *); static void apply_parsed_attribute_list(CtkColorCorrection *, ParsedAttribute *); +static gboolean +do_confirm_countdown (gpointer); + +static void +update_confirm_text (CtkColorCorrection *); + enum { CHANGED, LAST_SIGNAL @@ -87,6 +105,15 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; +#define RED RED_CHANNEL_INDEX +#define GREEN GREEN_CHANNEL_INDEX +#define BLUE BLUE_CHANNEL_INDEX + +#define CONTRAST (CONTRAST_INDEX - CONTRAST_INDEX) +#define BRIGHTNESS (BRIGHTNESS_INDEX - CONTRAST_INDEX) +#define GAMMA (GAMMA_INDEX - CONTRAST_INDEX) + +#define DEFAULT_CONFIRM_COLORCORRECTION_TIMEOUT 10 #define CREATE_COLOR_ADJUSTMENT(adj, attr, min, max) \ { \ @@ -171,7 +198,7 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, GtkWidget *rightvbox; GtkWidget *hbox; GtkWidget *vbox; - GtkWidget *button; + GtkWidget *button, *confirm_button; GtkWidget *widget; GtkWidget *hsep; GtkWidget *eventbox; @@ -183,12 +210,20 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_EXT_VM_PRESENT, &val); if ((ret != NvCtrlSuccess) || (val == FALSE)) return NULL; + /* check if the noScanout mode enabled */ + + ret = NvCtrlGetAttribute(handle, NV_CTRL_NO_SCANOUT, &val); + if ((ret == NvCtrlSuccess) && (val == NV_CTRL_NO_SCANOUT_ENABLED)) + return NULL; + object = g_object_new(CTK_TYPE_COLOR_CORRECTION, NULL); ctk_color_correction = CTK_COLOR_CORRECTION(object); ctk_color_correction->handle = handle; ctk_color_correction->ctk_config = ctk_config; - + ctk_color_correction->confirm_timer = 0; + ctk_color_correction->confirm_countdown = + DEFAULT_CONFIRM_COLORCORRECTION_TIMEOUT; apply_parsed_attribute_list(ctk_color_correction, p); gtk_box_set_spacing(GTK_BOX(ctk_color_correction), 10); @@ -327,16 +362,24 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, * settings to their respective default values (for all channels). */ - label = gtk_label_new("Reset Hardware Defaults"); hbox = gtk_hbox_new(FALSE, 0); - button = gtk_button_new(); + button = gtk_button_new_with_label("Reset Hardware Defaults"); + gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15); - gtk_container_add(GTK_CONTAINER(button), hbox); + confirm_button = gtk_button_new_with_label("Confirm Current Changes"); + gtk_box_pack_end(GTK_BOX(hbox), confirm_button, FALSE, FALSE, 5); + gtk_widget_set_sensitive(confirm_button, FALSE); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_clicked), + g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(reset_button_clicked), + (gpointer) ctk_color_correction); + + g_signal_connect(G_OBJECT(confirm_button), "clicked", + G_CALLBACK(confirm_button_clicked), (gpointer) ctk_color_correction); + ctk_color_correction->confirm_button = confirm_button; + gtk_widget_set_size_request(confirm_button, 160, -1); + ctk_config_set_tooltip(ctk_config, confirm_button, __confirm_button_help); ctk_config_set_tooltip(ctk_config, button, __resest_button_help); /* @@ -450,7 +493,7 @@ GtkWidget* ctk_color_correction_new(NvCtrlAttributeHandle *handle, */ alignment = gtk_alignment_new(1, 1, 0, 0); - gtk_container_add(GTK_CONTAINER(alignment), button); + gtk_container_add(GTK_CONTAINER(alignment), hbox); gtk_box_pack_start(GTK_BOX(object), alignment, TRUE, TRUE, 0); /* finally, show the widget */ @@ -535,21 +578,89 @@ static void set_button_sensitive( gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE); } -static void button_clicked( + + +/** set_color_state() ******************* + * + * Stores color state to cur_val[attribute][channel] + * and prev_val[attribute][channel]. + * + **/ + +static void set_color_state(CtkColorCorrection *ctk_color_correction, + gint attribute_idx, gint channel_idx, + gfloat value, gboolean all +) +{ + if ( channel_idx != ALL_CHANNELS ) { + ctk_color_correction->cur_val + [attribute_idx][channel_idx] = value; + if ( all ) { + ctk_color_correction->prev_val + [attribute_idx][channel_idx] = value; + } + } else { + gint ch; + for ( ch = RED; ch <= BLUE; ch++ ) { + set_color_state(ctk_color_correction, attribute_idx, ch, value, all); + } + } +} /* set_color_state() */ + + + +/** confirm_button_clicked() ************* + * + * Callback function which stores current values to previous value when user + * clicks Confirm button. + * + **/ + +static void confirm_button_clicked( + GtkButton *button, + gpointer user_data +) +{ + CtkColorCorrection *ctk_color_correction = CTK_COLOR_CORRECTION(user_data); + + /* Store cur_val[attribute][channel] to prev_val[attribute][channel]. */ + memcpy (ctk_color_correction->prev_val, ctk_color_correction->cur_val, + sizeof(ctk_color_correction->cur_val)); + + /* kill the timer */ + g_source_remove(ctk_color_correction->confirm_timer); + ctk_color_correction->confirm_timer = 0; + + /* Reset confirm button text */ + gtk_button_set_label(GTK_BUTTON(ctk_color_correction->confirm_button), + "Confirm Current Changes"); + + gtk_widget_set_sensitive(ctk_color_correction->confirm_button, FALSE); +} /* confirm_button_clicked() */ + + + +static void reset_button_clicked( GtkButton *button, gpointer user_data ) { CtkColorCorrection *ctk_color_correction; - gfloat c[3] = {CONTRAST_DEFAULT, CONTRAST_DEFAULT, CONTRAST_DEFAULT}; - gfloat b[3] = {BRIGHTNESS_DEFAULT, BRIGHTNESS_DEFAULT, BRIGHTNESS_DEFAULT}; - gfloat g[3] = {GAMMA_DEFAULT, GAMMA_DEFAULT, GAMMA_DEFAULT}; GtkOptionMenu *option_menu; - ctk_color_correction = CTK_COLOR_CORRECTION(user_data); - - NvCtrlSetColorAttributes(ctk_color_correction->handle, c, b, g, - ALL_CHANNELS | ALL_VALUES); + /* Set default values */ + set_color_state(ctk_color_correction, CONTRAST, ALL_CHANNELS, + CONTRAST_DEFAULT, TRUE); + set_color_state(ctk_color_correction, BRIGHTNESS, ALL_CHANNELS, + BRIGHTNESS_DEFAULT, TRUE); + set_color_state(ctk_color_correction, GAMMA, ALL_CHANNELS, + GAMMA_DEFAULT, TRUE); + + NvCtrlSetColorAttributes(ctk_color_correction->handle, + ctk_color_correction->cur_val[CONTRAST], + ctk_color_correction->cur_val[BRIGHTNESS], + ctk_color_correction->cur_val[GAMMA], + ALL_VALUES | ALL_CHANNELS); option_menu = GTK_OPTION_MENU(ctk_color_correction->option_menu); @@ -568,7 +679,16 @@ static void button_clicked( ctk_config_statusbar_message(ctk_color_correction->ctk_config, "Reset color correction hardware defaults."); + gtk_widget_set_sensitive(GTK_WIDGET(ctk_color_correction->confirm_button), + FALSE); gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); + /* kill the timer */ + g_source_remove(ctk_color_correction->confirm_timer); + ctk_color_correction->confirm_timer = 0; + + /* Reset confirm button text */ + gtk_button_set_label(GTK_BUTTON(ctk_color_correction->confirm_button), + "Confirm Current Changes"); } static void adjustment_value_changed( @@ -578,6 +698,7 @@ static void adjustment_value_changed( { CtkColorCorrection *ctk_color_correction; gint attribute, channel; + gint attribute_idx, channel_idx; gfloat value; gchar *channel_str, *attribute_str; @@ -591,28 +712,67 @@ static void adjustment_value_changed( channel = GPOINTER_TO_INT(user_data); value = gtk_adjustment_get_value(adjustment); - - set_attribute_channel_value(ctk_color_correction, - attribute, channel, value); + + /* start timer for confirming changes */ + ctk_color_correction->confirm_countdown = + DEFAULT_CONFIRM_COLORCORRECTION_TIMEOUT; + update_confirm_text(ctk_color_correction); + + if (ctk_color_correction->confirm_timer == 0) { + ctk_color_correction->confirm_timer = + g_timeout_add(1000, + (GSourceFunc)do_confirm_countdown, + (gpointer) (ctk_color_correction)); + } switch (attribute) { - case CONTRAST_VALUE: attribute_str = "contrast"; break; - case BRIGHTNESS_VALUE: attribute_str = "brightness"; break; - case GAMMA_VALUE: attribute_str = "gamma"; break; - default: attribute_str = "unknown"; break; + case CONTRAST_VALUE: + attribute_idx = CONTRAST; + attribute_str = "contrast"; + break; + case BRIGHTNESS_VALUE: + attribute_idx = BRIGHTNESS; + attribute_str = "brightness"; + break; + case GAMMA_VALUE: + attribute_idx = GAMMA; + attribute_str = "gamma"; + break; + default: + return; } switch (channel) { - case RED_CHANNEL: channel_str = "red "; break; - case GREEN_CHANNEL: channel_str = "green "; break; - case BLUE_CHANNEL: channel_str = "blue "; break; - case ALL_CHANNELS: /* fall through */ - default: channel_str = ""; break; + case RED_CHANNEL: + channel_idx = RED; + channel_str = "red "; + break; + case GREEN_CHANNEL: + channel_idx = GREEN; + channel_str = "green "; + break; + case BLUE_CHANNEL: + channel_idx = BLUE; + channel_str = "blue "; + break; + case ALL_CHANNELS: + channel_idx = ALL_CHANNELS; + channel_str = ""; + break; + default: + return; } + set_color_state(ctk_color_correction, attribute_idx, channel_idx, + value, FALSE); + + flush_attribute_channel_values(ctk_color_correction, + attribute, channel, value); + ctk_config_statusbar_message(ctk_color_correction->ctk_config, "Set %s%s to %f.", channel_str, attribute_str, value); + gtk_widget_set_sensitive(ctk_color_correction->confirm_button, TRUE); } @@ -652,7 +812,7 @@ static gfloat get_attribute_channel_value(CtkColorCorrection } } -static void set_attribute_channel_value( +static void flush_attribute_channel_values( CtkColorCorrection *ctk_color_correction, gint attribute, gint channel, @@ -660,70 +820,88 @@ static void set_attribute_channel_value( ) { NvCtrlAttributeHandle *handle = ctk_color_correction->handle; - gfloat v[3]; - v[0] = v[1] = v[2] = value; - - NvCtrlSetColorAttributes(handle, v, v, v, attribute | channel); + NvCtrlSetColorAttributes(handle, + ctk_color_correction->cur_val[CONTRAST], + ctk_color_correction->cur_val[BRIGHTNESS], + ctk_color_correction->cur_val[GAMMA], + attribute | channel); g_signal_emit(ctk_color_correction, signals[CHANGED], 0); } -#define RED RED_CHANNEL_INDEX -#define GREEN GREEN_CHANNEL_INDEX -#define BLUE BLUE_CHANNEL_INDEX - static void apply_parsed_attribute_list( CtkColorCorrection *ctk_color_correction, ParsedAttribute *p ) { - float c[3], b[3], g[3]; - char *this_display_name, *display_name; + int target_type, target_id; unsigned int attr = 0; - this_display_name = NvCtrlGetDisplayName(ctk_color_correction->handle); - - c[0] = c[1] = c[2] = CONTRAST_DEFAULT; - b[0] = b[1] = b[2] = BRIGHTNESS_DEFAULT; - g[0] = g[1] = g[2] = GAMMA_DEFAULT; - - while (p) { + set_color_state(ctk_color_correction, CONTRAST, ALL_CHANNELS, + CONTRAST_DEFAULT, TRUE); + set_color_state(ctk_color_correction, BRIGHTNESS, ALL_CHANNELS, + BRIGHTNESS_DEFAULT, TRUE); + set_color_state(ctk_color_correction, GAMMA, ALL_CHANNELS, + GAMMA_DEFAULT, TRUE); - display_name = NULL; + target_type = NvCtrlGetTargetType(ctk_color_correction->handle); + target_id = NvCtrlGetTargetId(ctk_color_correction->handle); + + while (p) { if (!p->next) goto next_attribute; if (!(p->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE)) goto next_attribute; /* - * if this parsed attribute's display name does not match the - * current display name, then ignore + * if this parsed attribute's target_type, target_id does not match the + * current target_type and target_id then ignore */ - display_name = nv_standardize_screen_name(p->display, -1); - - if (strcmp(display_name, this_display_name) != 0) goto next_attribute; + if ((p->target_type != target_type) || + (p->target_id != target_id)) goto next_attribute; switch (p->attr & (ALL_VALUES | ALL_CHANNELS)) { - case (CONTRAST_VALUE | RED_CHANNEL): c[RED] = p->fval; break; - case (CONTRAST_VALUE | GREEN_CHANNEL): c[GREEN] = p->fval; break; - case (CONTRAST_VALUE | BLUE_CHANNEL): c[BLUE] = p->fval; break; + case (CONTRAST_VALUE | RED_CHANNEL): + set_color_state(ctk_color_correction, CONTRAST, + RED, p->fval, TRUE); break; + case (CONTRAST_VALUE | GREEN_CHANNEL): + set_color_state(ctk_color_correction, CONTRAST, + GREEN, p->fval, TRUE); break; + case (CONTRAST_VALUE | BLUE_CHANNEL): + set_color_state(ctk_color_correction, CONTRAST, + BLUE, p->fval, TRUE); break; case (CONTRAST_VALUE | ALL_CHANNELS): - c[RED] = c[GREEN] = c[BLUE] = p->fval; break; - - case (BRIGHTNESS_VALUE | RED_CHANNEL): b[RED] = p->fval; break; - case (BRIGHTNESS_VALUE | GREEN_CHANNEL): b[GREEN] = p->fval; break; - case (BRIGHTNESS_VALUE | BLUE_CHANNEL): b[BLUE] = p->fval; break; + set_color_state(ctk_color_correction, CONTRAST, + ALL_CHANNELS, p->fval, TRUE); break; + + case (BRIGHTNESS_VALUE | RED_CHANNEL): + set_color_state(ctk_color_correction, BRIGHTNESS, + RED, p->fval, TRUE); break; + case (BRIGHTNESS_VALUE | GREEN_CHANNEL): + set_color_state(ctk_color_correction, BRIGHTNESS, + GREEN, p->fval, TRUE); break; + case (BRIGHTNESS_VALUE | BLUE_CHANNEL): + set_color_state(ctk_color_correction, BRIGHTNESS, + BLUE, p->fval, TRUE); break; case (BRIGHTNESS_VALUE | ALL_CHANNELS): - b[RED] = b[GREEN] = b[BLUE] = p->fval; break; - - case (GAMMA_VALUE | RED_CHANNEL): g[RED] = p->fval; break; - case (GAMMA_VALUE | GREEN_CHANNEL): g[GREEN] = p->fval; break; - case (GAMMA_VALUE | BLUE_CHANNEL): g[BLUE] = p->fval; break; + set_color_state(ctk_color_correction, BRIGHTNESS, + ALL_CHANNELS, p->fval, TRUE); break; + + case (GAMMA_VALUE | RED_CHANNEL): + set_color_state(ctk_color_correction, GAMMA, + RED, p->fval, TRUE); break; + case (GAMMA_VALUE | GREEN_CHANNEL): + set_color_state(ctk_color_correction, GAMMA, + GREEN, p->fval, TRUE); break; + case (GAMMA_VALUE | BLUE_CHANNEL): + set_color_state(ctk_color_correction, GAMMA, + BLUE, p->fval, TRUE); break; case (GAMMA_VALUE | ALL_CHANNELS): - g[RED] = g[GREEN] = g[BLUE] = p->fval; break; + set_color_state(ctk_color_correction, GAMMA, + ALL_CHANNELS, p->fval, TRUE); break; default: goto next_attribute; @@ -733,19 +911,95 @@ static void apply_parsed_attribute_list( next_attribute: - if (display_name) free(display_name); - p = p->next; } - free(this_display_name); - if (attr) { - NvCtrlSetColorAttributes(ctk_color_correction->handle, c, b, g, attr); + NvCtrlSetColorAttributes(ctk_color_correction->handle, + ctk_color_correction->cur_val[CONTRAST], + ctk_color_correction->cur_val[BRIGHTNESS], + ctk_color_correction->cur_val[GAMMA], + attr); } } /* apply_parsed_attribute_list() */ +/** update_confirm_text() ************************************ + * + * Generates the text used to lable confirmation button. + * + **/ + +static void update_confirm_text(CtkColorCorrection *ctk_color_correction) +{ + gchar *str; + str = g_strdup_printf("%d Seconds to Confirm", + ctk_color_correction->confirm_countdown); + gtk_button_set_label(GTK_BUTTON(ctk_color_correction->confirm_button), + str); + g_free(str); +} /* update_confirm_text() */ + +/** do_confirm_countdown() *********************************** + * + * timeout callback for reverting color correction slider changes if user not + * confirm changes. + * + **/ + +static gboolean do_confirm_countdown(gpointer data) +{ + gint attr, ch; + CtkColorCorrection *ctk_color_correction = (CtkColorCorrection *)(data); + unsigned int active_attributes_channels = 0; + GtkOptionMenu *option_menu = + GTK_OPTION_MENU(ctk_color_correction->option_menu); + + ctk_color_correction->confirm_countdown--; + if (ctk_color_correction->confirm_countdown > 0) { + update_confirm_text(ctk_color_correction); + return True; + } + + /* Countdown timed out, reset color settings to previous state */ + for (attr = CONTRAST_INDEX; attr <= GAMMA_INDEX; attr++) { + for (ch = RED; ch <= BLUE; ch++) { + /* Check for attribute channel value change. */ + if (ctk_color_correction->cur_val[attr - CONTRAST_INDEX][ch] != + ctk_color_correction->prev_val[attr - CONTRAST_INDEX][ch]) { + ctk_color_correction->cur_val[attr - CONTRAST_INDEX][ch] = + ctk_color_correction->prev_val[attr - CONTRAST_INDEX][ch]; + active_attributes_channels |= (1 << attr) | (1 << ch); + } + } + } + if (active_attributes_channels) { + NvCtrlSetColorAttributes(ctk_color_correction->handle, + ctk_color_correction->cur_val[CONTRAST], + ctk_color_correction->cur_val[BRIGHTNESS], + ctk_color_correction->cur_val[GAMMA], + active_attributes_channels); + g_signal_emit(ctk_color_correction, signals[CHANGED], 0); + } + + /* Refresh color correction page for current selected channel. */ + option_menu_changed(option_menu, (gpointer)(ctk_color_correction)); + + /* Reset confirm button text */ + gtk_button_set_label(GTK_BUTTON(ctk_color_correction->confirm_button), + "Confirm Current Changes"); + + /* Update status bar message */ + ctk_config_statusbar_message(ctk_color_correction->ctk_config, + "Reverted color correction changes, due to " + "confirmation timeout."); + + + ctk_color_correction->confirm_timer = 0; + gtk_widget_set_sensitive(ctk_color_correction->confirm_button, FALSE); + return False; + +} /* do_confirm_countdown() */ GtkTextBuffer *ctk_color_correction_create_help(GtkTextTagTable *table) @@ -785,6 +1039,9 @@ GtkTextBuffer *ctk_color_correction_create_help(GtkTextTagTable *table) "the XF86VidMode extension to manipulate the X screen's " "color ramps."); + ctk_help_heading(b, &i, "Confirm Current Changes"); + ctk_help_para(b, &i, __confirm_button_help); + ctk_help_heading(b, &i, "Reset Hardware Defaults"); ctk_help_para(b, &i, __resest_button_help); diff --git a/src/gtk+-2.x/ctkcolorcorrection.h b/src/gtk+-2.x/ctkcolorcorrection.h index a25b2ce..746a787 100644 --- a/src/gtk+-2.x/ctkcolorcorrection.h +++ b/src/gtk+-2.x/ctkcolorcorrection.h @@ -64,6 +64,11 @@ struct _CtkColorCorrection GtkObject *brightness_adjustment; GtkObject *contrast_adjustment; GtkObject *gamma_adjustment; + GtkWidget *confirm_button; + gint confirm_countdown; + guint confirm_timer; + gfloat cur_val[3][3]; // as [attribute][channel] + gfloat prev_val[3][3]; // as [attribute][channel] guint enabled_display_devices; }; diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c index 8381b86..33c291e 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.c +++ b/src/gtk+-2.x/ctkdisplayconfig.c @@ -42,6 +42,7 @@ #include "msg.h" #include "parse.h" +#include "lscf.h" #include "ctkutils.h" @@ -103,7 +104,11 @@ static void validation_details_clicked(GtkWidget *widget, gpointer user_data); static int generateXConfig(CtkDisplayConfig *ctk_object, XConfigPtr *pConfig); static void update_banner(XConfigPtr config); - +static void display_config_attribute_changed(GtkObject *object, gpointer arg1, + gpointer user_data); +static void reset_layout(CtkDisplayConfig *ctk_object); +static gboolean force_layout_reset(gpointer user_data); +static void user_changed_attributes(CtkDisplayConfig *ctk_object); @@ -330,6 +335,116 @@ static gboolean layout_supports_depth_30(nvLayoutPtr layout) +/** register_layout_events() ***************************************** + * + * Registers to display-configuration related events relating to all + * parts of the given layout structure. + * + **/ + +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) { + + if (!gpu->handle) continue; + + g_signal_connect(G_OBJECT(gpu->ctk_event), + CTK_EVENT_NAME(NV_CTRL_PROBE_DISPLAYS), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); + + g_signal_connect(G_OBJECT(gpu->ctk_event), + 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) { + + 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() */ + + + +/** unregister_layout_events() ***************************************** + * + * Unregisters display-configuration related events relating to all + * parts of the given layout structure as registered by + + * Unregisters all Screen/Gpu events. + * + **/ + +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) { + + 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 + 0, // Signal Detail + NULL, // Closure + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); + + for (screen = gpu->screens; screen; screen = screen->next) { + + 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); + } + } + +} /* unregister_layout_events() */ + + + /** consolidate_xinerama() ******************************************* * * Ensures that all X screens have the same depth if Xinerama is @@ -879,6 +994,17 @@ GtkWidget * create_validation_apply_dialog(CtkDisplayConfig *ctk_object) } /* create_validation_apply_dialog() */ + +static void user_changed_attributes(CtkDisplayConfig *ctk_object) +{ + if (ctk_object->forced_reset_allowed) { + gtk_widget_set_sensitive(ctk_object->btn_apply, True); + ctk_object->forced_reset_allowed = FALSE; + } +} /* user_changed_attributes() */ + + + static void screen_primary_display_toggled(GtkWidget *widget, gpointer user_data) { @@ -892,9 +1018,7 @@ static void screen_primary_display_toggled(GtkWidget *widget, screen->primaryDisplay = display; } - /* Make the apply button sensitive to user input */ - gtk_widget_set_sensitive(ctk_object->btn_apply, True); - + user_changed_attributes(ctk_object); } /* screen_primary_display_toggled() */ @@ -984,6 +1108,12 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, ctk_object->ctk_config = ctk_config; ctk_object->apply_possible = TRUE; + + ctk_object->reset_required = FALSE; + ctk_object->forced_reset_allowed = TRUE; + ctk_object->notify_user_of_reset = TRUE; + ctk_object->ignore_reset_events = FALSE; + ctk_object->advanced_mode = FALSE; /* Set container properties of the object & pack the banner */ @@ -1026,6 +1156,9 @@ GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle, return GTK_WIDGET(ctk_object); } + /* Register all Screen/Gpu events. */ + register_layout_events(ctk_object); + /* Create the layout widget */ ctk_object->obj_layout = ctk_display_layout_new(handle, ctk_config, ctk_object->layout, @@ -2305,7 +2438,6 @@ static void setup_display_resolution_dropdown(CtkDisplayConfig *ctk_object) cur_modeline = display->cur_mode->modeline; - /* Create the modeline lookup table for the dropdown */ if (ctk_object->resolution_table) { free(ctk_object->resolution_table); @@ -2433,11 +2565,14 @@ static void setup_display_resolution_dropdown(CtkDisplayConfig *ctk_object) } /* setup_display_resolution_dropdown() */ + + /** generate_display_modelname_dropdown() ******************************** * * Generate display modelname dropdown menu. * **/ + static GtkWidget* generate_display_modelname_dropdown (CtkDisplayConfig *ctk_object, int *cur_idx) { @@ -2489,14 +2624,19 @@ static GtkWidget* generate_display_modelname_dropdown [ctk_object->display_model_table_len++] = display; } } + return menu; + } /* generate_display_modelname_dropdown() */ + + /** setup_display_modelname_dropdown() ************************** * * Setup display modelname dropdown menu. * **/ + static void setup_display_modelname_dropdown(CtkDisplayConfig *ctk_object) { GtkWidget *menu; @@ -2531,13 +2671,14 @@ static void setup_display_modelname_dropdown(CtkDisplayConfig *ctk_object) gtk_option_menu_set_history (GTK_OPTION_MENU(ctk_object->mnu_display_model), cur_idx); - g_signal_handlers_unblock_by_func (G_OBJECT(ctk_object->mnu_display_model), G_CALLBACK(display_modelname_changed), (gpointer) ctk_object); + } /* setup_display_modelname_dropdown() */ + /** setup_display_position_type() ************************************ * * Sets up the display position type dropdown to reflect the position @@ -2795,8 +2936,11 @@ static void setup_primary_display(CtkDisplayConfig *ctk_object) (G_OBJECT(ctk_object->chk_primary_display), G_CALLBACK(screen_primary_display_toggled), (gpointer) ctk_object); + } /* setup_primary_display() */ + + /** setup_display_panning() ****************************************** * * Sets up the display panning text entry to reflect the currently @@ -3885,7 +4029,7 @@ void layout_modified_callback(nvLayoutPtr layout, void *data) /* If the positioning of the X screen changes, we cannot apply */ check_screen_pos_changed(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* layout_modified_callback() */ @@ -4176,9 +4320,19 @@ static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object, return; } else { + g_signal_handlers_block_by_func + (G_OBJECT(screen->ctk_event), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); + /* Make sure other parts of nvidia-settings get updated */ ctk_event_emit(screen->ctk_event, 0, NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, new_mask); + + g_signal_handlers_unblock_by_func + (G_OBJECT(screen->ctk_event), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); } } @@ -4883,8 +5037,8 @@ static void display_config_clicked(GtkWidget *widget, gpointer user_data) setup_layout_frame(ctk_object); setup_display_page(ctk_object); setup_screen_page(ctk_object); - - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + + user_changed_attributes(ctk_object); } } /* display_config_clicked() */ @@ -4937,7 +5091,7 @@ static void display_refresh_changed(GtkWidget *widget, gpointer user_data) /* Update the modename */ setup_display_modename(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* display_refresh_changed() */ @@ -5004,7 +5158,7 @@ static void display_resolution_changed(GtkWidget *widget, gpointer user_data) setup_display_panning(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* display_resolution_changed() */ @@ -5092,8 +5246,7 @@ static void display_position_type_changed(GtkWidget *widget, setup_display_position_offset(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); - + user_changed_attributes(ctk_object); } /* display_position_type_changed() */ @@ -5146,7 +5299,7 @@ static void display_position_relative_changed(GtkWidget *widget, /* Update the GUI */ setup_display_position_offset(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* display_position_relative_changed() */ @@ -5188,7 +5341,7 @@ static void display_position_offset_activate(GtkWidget *widget, (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), display, CONF_ADJ_ABSOLUTE, NULL, x, y); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* display_position_offset_activate() */ @@ -5283,13 +5436,15 @@ static void screen_depth_changed(GtkWidget *widget, gpointer user_data) } ctk_display_layout_set_screen_depth (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, depth); + /* Update default screen depth in SMF using libscf functions */ + update_scf_depth(depth); consolidate_xinerama(ctk_object, screen); /* Can't apply screen depth changes */ ctk_object->apply_possible = FALSE; - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* screen_depth_changed() */ @@ -5350,7 +5505,7 @@ static void screen_position_type_changed(GtkWidget *widget, setup_screen_position_offset(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* screen_position_type_changed() */ @@ -5404,7 +5559,7 @@ static void screen_position_relative_changed(GtkWidget *widget, /* Update the GUI */ setup_screen_position_offset(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* screen_position_relative_changed() */ @@ -5446,7 +5601,7 @@ static void screen_position_offset_activate(GtkWidget *widget, (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, screen->position_type, screen->relative_to, x, y); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* screen_position_offset_activate() */ @@ -5533,7 +5688,7 @@ static void screen_metamode_activate(GtkWidget *widget, gpointer user_data) /* Sync the display frame */ setup_display_page(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* screen_metamode_activate() */ @@ -5563,7 +5718,7 @@ static void screen_metamode_add_clicked(GtkWidget *widget, gpointer user_data) setup_display_page(ctk_object); setup_screen_page(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* screen_metamode_add_clicked() */ @@ -5593,7 +5748,7 @@ static void screen_metamode_delete_clicked(GtkWidget *widget, setup_display_page(ctk_object); setup_screen_page(ctk_object); - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* screen_metamode_delete_clicked() */ @@ -5620,9 +5775,8 @@ static void xinerama_state_toggled(GtkWidget *widget, gpointer user_data) consolidate_xinerama(ctk_object, NULL); setup_screen_page(ctk_object); - /* Make the apply button sensitive to user input */ - gtk_widget_set_sensitive(ctk_object->btn_apply, True); - + user_changed_attributes(ctk_object); + } /* xinerama_state_toggled() */ @@ -6148,7 +6302,9 @@ static int update_screen_metamodes(CtkDisplayConfig *ctk_object, /* If we need to switch metamodes, do so now */ if (strcmp(screen->cur_metamode->string, metamode_str)) { + if (switch_to_current_metamode(ctk_object, screen)) { + ctk_config_statusbar_message(ctk_object->ctk_config, "Switched to MetaMode %dx%d.", screen->cur_metamode->edim[W], @@ -6186,7 +6342,7 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data) CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); nvGpuPtr gpu; ReturnStatus ret; - int clear_apply = 1; + gboolean clear_apply = TRUE; /* Make sure we can apply */ @@ -6199,6 +6355,9 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data) return; } + /* Temporarily unregister events */ + unregister_layout_events(ctk_object); + /* Update all GPUs */ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { nvScreenPtr screen; @@ -6232,7 +6391,8 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data) if (screen->primaryDisplay) { gchar *primary_str = - display_get_type_str(screen->primaryDisplay->device_mask, 0); + display_get_type_str(screen->primaryDisplay->device_mask, + 0); ret = NvCtrlSetStringAttribute(screen->handle, NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER, @@ -6255,8 +6415,21 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data) /* Clear the apply button if all went well */ if (clear_apply) { gtk_widget_set_sensitive(widget, False); + ctk_object->forced_reset_allowed = TRUE; + } + + /* XXX Run the GTK main loop to flush any pending layout events + * that should be ignored. This is done because the GTK main loop + * seems to only ignore the first blocked event received when it + * finally runs. + */ + while (gtk_events_pending()) { + gtk_main_iteration_do(FALSE); } + /* re-register to receive events */ + register_layout_events(ctk_object); + } /* apply_clicked() */ @@ -6393,7 +6566,7 @@ static gboolean update_xconfig_save_buffer(CtkDisplayConfig *ctk_object) /* Find out if the file is mergable */ - if (!filename) { + if (!filename || (filename[0] == '\0')) { mergable = FALSE; } else { /* Must be able to open the file */ @@ -6805,7 +6978,7 @@ static XConfigDevicePtr add_device_to_xconfig(nvGpuPtr gpu, XConfigPtr config, /* Fill out the device information */ device->identifier = (char *)malloc(32); - snprintf(device->identifier, 32, "Videocard%d", device_id); + snprintf(device->identifier, 32, "Device%d", device_id); device->driver = xconfigStrdup("nvidia"); device->vendor = xconfigStrdup("NVIDIA Corporation"); @@ -7679,11 +7852,15 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data) gchar *type; gchar *str; - /* Probe each GPU for display changes */ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { + if (!gpu->handle) continue; - + + g_signal_handlers_block_by_func + (G_OBJECT(gpu->ctk_event), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); /* Do the probe */ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_PROBE_DISPLAYS, @@ -7691,6 +7868,12 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data) if (ret != NvCtrlSuccess) { nv_error_msg("Failed to probe for display devices on GPU-%d '%s'.", NvCtrlGetTargetId(gpu->handle), gpu->name); + + g_signal_handlers_unblock_by_func + (G_OBJECT(gpu->ctk_event), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); + continue; } @@ -7745,8 +7928,7 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data) ctk_display_layout_update_display_count (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), NULL); - /* Activate the apply button */ - gtk_widget_set_sensitive(ctk_object->btn_apply, True); + user_changed_attributes(ctk_object); } /* Add new displays as 'disabled' */ @@ -7764,6 +7946,11 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data) selected_display); } } + + g_signal_handlers_unblock_by_func + (G_OBJECT(gpu->ctk_event), + G_CALLBACK(display_config_attribute_changed), + (gpointer) ctk_object); } @@ -7778,6 +7965,68 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data) +/** reset_layout() ************************************************* + * + * Load current X server settings. + * + **/ + +static void reset_layout(CtkDisplayConfig *ctk_object) +{ + gchar *err_str = NULL; + nvLayoutPtr layout; + /* Load the current layout */ + layout = layout_load_from_server(ctk_object->handle, &err_str); + + + /* Handle errors loading the new layout */ + if (!layout || err_str) { + nv_error_msg(err_str); + g_free(err_str); + return; + } + + + /* Free existing layout */ + unregister_layout_events(ctk_object); + layout_free(ctk_object->layout); + + + /* Setup the new layout */ + ctk_object->layout = layout; + ctk_display_layout_set_layout((CtkDisplayLayout *)(ctk_object->obj_layout), + ctk_object->layout); + + register_layout_events(ctk_object); + + + /* Make sure all X screens have the same depth if Xinerama is enabled */ + consolidate_xinerama(ctk_object, NULL); + + /* Make sure X screens have some kind of position */ + assign_screen_positions(ctk_object); + + + /* Setup the GUI */ + setup_layout_frame(ctk_object); + setup_display_page(ctk_object); + setup_screen_page(ctk_object); + + /* Get new position */ + get_cur_screen_pos(ctk_object); + + /* Clear the apply button */ + ctk_object->apply_possible = TRUE; + gtk_widget_set_sensitive(ctk_object->btn_apply, FALSE); + + ctk_object->forced_reset_allowed = TRUE; /* OK to reset w/o user input */ + ctk_object->notify_user_of_reset = TRUE; /* Notify user of new changes */ + ctk_object->reset_required = FALSE; /* No reset required to apply */ + +} /* reset_layout() */ + + + /** reset_clicked() ************************************************** * * Called when user clicks on the "Reset" button. @@ -7787,9 +8036,7 @@ static void probe_clicked(GtkWidget *widget, gpointer user_data) static void reset_clicked(GtkWidget *widget, gpointer user_data) { CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data); - nvLayoutPtr layout; gint result; - gchar *err_str = NULL; /* Show the confirm dialog */ @@ -7813,48 +8060,168 @@ static void reset_clicked(GtkWidget *widget, gpointer user_data) return; } + reset_layout(ctk_object); - /* Load the current layout */ - layout = layout_load_from_server(ctk_object->handle, &err_str); +} /* reset_clicked() */ - /* Handle errors loading the new layout */ - if (!layout || err_str) { - nv_error_msg(err_str); - g_free(err_str); - return; - } +/** force_layout_reset() ****************************************** + * + * Pop up dialog box to user when the layout needs to be reloaded + * due to changes made to the server layout by another client. + * + **/ - /* Free the existing layout */ - layout_free(ctk_object->layout); +static gboolean force_layout_reset(gpointer user_data) +{ + gint result; + GtkWidget *parent; + GtkWidget *dlg; + CtkDisplayConfig *ctk_object = (CtkDisplayConfig *) user_data; + if ((ctk_object->forced_reset_allowed) ) { + /* It is OK to force a reset of the layout since no + * changes have been made. + */ + reset_layout(ctk_object); + goto done; + } - /* Setup the new layout */ - ctk_object->layout = layout; - ctk_display_layout_set_layout((CtkDisplayLayout *)(ctk_object->obj_layout), - ctk_object->layout); + /* It is not OK to force a reset of the layout since the user + * may have changed some settings. The user will need to + * reset the layout manually. + */ - /* Make sure all X screens have the same depth if Xinerama is enabled */ - consolidate_xinerama(ctk_object, NULL); + ctk_object->reset_required = TRUE; - /* Make sure X screens have some kind of position */ - assign_screen_positions(ctk_object); + /* If the X server display configuration page is not currently + * selected, we will need to notify the user once they get + * back to it. + */ + if (!ctk_object->page_selected) goto done; + /* Notify the user of the required reset if they haven't + * already been notified. + */ + if (!ctk_object->notify_user_of_reset) goto done; - /* Setup the GUI */ - setup_layout_frame(ctk_object); - setup_display_page(ctk_object); - setup_screen_page(ctk_object); + parent = ctk_get_parent_window(GTK_WIDGET(ctk_object)); - /* Get new position */ - get_cur_screen_pos(ctk_object); + dlg = gtk_message_dialog_new + (GTK_WINDOW(parent), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_NONE, + "Your current changes to the X server display configuration may no " + "longer be applied due to changes made to the running X server.\n\n" + "You may either reload the current X server settings and lose any " + "configuration setup in this page, or select \"Cancel\" and save " + "your changes to the X configuration file (requires restarting X " + "to take effect.)\n\n" + "If you select \"Cancel\", you will only be allowed to apply " + "settings once you have reset the configuration."); + + gtk_dialog_add_buttons(GTK_DIALOG(dlg), + "Reload current X server settings", + GTK_RESPONSE_YES, + "Cancel", GTK_RESPONSE_CANCEL, + NULL); + + result = gtk_dialog_run(GTK_DIALOG(dlg)); + switch (result) { + case GTK_RESPONSE_YES: + reset_layout(ctk_object); + break; + case GTK_RESPONSE_CANCEL: + /* Fall through */ + default: + /* User does not want to reset the layout, don't allow them + * to apply their changes (but allow them to save their changes) + * until they have reloaded the layout manually. + */ + ctk_object->notify_user_of_reset = FALSE; + gtk_widget_set_sensitive(ctk_object->btn_apply, False); + break; + } + gtk_widget_destroy(dlg); - /* Clear the apply button */ - ctk_object->apply_possible = TRUE; - gtk_widget_set_sensitive(ctk_object->btn_apply, FALSE); +done: + ctk_object->ignore_reset_events = FALSE; + return FALSE; -} /* reset_clicked() */ +} /* force_layout_reset() */ + + + +/** display_config_attribute_changed() ******************************* + * + * Callback function for all display config page related events + * change. + * + * Display configuration changes usually involve multiple related + * events in succession. To avoid reloading the layout for every + * event, we register the force_layout_reset() function (once per + * block of events) to be called when the app becomes idle (which + * will happen once there are no more pending events) using + * g_idle_add(). Once force_layout_reset() is called, it will + * unresgister itself by returning FALSE. + * + **/ + +static void display_config_attribute_changed(GtkObject *object, gpointer arg1, + gpointer user_data) +{ + CtkDisplayConfig *ctk_object = (CtkDisplayConfig *) user_data; + + if (ctk_object->ignore_reset_events) return; + + ctk_object->ignore_reset_events = TRUE; + + /* queue force_layout_reset() to be called once all other pending + * events are consumed. + */ + g_idle_add(force_layout_reset, (gpointer)ctk_object); + +} /* display_config_attribute_changed() */ + + + +/** ctk_display_config_unselected() ********************************** + * + * Called when display config page is unselected. + * + **/ + +void ctk_display_config_unselected(GtkWidget *widget) { + CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(widget); + + ctk_object->page_selected = FALSE; + +} /* ctk_display_config_unselected() */ + + + +/** ctk_display_config_selected() *********************************** + * + * Called when display config page is selected. + * + **/ + +void ctk_display_config_selected(GtkWidget *widget) { + CtkDisplayConfig *ctk_object=CTK_DISPLAY_CONFIG(widget); + + ctk_object->page_selected = TRUE; + + /* Handle case where a layout reset is required but we could + * not notify the user since the X server display configuration + * page was not selected + */ + if (ctk_object->reset_required) { + force_layout_reset(ctk_object); + } + +} /* ctk_display_config_selected() */ diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h index 3a8348d..e87e8ab 100644 --- a/src/gtk+-2.x/ctkdisplayconfig.h +++ b/src/gtk+-2.x/ctkdisplayconfig.h @@ -60,6 +60,7 @@ typedef struct _CtkDisplayConfig NvCtrlAttributeHandle *handle; CtkConfig *ctk_config; + gboolean page_selected; /* Is the display config page selected in the UI */ /* Layout */ nvLayoutPtr layout; @@ -173,6 +174,12 @@ typedef struct _CtkDisplayConfig /* Buttons */ GtkWidget *btn_apply; gboolean apply_possible; /* True if all modifications are applicable */ + + gboolean reset_required; /* Reser required to apply */ + gboolean forced_reset_allowed; /* OK to reset layout w/o user input */ + gboolean notify_user_of_reset; /* User was notified of reset requirement */ + gboolean ignore_reset_events; /* Ignore reset-causing events */ + int cur_screen_pos[2]; /* Keep track of the selected X screen's position */ GtkWidget *btn_save; @@ -198,6 +205,10 @@ GtkWidget* ctk_display_config_new (NvCtrlAttributeHandle *, GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *, CtkDisplayConfig *); +void ctk_display_config_selected(GtkWidget *); +void ctk_display_config_unselected(GtkWidget *); + + G_END_DECLS #endif /* __CTK_DISPLAYCONFIG_H__ */ diff --git a/src/gtk+-2.x/ctkdisplaydevice-crt.c b/src/gtk+-2.x/ctkdisplaydevice-crt.c index 4f391c7..991875b 100644 --- a/src/gtk+-2.x/ctkdisplaydevice-crt.c +++ b/src/gtk+-2.x/ctkdisplaydevice-crt.c @@ -92,6 +92,13 @@ static void ctk_display_device_crt_finalize( { CtkDisplayDeviceCrt *ctk_display_device_crt = CTK_DISPLAY_DEVICE_CRT(object); g_free(ctk_display_device_crt->name); + g_signal_handlers_disconnect_matched(ctk_display_device_crt->ctk_event, + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + (gpointer) ctk_display_device_crt); } /* @@ -115,6 +122,7 @@ GtkWidget* ctk_display_device_crt_new(NvCtrlAttributeHandle *handle, GtkWidget *alignment; object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_CRT, NULL); + if (!object) return NULL; ctk_display_device_crt = CTK_DISPLAY_DEVICE_CRT(object); ctk_display_device_crt->handle = handle; diff --git a/src/gtk+-2.x/ctkdisplaydevice-dfp.c b/src/gtk+-2.x/ctkdisplaydevice-dfp.c index 13da164..86c2a66 100644 --- a/src/gtk+-2.x/ctkdisplaydevice-dfp.c +++ b/src/gtk+-2.x/ctkdisplaydevice-dfp.c @@ -169,6 +169,13 @@ static void ctk_display_device_dfp_finalize( { CtkDisplayDeviceDfp *ctk_display_device_dfp = CTK_DISPLAY_DEVICE_DFP(object); g_free(ctk_display_device_dfp->name); + g_signal_handlers_disconnect_matched(ctk_display_device_dfp->ctk_event, + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + (gpointer) ctk_display_device_dfp); } @@ -199,9 +206,11 @@ GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle, GtkWidget *table; object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_DFP, NULL); + if (!object) return NULL; ctk_display_device_dfp = CTK_DISPLAY_DEVICE_DFP(object); ctk_display_device_dfp->handle = handle; + ctk_display_device_dfp->ctk_event = ctk_event; ctk_display_device_dfp->ctk_config = ctk_config; ctk_display_device_dfp->display_device_mask = display_device_mask; ctk_display_device_dfp->name = g_strdup(name); diff --git a/src/gtk+-2.x/ctkdisplaydevice-tv.c b/src/gtk+-2.x/ctkdisplaydevice-tv.c index 4db531c..12773e6 100644 --- a/src/gtk+-2.x/ctkdisplaydevice-tv.c +++ b/src/gtk+-2.x/ctkdisplaydevice-tv.c @@ -131,6 +131,13 @@ static void ctk_display_device_tv_finalize( { CtkDisplayDeviceTv *ctk_display_device_tv = CTK_DISPLAY_DEVICE_TV(object); g_free(ctk_display_device_tv->name); + g_signal_handlers_disconnect_matched(ctk_display_device_tv->ctk_event, + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + (gpointer) ctk_display_device_tv); } @@ -156,6 +163,7 @@ GtkWidget* ctk_display_device_tv_new(NvCtrlAttributeHandle *handle, object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_TV, NULL); + if (!object) return NULL; ctk_display_device_tv = CTK_DISPLAY_DEVICE_TV(object); ctk_display_device_tv->handle = handle; diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c index 3f38c1e..6d8b620 100644 --- a/src/gtk+-2.x/ctkdisplaylayout.c +++ b/src/gtk+-2.x/ctkdisplaylayout.c @@ -2372,7 +2372,8 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, pango_font_description_set_family(font_description, "Sans"); pango_font_description_set_weight(font_description, PANGO_WEIGHT_BOLD); - pango_layout_set_font_description(ctk_object->pango_layout, font_description); + pango_layout_set_font_description(ctk_object->pango_layout, + font_description); /* Setup colors */ @@ -2404,23 +2405,28 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, GDK_POINTER_MOTION_MASK); g_signal_connect (G_OBJECT (tmp), "expose_event", - G_CALLBACK (expose_event_callback), (gpointer)(ctk_object)); + G_CALLBACK (expose_event_callback), + (gpointer)(ctk_object)); g_signal_connect (G_OBJECT (tmp), "configure_event", - G_CALLBACK (configure_event_callback), (gpointer)(ctk_object)); + G_CALLBACK (configure_event_callback), + (gpointer)(ctk_object)); g_signal_connect (G_OBJECT (tmp), "motion_notify_event", - G_CALLBACK (motion_event_callback), (gpointer)(ctk_object)); + G_CALLBACK (motion_event_callback), + (gpointer)(ctk_object)); g_signal_connect (G_OBJECT (tmp), "button_press_event", - G_CALLBACK (button_press_event_callback), (gpointer)(ctk_object)); + G_CALLBACK (button_press_event_callback), + (gpointer)(ctk_object)); g_signal_connect (G_OBJECT (tmp), "button_release_event", - G_CALLBACK (button_release_event_callback), (gpointer)(ctk_object)); + G_CALLBACK (button_release_event_callback), + (gpointer)(ctk_object)); GTK_WIDGET_SET_FLAGS(tmp, GTK_DOUBLE_BUFFERED); - ctk_object->drawing_area = tmp; + ctk_object->drawing_area = tmp; gtk_widget_set_size_request(tmp, width, height); @@ -2445,6 +2451,26 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, +/** get_widget_fg_gc() *********************************************** + * + * Returns the foreground graphics context of the given widget. If + * this function returns NULL, then drawing on this widget is not + * currently possible and should be avoided. + * + **/ + +static GdkGC *get_widget_fg_gc(GtkWidget *widget) +{ + GtkStyle *style = gtk_widget_get_style(widget); + + if (!style) return NULL; + + return style->fg_gc[GTK_WIDGET_STATE(widget)]; + +} /* get_widget_fg_gc() */ + + + /** do_swap() ******************************************************** * * Preforms a swap from the back buffer if one is needed. @@ -2453,10 +2479,13 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle, static void do_swap(CtkDisplayLayout *ctk_object) { - if (ctk_object->need_swap) { + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); + + if (ctk_object->need_swap && drawing_area->window && fg_gc) { - gdk_draw_pixmap(ctk_object->drawing_area->window, - ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], + gdk_draw_pixmap(drawing_area->window, + fg_gc, ctk_object->pixmap, 0,0, 0,0, @@ -2482,16 +2511,18 @@ static void draw_rect(CtkDisplayLayout *ctk_object, GdkColor *color, int fill) { + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); + int w = (int)(ctk_object->scale * (dim[X] + dim[W])) - (int)(ctk_object->scale * (dim[X])); int h = (int)(ctk_object->scale * (dim[Y] + dim[H])) - (int)(ctk_object->scale * (dim[Y])); /* Setup color to use */ - gdk_gc_set_rgb_fg_color(ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE (ctk_object->drawing_area)], - color); + gdk_gc_set_rgb_fg_color(fg_gc, color); /* Draw the rectangle */ gdk_draw_rectangle(ctk_object->pixmap, - ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE (ctk_object->drawing_area)], + fg_gc, fill, ctk_object->img_dim[X] + ctk_object->scale * dim[X], ctk_object->img_dim[Y] + ctk_object->scale * dim[Y], @@ -2517,8 +2548,8 @@ static void draw_rect_strs(CtkDisplayLayout *ctk_object, const char *str_1, const char *str_2) { - GdkGC *gdk_gc; - GtkWidget *drawing_area; + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); char *str; int txt_w; @@ -2529,9 +2560,6 @@ static void draw_rect_strs(CtkDisplayLayout *ctk_object, int draw_1 = 0; int draw_2 = 0; - drawing_area = ctk_object->drawing_area; - gdk_gc = drawing_area->style->fg_gc[GTK_WIDGET_STATE(drawing_area)]; - if (str_1) { pango_layout_set_text(ctk_object->pango_layout, str_1, -1); pango_layout_get_pixel_size(ctk_object->pango_layout, &txt_w, &txt_h); @@ -2572,9 +2600,10 @@ static void draw_rect_strs(CtkDisplayLayout *ctk_object, txt_y1 = ctk_object->scale*(dim[Y] + dim[H] / 2) - (txt_h / 2); /* Write name */ - gdk_gc_set_rgb_fg_color(gdk_gc, color); + gdk_gc_set_rgb_fg_color(fg_gc, color); - gdk_draw_layout(ctk_object->pixmap, gdk_gc, + gdk_draw_layout(ctk_object->pixmap, + fg_gc, ctk_object->img_dim[X] + txt_x1, ctk_object->img_dim[Y] + txt_y1, ctk_object->pango_layout); @@ -2590,9 +2619,10 @@ static void draw_rect_strs(CtkDisplayLayout *ctk_object, txt_y2 = ctk_object->scale*(dim[Y] + dim[H] / 2) - (txt_h / 2); /* Write dimensions */ - gdk_gc_set_rgb_fg_color(gdk_gc, color); + gdk_gc_set_rgb_fg_color(fg_gc, color); - gdk_draw_layout(ctk_object->pixmap, gdk_gc, + gdk_draw_layout(ctk_object->pixmap, + fg_gc, ctk_object->img_dim[X] + txt_x2, ctk_object->img_dim[Y] + txt_y2, ctk_object->pango_layout); @@ -2610,9 +2640,10 @@ static void draw_rect_strs(CtkDisplayLayout *ctk_object, txt_y = ctk_object->scale*(dim[Y] + dim[H] / 2) - (txt_h / 2); /* Write both */ - gdk_gc_set_rgb_fg_color(gdk_gc, color); + gdk_gc_set_rgb_fg_color(fg_gc, color); - gdk_draw_layout(ctk_object->pixmap, gdk_gc, + gdk_draw_layout(ctk_object->pixmap, + fg_gc, ctk_object->img_dim[X] + txt_x, ctk_object->img_dim[Y] + txt_y, ctk_object->pango_layout); @@ -2634,27 +2665,29 @@ static void draw_display(CtkDisplayLayout *ctk_object, nvDisplayPtr display) { nvModePtr mode; - int color; + int base_color_idx; + int color_idx; char *tmp_str; if (!display || !(display->cur_mode)) { return; } - mode = display->cur_mode; - color = NUM_COLORS_PER_PALETTE * NvCtrlGetTargetId(display->gpu->handle); + mode = display->cur_mode; + base_color_idx = + NUM_COLORS_PER_PALETTE * NvCtrlGetTargetId(display->gpu->handle); /* Draw panning */ - draw_rect(ctk_object, mode->pan, - &(ctk_object->color_palettes[color +((mode->modeline)?BG_PAN_ON:BG_PAN_OFF)]), + color_idx = base_color_idx + ((mode->modeline) ? BG_PAN_ON : BG_PAN_OFF); + draw_rect(ctk_object, mode->pan, &(ctk_object->color_palettes[color_idx]), 1); draw_rect(ctk_object, mode->pan, &(ctk_object->fg_color), 0); /* Draw viewport */ - draw_rect(ctk_object, mode->dim, - &(ctk_object->color_palettes[color +((mode->modeline)?BG_SCR_ON:BG_SCR_OFF)]), + color_idx = base_color_idx + ((mode->modeline) ? BG_SCR_ON : BG_SCR_OFF); + draw_rect(ctk_object, mode->dim, &(ctk_object->color_palettes[color_idx]), 1); draw_rect(ctk_object, mode->dim, &(ctk_object->fg_color), 0); @@ -2686,21 +2719,22 @@ static void draw_display(CtkDisplayLayout *ctk_object, static void draw_layout(CtkDisplayLayout *ctk_object) { - int z; + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); + GdkColor bg_color; /* Background color */ GdkColor bd_color; /* Border color */ nvGpuPtr gpu; nvScreenPtr screen; + int z; /* Draw the metamode's effective size */ gdk_color_parse("#888888", &bg_color); gdk_color_parse("#777777", &bd_color); - gdk_gc_set_line_attributes - (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], - 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_NOT_LAST, - GDK_JOIN_ROUND); + gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_ON_OFF_DASH, + GDK_CAP_NOT_LAST, GDK_JOIN_ROUND); for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) { for (screen = gpu->screens; screen; screen = screen->next) { @@ -2710,10 +2744,8 @@ static void draw_layout(CtkDisplayLayout *ctk_object) } } - gdk_gc_set_line_attributes - (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], - 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, - GDK_JOIN_ROUND); + gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, + GDK_JOIN_ROUND); /* Draw display devices from back to front */ @@ -2725,7 +2757,6 @@ static void draw_layout(CtkDisplayLayout *ctk_object) /* Hilite the selected display device */ if (ctk_object->Zselected && ctk_object->Zcount) { - GtkWidget *widget = ctk_object->drawing_area; int w, h; int size; /* Hilite line size */ int offset; /* Hilite box offset */ @@ -2738,8 +2769,7 @@ static void draw_layout(CtkDisplayLayout *ctk_object) h = (int)(ctk_object->scale * (dim[Y] + dim[H])) - (int)(ctk_object->scale * (dim[Y])); /* Setup color to use */ - gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - &(ctk_object->select_color)); + gdk_gc_set_rgb_fg_color(fg_gc, &(ctk_object->select_color)); /* If dislay is too small, just color the whole thing */ size = 3; @@ -2750,19 +2780,19 @@ static void draw_layout(CtkDisplayLayout *ctk_object) draw_rect(ctk_object, dim, &(ctk_object->fg_color), 0); } else { - gdk_gc_set_line_attributes(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - size, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND); + gdk_gc_set_line_attributes(fg_gc, size, GDK_LINE_SOLID, + GDK_CAP_ROUND, GDK_JOIN_ROUND); gdk_draw_rectangle(ctk_object->pixmap, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + fg_gc, 0, ctk_object->img_dim[X] +(ctk_object->scale * dim[X]) +offset, ctk_object->img_dim[Y] +(ctk_object->scale * dim[Y]) +offset, w -(2 * offset), h -(2 * offset)); - gdk_gc_set_line_attributes(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - 1, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND); + gdk_gc_set_line_attributes(fg_gc, 1, GDK_LINE_SOLID, GDK_CAP_ROUND, + GDK_JOIN_ROUND); } @@ -2811,46 +2841,44 @@ static void draw_layout(CtkDisplayLayout *ctk_object) static void clear_layout(CtkDisplayLayout *ctk_object) { - GtkWidget *widget = ctk_object->drawing_area; + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); GdkColor color; - /* Clear to background color */ - gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - &(ctk_object->bg_color)); + gdk_gc_set_rgb_fg_color(fg_gc, &(ctk_object->bg_color)); + gdk_draw_rectangle(ctk_object->pixmap, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + fg_gc, TRUE, 2, 2, - widget->allocation.width -4, - widget->allocation.height -4); + drawing_area->allocation.width -4, + drawing_area->allocation.height -4); /* Add white trim */ gdk_color_parse("white", &color); - gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - &color); + gdk_gc_set_rgb_fg_color(fg_gc, &color); gdk_draw_rectangle(ctk_object->pixmap, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + fg_gc, FALSE, 1, 1, - widget->allocation.width -3, - widget->allocation.height -3); + drawing_area->allocation.width -3, + drawing_area->allocation.height -3); /* Add layout border */ - gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - &(ctk_object->fg_color)); + gdk_gc_set_rgb_fg_color(fg_gc, &(ctk_object->fg_color)); gdk_draw_rectangle(ctk_object->pixmap, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + fg_gc, FALSE, 0, 0, - widget->allocation.width -1, - widget->allocation.height -1); + drawing_area->allocation.width -1, + drawing_area->allocation.height -1); ctk_object->need_swap = 1; @@ -2866,21 +2894,20 @@ static void clear_layout(CtkDisplayLayout *ctk_object) static void draw_all(CtkDisplayLayout *ctk_object) { - GdkGCValues old_gc_values; - GtkWidget *widget = ctk_object->drawing_area; - + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); + GdkGCValues old_gc_values; + + if (!fg_gc) return; /* Redraw everything */ - gdk_gc_get_values(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - &old_gc_values); + gdk_gc_get_values(fg_gc, &old_gc_values); clear_layout(ctk_object); draw_layout(ctk_object); - gdk_gc_set_values(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - &old_gc_values, - GDK_GC_FOREGROUND); + gdk_gc_set_values(fg_gc, &old_gc_values, GDK_GC_FOREGROUND); } /* draw_all() */ @@ -3290,6 +3317,8 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, nvDisplayPtr relative_to, int x, int y) { + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); GdkGCValues old_gc_values; int modified = 0; nvLayoutPtr layout = ctk_object->layout; @@ -3301,11 +3330,11 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, /* Backup the foreground color and clear the layout */ - gdk_gc_get_values - (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], - &old_gc_values); - - clear_layout(ctk_object); + if (fg_gc) { + gdk_gc_get_values(fg_gc, &old_gc_values); + + clear_layout(ctk_object); + } /* XXX When configuring a relative position, make sure @@ -3381,13 +3410,13 @@ void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object, /* Redraw the layout and reset the foreground color */ - draw_layout(ctk_object); - - gdk_gc_set_values - (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], - &old_gc_values, GDK_GC_FOREGROUND); + if (fg_gc) { + draw_layout(ctk_object); - do_swap(ctk_object); + gdk_gc_set_values(fg_gc, &old_gc_values, GDK_GC_FOREGROUND); + + do_swap(ctk_object); + } } /* ctk_display_layout_set_display_position() */ @@ -3403,6 +3432,8 @@ void ctk_display_layout_set_display_panning(CtkDisplayLayout *ctk_object, nvDisplayPtr display, int width, int height) { + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); GdkGCValues old_gc_values; int modified = 0; @@ -3411,10 +3442,11 @@ void ctk_display_layout_set_display_panning(CtkDisplayLayout *ctk_object, /* Backup the foreground color */ - gdk_gc_get_values(ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], - &old_gc_values); + if (fg_gc) { + gdk_gc_get_values(fg_gc, &old_gc_values); - clear_layout(ctk_object); + clear_layout(ctk_object); + } /* Change the panning */ @@ -3434,24 +3466,26 @@ void ctk_display_layout_set_display_panning(CtkDisplayLayout *ctk_object, ctk_object->modified_callback_data); } - draw_layout(ctk_object); + /* Redraw layout and reset the foreground color */ + if (fg_gc) { + draw_layout(ctk_object); - /* Reset the foreground color */ - gdk_gc_set_values(ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], - &old_gc_values, - GDK_GC_FOREGROUND); - - do_swap(ctk_object); + gdk_gc_set_values(fg_gc, &old_gc_values, GDK_GC_FOREGROUND); + do_swap(ctk_object); + } } /* ctk_display_layout_set_display_panning() */ + + /** ctk_display_layout_select_display() *********************** * * Updates the currently selected display. * **/ + void ctk_display_layout_select_display(CtkDisplayLayout *ctk_object, nvDisplayPtr display) { @@ -3462,8 +3496,11 @@ void ctk_display_layout_select_display(CtkDisplayLayout *ctk_object, /* Select the new topmost display */ select_display(ctk_object, ctk_object->Zorder[0]); } + } /* ctk_display_layout_select_display() */ + + /** ctk_display_layout_update_display_count() ************************ * * Updates the number of displays shown in the layout by re-building @@ -3479,6 +3516,7 @@ void ctk_display_layout_update_display_count(CtkDisplayLayout *ctk_object, /* Select the previously selected display */ ctk_display_layout_select_display(ctk_object, display); + } /* ctk_display_layout_update_display_count() */ @@ -3514,27 +3552,22 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object, nvScreenPtr relative_to, int x, int y) { + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); GdkGCValues old_gc_values; int modified = 0; nvLayoutPtr layout = ctk_object->layout; nvGpuPtr gpu; - int draw; + if (!screen) return; if (position_type != CONF_ADJ_ABSOLUTE && !relative_to) return; - /* If there is no GC for the drawing area, don't draw */ - draw = ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)] ? - 1 : 0; - - /* Backup the foreground color and clear the layout */ - if (draw) { - gdk_gc_get_values - (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], - &old_gc_values); + if (fg_gc) { + gdk_gc_get_values(fg_gc, &old_gc_values); clear_layout(ctk_object); } @@ -3634,12 +3667,10 @@ void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object, /* Redraw the layout and reset the foreground color */ - if (draw) { + if (fg_gc) { draw_layout(ctk_object); - gdk_gc_set_values - (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)], - &old_gc_values, GDK_GC_FOREGROUND); + gdk_gc_set_values(fg_gc, &old_gc_values, GDK_GC_FOREGROUND); do_swap(ctk_object); } @@ -3742,14 +3773,16 @@ static gboolean motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) { CtkDisplayLayout *ctk_object = CTK_DISPLAY_LAYOUT(data); - GdkGCValues old_gc_values; + GtkWidget *drawing_area = ctk_object->drawing_area; + GdkGC *fg_gc = get_widget_fg_gc(drawing_area); + GdkGCValues old_gc_values; static int init = 1; static int __modify_panning; if (init) { init = 0; - __modify_panning = (event->state & ShiftMask)?1:0; + __modify_panning = (event->state & ShiftMask) ? 1 : 0; } @@ -3767,8 +3800,7 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) /* Backup the foreground color */ - gdk_gc_get_values(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - &old_gc_values); + gdk_gc_get_values(fg_gc, &old_gc_values); /* Modify screen layout */ @@ -3783,8 +3815,8 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) clear_layout(ctk_object); /* Swap between panning and moving */ - if (__modify_panning != (event->state & ShiftMask)?1:0) { - __modify_panning = (event->state & ShiftMask)?1:0; + if (__modify_panning != ((event->state & ShiftMask) ? 1 : 0)) { + __modify_panning = ((event->state & ShiftMask) ? 1 : 0); sync_modify(ctk_object); } if (!(event->state & ShiftMask) || !ctk_object->advanced_mode) { @@ -3801,7 +3833,6 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) draw_layout(ctk_object); - /* Update the tooltip under the mouse */ } else { char *tip = @@ -3823,9 +3854,7 @@ motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) /* Reset the foreground color */ - gdk_gc_set_values(widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - &old_gc_values, - GDK_GC_FOREGROUND); + gdk_gc_set_values(fg_gc, &old_gc_values, GDK_GC_FOREGROUND); /* Refresh GUI */ @@ -3900,9 +3929,9 @@ button_press_event_callback(GtkWidget *widget, GdkEventButton *event, time = event->time; } - /* Redraw everything */ draw_all(ctk_object); + break; default: diff --git a/src/gtk+-2.x/ctkdropdownmenu.c b/src/gtk+-2.x/ctkdropdownmenu.c index 3fea606..3fca0b7 100644 --- a/src/gtk+-2.x/ctkdropdownmenu.c +++ b/src/gtk+-2.x/ctkdropdownmenu.c @@ -134,12 +134,17 @@ GtkWidget* ctk_drop_down_menu_new(guint flags) d->values = NULL; d->num_entries = 0; - d->menu = gtk_menu_new(); d->option_menu = gtk_option_menu_new(); - + d->menu = gtk_menu_new(); + + gtk_option_menu_set_menu(GTK_OPTION_MENU(d->option_menu), d->menu); + gtk_box_set_spacing(GTK_BOX(d), 0); gtk_box_pack_start(GTK_BOX(d), d->option_menu, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(d->option_menu), "changed", + G_CALLBACK(changed), (gpointer) d); + return GTK_WIDGET(d); } /* ctk_drop_down_menu_new() */ @@ -158,6 +163,8 @@ void ctk_drop_down_menu_reset(CtkDropDownMenu *d) d->num_entries = 0; d->menu = gtk_menu_new(); + + gtk_option_menu_set_menu(GTK_OPTION_MENU(d->option_menu), d->menu); } /* ctk_drop_down_menu_reset() */ @@ -168,9 +175,9 @@ void ctk_drop_down_menu_reset(CtkDropDownMenu *d) * menu */ -void ctk_drop_down_menu_append_item(CtkDropDownMenu *d, - const gchar *name, - const gint value) +GtkWidget *ctk_drop_down_menu_append_item(CtkDropDownMenu *d, + const gchar *name, + const gint value) { GtkWidget *menu_item, *label, *alignment; gchar *str; @@ -197,30 +204,14 @@ void ctk_drop_down_menu_append_item(CtkDropDownMenu *d, d->values[d->num_entries].value = value; d->num_entries++; + + return label; } /* ctk_drop_down_menu_append_item() */ /* - * ctk_drop_down_menu_finalize() - to be called once all menu entries - * have been added. - */ - -void ctk_drop_down_menu_finalize(CtkDropDownMenu *d) -{ - gtk_option_menu_set_menu(GTK_OPTION_MENU(d->option_menu), d->menu); - - g_signal_connect(G_OBJECT(d->option_menu), "changed", - G_CALLBACK(changed), (gpointer) d); - - gtk_widget_show_all(GTK_WIDGET(d)); - -} /* ctk_drop_down_menu_finalize() */ - - - -/* * ctk_drop_down_menu_get_current_value() - return the current value * selected in the drop down menu. */ diff --git a/src/gtk+-2.x/ctkdropdownmenu.h b/src/gtk+-2.x/ctkdropdownmenu.h index b1ee87d..b0c544d 100644 --- a/src/gtk+-2.x/ctkdropdownmenu.h +++ b/src/gtk+-2.x/ctkdropdownmenu.h @@ -85,10 +85,9 @@ struct _CtkDropDownMenuClass GType ctk_drop_down_menu_get_type (void) G_GNUC_CONST; GtkWidget* ctk_drop_down_menu_new (guint flags); -void ctk_drop_down_menu_append_item (CtkDropDownMenu *d, +GtkWidget* ctk_drop_down_menu_append_item (CtkDropDownMenu *d, const gchar *name, const gint value); -void ctk_drop_down_menu_finalize (CtkDropDownMenu *d); gint ctk_drop_down_menu_get_current_value (CtkDropDownMenu *d); void ctk_drop_down_menu_set_current_value (CtkDropDownMenu *d, gint value); diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c index 090f77d..1e056a7 100644 --- a/src/gtk+-2.x/ctkevent.c +++ b/src/gtk+-2.x/ctkevent.c @@ -254,7 +254,12 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) MAKE_SIGNAL(NV_CTRL_GVO_COMPOSITE_ALPHA_KEY); MAKE_SIGNAL(NV_CTRL_GVO_COMPOSITE_NUM_KEY_RANGES); MAKE_SIGNAL(NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT); + MAKE_SIGNAL(NV_CTRL_MODE_SET_EVENT); + MAKE_SIGNAL(NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE); MAKE_SIGNAL(NV_CTRL_DISPLAYPORT_LINK_RATE); + MAKE_SIGNAL(NV_CTRL_STEREO_EYES_EXCHANGE); + MAKE_SIGNAL(NV_CTRL_NO_SCANOUT); + MAKE_SIGNAL(NV_CTRL_GVO_CSC_CHANGED_EVENT); #undef MAKE_SIGNAL @@ -265,7 +270,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class) * knows about. */ -#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_DISPLAYPORT_LINK_RATE +#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GVO_CSC_CHANGED_EVENT #warning "There are attributes that do not emit signals!" #endif diff --git a/src/gtk+-2.x/ctkframelock.c b/src/gtk+-2.x/ctkframelock.c index 81aa319..66705fc 100644 --- a/src/gtk+-2.x/ctkframelock.c +++ b/src/gtk+-2.x/ctkframelock.c @@ -696,13 +696,13 @@ static GtkWidget *create_enable_confirm_dialog(CtkFramelock *ctk_framelock) GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_framelock))), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, - GTK_STOCK_OK, + GTK_STOCK_YES, GTK_RESPONSE_ACCEPT, NULL); ctk_framelock->enable_confirm_cancel_button = gtk_dialog_add_button(GTK_DIALOG(dialog), - GTK_STOCK_CANCEL, + GTK_STOCK_NO, GTK_RESPONSE_REJECT); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); @@ -2755,7 +2755,7 @@ static void update_enable_confirm_text(CtkFramelock *ctk_framelock) gchar *str; str = g_strdup_printf("Frame Lock has been enabled but no server\n" "device was selected. Would you like to keep\n" - "the current settings?\n" + "Frame Lock enabled on the selected devices?\n" "\n" "Disabling Frame Lock in %d seconds...", ctk_framelock->enable_confirm_countdown); diff --git a/src/gtk+-2.x/ctkgvo-csc.c b/src/gtk+-2.x/ctkgvo-csc.c index 16bca87..341b26f 100644 --- a/src/gtk+-2.x/ctkgvo-csc.c +++ b/src/gtk+-2.x/ctkgvo-csc.c @@ -28,14 +28,14 @@ #include <string.h> #include "ctkbanner.h" - -#include "ctkgvo-csc.h" - #include "ctkconfig.h" #include "ctkhelp.h" - #include "ctkdropdownmenu.h" +#include "ctkgvo-csc.h" + +#include "msg.h" + /* * The CtkGvoCsc widget is used to provide a way for configuring * custom Color Space Conversion Matrices, Offsets, and Scale Factors @@ -110,6 +110,10 @@ static void set_apply_button_senstive (CtkGvoCsc *ctk_gvo_csc); static void apply_csc_values (CtkGvoCsc *ctk_gvo_csc); +static void gvo_csc_event_received (GtkObject *object, + gpointer arg1, + gpointer user_data); + static GtkWidget *build_opengl_only_msg (void); /* @@ -137,8 +141,9 @@ static const char * __override_help = "custom CSC."; static const char * __initialize_help = -"The Initialize Color Space Conversion dropdown allows you to select between " -"some standard CSC configurations."; +"The Initialize Color Space Conversion drop down menu, when selected, " +"populates the Color Space Conversion Matrix, Offset, and Scale with the " +"values from the selected standard."; static const char * __csc_help = "The color space conversion matrix defines the paramaters used for " @@ -236,6 +241,7 @@ GtkWidget* ctk_gvo_csc_new(NvCtrlAttributeHandle *handle, ctk_gvo_csc = CTK_GVO_CSC(object); ctk_gvo_csc->handle = handle; ctk_gvo_csc->ctk_config = ctk_config; + ctk_gvo_csc->ctk_event = ctk_event; ctk_gvo_csc->gvo_parent = gvo_parent; ctk_gvo_csc->caps = caps; @@ -355,8 +361,7 @@ GtkWidget* ctk_gvo_csc_new(NvCtrlAttributeHandle *handle, CSC_STANDARD_IDENTITY_STRING, CSC_STANDARD_IDENTITY); - ctk_drop_down_menu_finalize - (CTK_DROP_DOWN_MENU(ctk_gvo_csc->initializeDropDown)); + gtk_widget_show_all(ctk_gvo_csc->initializeDropDown); gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_csc->initializeDropDown, @@ -364,6 +369,10 @@ GtkWidget* ctk_gvo_csc_new(NvCtrlAttributeHandle *handle, FALSE, // fill 5); // padding + ctk_drop_down_menu_set_current_value + (CTK_DROP_DOWN_MENU(ctk_gvo_csc->initializeDropDown), + CSC_STANDARD_ITU_601); + g_signal_connect(G_OBJECT(ctk_gvo_csc->initializeDropDown), "changed", G_CALLBACK(initialize_csc_dropdown_changed), @@ -645,6 +654,18 @@ GtkWidget* ctk_gvo_csc_new(NvCtrlAttributeHandle *handle, override_state_toggled(ctk_gvo_csc, override); + /* Listen to server events */ + + g_signal_connect(G_OBJECT(ctk_gvo_csc->ctk_event), + CTK_EVENT_NAME(NV_CTRL_GVO_CSC_CHANGED_EVENT), + G_CALLBACK(gvo_csc_event_received), + (gpointer) ctk_gvo_csc); + + g_signal_connect(G_OBJECT(ctk_gvo_csc->ctk_event), + CTK_EVENT_NAME(NV_CTRL_GVO_OVERRIDE_HW_CSC), + G_CALLBACK(gvo_csc_event_received), + (gpointer) ctk_gvo_csc); + /* show the page */ gtk_widget_show_all(GTK_WIDGET(object)); @@ -1016,6 +1037,114 @@ static void apply_csc_values(CtkGvoCsc *ctk_gvo_csc) } /* apply_csc_values() */ + +/* + * GVO CSC event handler. + */ + +static void gvo_csc_event_received(GtkObject *object, + gpointer arg1, + gpointer user_data) +{ + CtkEventStruct *event_struct = (CtkEventStruct *) arg1; + CtkGvoCsc *ctk_gvo_csc = CTK_GVO_CSC(user_data); + GtkWidget *widget; + gint attribute = event_struct->attribute; + gint value = event_struct->value; + ReturnStatus ret; + + float newCSCMatrix[3][3]; + float newCSCOffset[3]; + float newCSCScale[3]; + int row, column; + + + switch (attribute) { + + case NV_CTRL_GVO_CSC_CHANGED_EVENT: + + /* Re-query the GVO CSC matrix */ + + ret = NvCtrlGetGvoColorConversion(ctk_gvo_csc->handle, + newCSCMatrix, + newCSCOffset, + newCSCScale); + if (ret == NvCtrlSuccess) { + + for (row = 0; row < 3; row++) { + for (column = 0; column < 3; column++) { + g_signal_handlers_block_by_func + (G_OBJECT(ctk_gvo_csc->matrixWidget[row][column]), + G_CALLBACK(spin_button_value_changed), + (gpointer) ctk_gvo_csc); + ctk_gvo_csc->matrix[row][column] = newCSCMatrix[row][column]; + gtk_spin_button_set_value + (GTK_SPIN_BUTTON(ctk_gvo_csc->matrixWidget[row][column]), + ctk_gvo_csc->matrix[row][column]); + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_gvo_csc->matrixWidget[row][column]), + G_CALLBACK(spin_button_value_changed), + (gpointer) ctk_gvo_csc); + } + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_gvo_csc->offsetWidget[row]), + G_CALLBACK(spin_button_value_changed), + (gpointer) ctk_gvo_csc); + ctk_gvo_csc->offset[row] = newCSCOffset[row]; + gtk_spin_button_set_value + (GTK_SPIN_BUTTON(ctk_gvo_csc->offsetWidget[row]), + ctk_gvo_csc->offset[row]); + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_gvo_csc->offsetWidget[row]), + G_CALLBACK(spin_button_value_changed), + (gpointer) ctk_gvo_csc); + + g_signal_handlers_block_by_func + (G_OBJECT(ctk_gvo_csc->scaleWidget[row]), + G_CALLBACK(spin_button_value_changed), + (gpointer) ctk_gvo_csc); + ctk_gvo_csc->scale[row] = newCSCScale[row]; + gtk_spin_button_set_value + (GTK_SPIN_BUTTON(ctk_gvo_csc->scaleWidget[row]), + ctk_gvo_csc->scale[row]); + g_signal_handlers_unblock_by_func + (G_OBJECT(ctk_gvo_csc->scaleWidget[row]), + G_CALLBACK(spin_button_value_changed), + (gpointer) ctk_gvo_csc); + } + } + + gtk_widget_set_sensitive(ctk_gvo_csc->applyButton, FALSE); + break; + + case NV_CTRL_GVO_OVERRIDE_HW_CSC: + widget = ctk_gvo_csc->overrideButton; + + g_signal_handlers_block_by_func(G_OBJECT(widget), + G_CALLBACK(override_button_toggled), + (gpointer) ctk_gvo_csc); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), value); + override_state_toggled(ctk_gvo_csc, value); + + gtk_widget_set_sensitive(ctk_gvo_csc->applyButton, FALSE); + + g_signal_handlers_unblock_by_func(G_OBJECT(widget), + G_CALLBACK(override_button_toggled), + (gpointer) ctk_gvo_csc); + break; + + default: + nv_error_msg("Unhandled GVO CSC event received: %d\n", + attribute); + break; + } + +} /* gvo_csc_event_recieved() */ + + + /* * build_opengl_only_msg() - build a message to inform the user that * custom CSC will only be applied to OpenGL GVO output; this returns diff --git a/src/gtk+-2.x/ctkgvo-csc.h b/src/gtk+-2.x/ctkgvo-csc.h index ff50cfe..04757df 100644 --- a/src/gtk+-2.x/ctkgvo-csc.h +++ b/src/gtk+-2.x/ctkgvo-csc.h @@ -62,6 +62,7 @@ struct _CtkGvoCsc NvCtrlAttributeHandle *handle; CtkConfig *ctk_config; + CtkEvent *ctk_event; CtkGvo *gvo_parent; GtkWidget *banner_box; diff --git a/src/gtk+-2.x/ctkgvo-sync.c b/src/gtk+-2.x/ctkgvo-sync.c index cf3554f..1ac2e12 100644 --- a/src/gtk+-2.x/ctkgvo-sync.c +++ b/src/gtk+-2.x/ctkgvo-sync.c @@ -84,7 +84,6 @@ static void update_gvo_sync_sensitivity(CtkGvoSync *ctk_gvo_sync); static void update_input_video_format_text_entry(CtkGvoSync *ctk_gvo_sync); static void post_composite_termination_toggled(CtkGvoSync *ctk_gvo_sync, gboolean enabled); -static void update_delay_spin_buttons_range(CtkGvoSync *ctk_gvo_sync); static void detect_input_toggled(GtkToggleButton *togglebutton, @@ -335,7 +334,8 @@ GtkWidget* ctk_gvo_sync_new(NvCtrlAttributeHandle *handle, GtkWidget *table, *menu; - gint val, i, width, height; + gint val, i; + NVCTRLAttributeValidValuesRec valid; ReturnStatus ret; gint row; @@ -531,9 +531,6 @@ GtkWidget* ctk_gvo_sync_new(NvCtrlAttributeHandle *handle, gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); - - ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_PIXELS, &val); - if (ret != NvCtrlSuccess) val = 0; ctk_gvo_sync->sync_lock_status_text = gtk_label_new(""); @@ -551,116 +548,114 @@ GtkWidget* ctk_gvo_sync_new(NvCtrlAttributeHandle *handle, /* - * Synchronization Delay/Advance + * Synchronization Skew (Delay/Advance) */ - - ctk_gvo_get_video_format_resolution(ctk_gvo_sync->input_video_format, - &width, &height); /* NV_CTRL_GVO_SYNC_DELAY_PIXELS */ - if ( ctk_gvo_sync->caps && NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW ) { - label = gtk_label_new("HSync Advance:"); - } else { - label = gtk_label_new("HSync Delay:"); - } + ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GVO_SYNC_DELAY_PIXELS, + &valid); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, - GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); - - ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_PIXELS, &val); - if (ret != NvCtrlSuccess) val = 0; + if ((ret == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE)) { + ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_PIXELS, &val); + if (ret != NvCtrlSuccess) val = 0; - if (width < 1) width = 1; + if (ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW) { + label = gtk_label_new("HSync Advance:"); + help_text = __hsync_advance_help; + } else { + label = gtk_label_new("HSync Delay:"); + help_text = __hsync_delay_help; + } - if ( ctk_gvo_sync->caps && NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW ) { - width = INT_MAX; - help_text = __hsync_advance_help; - } else { - help_text = __hsync_delay_help; - } + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, + GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); - ctk_gvo_sync->hsync_delay_spin_button = - gtk_spin_button_new_with_range(0.0, width, 1); + ctk_gvo_sync->hsync_delay_spin_button = + gtk_spin_button_new_with_range(valid.u.range.min, + valid.u.range.max, 1); - ctk_config_set_tooltip(ctk_config, - ctk_gvo_sync->hsync_delay_spin_button, - help_text); + ctk_config_set_tooltip(ctk_config, + ctk_gvo_sync->hsync_delay_spin_button, + help_text); - gtk_spin_button_set_value - (GTK_SPIN_BUTTON(ctk_gvo_sync->hsync_delay_spin_button), val); + gtk_spin_button_set_value + (GTK_SPIN_BUTTON(ctk_gvo_sync->hsync_delay_spin_button), val); - g_signal_connect(G_OBJECT(ctk_gvo_sync->hsync_delay_spin_button), - "value-changed", - G_CALLBACK(hsync_delay_changed), ctk_gvo_sync); + g_signal_connect(G_OBJECT(ctk_gvo_sync->hsync_delay_spin_button), + "value-changed", + G_CALLBACK(hsync_delay_changed), ctk_gvo_sync); - hbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->hsync_delay_spin_button, - FALSE, FALSE, 0); + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(hbox), + ctk_gvo_sync->hsync_delay_spin_button, + FALSE, FALSE, 0); - label = gtk_label_new("(pixels)"); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), label, - FALSE, FALSE, 0); + label = gtk_label_new("(pixels)"); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_box_pack_start(GTK_BOX(hbox), label, + FALSE, FALSE, 0); - gtk_table_attach(GTK_TABLE(table), hbox, - 1, 2, row, row+1, - GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, - TABLE_PADDING, TABLE_PADDING); - row++; + gtk_table_attach(GTK_TABLE(table), hbox, + 1, 2, row, row+1, + GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, + TABLE_PADDING, TABLE_PADDING); + row++; + } /* NV_CTRL_GVO_SYNC_DELAY_LINES */ - if ( ctk_gvo_sync->caps && NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW ) { - label = gtk_label_new("VSync Advance:"); - } else { - label = gtk_label_new("VSync Delay:"); - } - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, - GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); + ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_GVO_SYNC_DELAY_LINES, + &valid); - ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_LINES, &val); - if (ret != NvCtrlSuccess) val = 0; - - if (height < 1) height = 1; + if ((ret == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE)) { + ret = NvCtrlGetAttribute(handle, NV_CTRL_GVO_SYNC_DELAY_LINES, &val); + if (ret != NvCtrlSuccess) val = 0; - if ( ctk_gvo_sync->caps && NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW ) { - height = INT_MAX; - help_text = __vsync_advance_help; - } else { - help_text = __vsync_delay_help; - } + if (ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW) { + label = gtk_label_new("VSync Advance:"); + help_text = __vsync_advance_help; + } else { + label = gtk_label_new("VSync Delay:"); + help_text = __vsync_delay_help; + } - ctk_gvo_sync->vsync_delay_spin_button = - gtk_spin_button_new_with_range(0.0, height, 1); - - ctk_config_set_tooltip(ctk_config, - ctk_gvo_sync->vsync_delay_spin_button, - help_text); - gtk_spin_button_set_value - (GTK_SPIN_BUTTON(ctk_gvo_sync->vsync_delay_spin_button), val); - - g_signal_connect(G_OBJECT(ctk_gvo_sync->vsync_delay_spin_button), - "value-changed", - G_CALLBACK(vsync_delay_changed), ctk_gvo_sync); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, + GTK_FILL, GTK_FILL, TABLE_PADDING, TABLE_PADDING); - hbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(hbox), ctk_gvo_sync->vsync_delay_spin_button, - FALSE, FALSE, 0); + ctk_gvo_sync->vsync_delay_spin_button = + gtk_spin_button_new_with_range(valid.u.range.min, + valid.u.range.max, 1); - label = gtk_label_new("(lines)"); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), label, - FALSE, FALSE, 0); + ctk_config_set_tooltip(ctk_config, + ctk_gvo_sync->vsync_delay_spin_button, + help_text); - gtk_table_attach(GTK_TABLE(table), hbox, - 1, 2, row, row+1, - GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, - TABLE_PADDING, TABLE_PADDING); - row++; + gtk_spin_button_set_value + (GTK_SPIN_BUTTON(ctk_gvo_sync->vsync_delay_spin_button), val); + + g_signal_connect(G_OBJECT(ctk_gvo_sync->vsync_delay_spin_button), + "value-changed", + G_CALLBACK(vsync_delay_changed), ctk_gvo_sync); + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(hbox), + ctk_gvo_sync->vsync_delay_spin_button, + FALSE, FALSE, 0); + + label = gtk_label_new("(lines)"); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_box_pack_start(GTK_BOX(hbox), label, + FALSE, FALSE, 0); + + gtk_table_attach(GTK_TABLE(table), hbox, + 1, 2, row, row+1, + GTK_FILL /*| GTK_EXPAND*/, GTK_FILL, + TABLE_PADDING, TABLE_PADDING); + row++; + } /* create the watch cursor (for use when the "Detect" button is toggled" */ @@ -716,7 +711,7 @@ static GtkWidget *start_menu(const gchar *name, GtkWidget *table, static void finish_menu(GtkWidget *menu, GtkWidget *table, const gint row) { - ctk_drop_down_menu_finalize(CTK_DROP_DOWN_MENU(menu)); + gtk_widget_show_all(menu); gtk_table_attach(GTK_TABLE(table), menu, 1, 2, row, row+1, GTK_FILL | GTK_EXPAND, GTK_FILL, @@ -930,8 +925,14 @@ static void update_gvo_sync_sensitivity(CtkGvoSync *ctk_gvo_sync) sensitive = (sensitive && sync_signal_detected(ctk_gvo_sync)); - gtk_widget_set_sensitive(ctk_gvo_sync->hsync_delay_spin_button, sensitive); - gtk_widget_set_sensitive(ctk_gvo_sync->vsync_delay_spin_button, sensitive); + if (ctk_gvo_sync->hsync_delay_spin_button) { + gtk_widget_set_sensitive(ctk_gvo_sync->hsync_delay_spin_button, + sensitive); + } + if (ctk_gvo_sync->vsync_delay_spin_button) { + gtk_widget_set_sensitive(ctk_gvo_sync->vsync_delay_spin_button, + sensitive); + } } /* update_gvo_sync_sensitivity() */ @@ -1040,32 +1041,6 @@ static void post_sync_format_menu_changed(CtkGvoSync *ctk_gvo_sync) -/* - * update_delay_spin_buttons_range() - Updates the range of the - * delay spin buttons. - */ - -static void update_delay_spin_buttons_range(CtkGvoSync *ctk_gvo_sync) -{ - gint w, h; - - if ( ctk_gvo_sync->caps && NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW ) { - // No need to reset max values - return; - } - - ctk_gvo_get_video_format_resolution(ctk_gvo_sync->input_video_format, - &w, &h); - - gtk_spin_button_set_range - (GTK_SPIN_BUTTON(ctk_gvo_sync->hsync_delay_spin_button), 0, 2*w); - gtk_spin_button_set_range - (GTK_SPIN_BUTTON(ctk_gvo_sync->vsync_delay_spin_button), 0, 2*h); - -} /* update_delay_spin_buttons_range() */ - - - /**** UI Event Handlers ************************************************/ @@ -1359,30 +1334,34 @@ static void gvo_sync_event_received(GtkObject *object, case NV_CTRL_GVO_SYNC_DELAY_PIXELS: widget = ctk_gvo_sync->hsync_delay_spin_button; + + if (widget) { + g_signal_handlers_block_by_func(G_OBJECT(widget), + G_CALLBACK(hsync_delay_changed), + (gpointer) ctk_gvo_sync); - g_signal_handlers_block_by_func(G_OBJECT(widget), - G_CALLBACK(hsync_delay_changed), - (gpointer) ctk_gvo_sync); - - gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), value); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), value); - g_signal_handlers_unblock_by_func(G_OBJECT(widget), - G_CALLBACK(hsync_delay_changed), - (gpointer) ctk_gvo_sync); + g_signal_handlers_unblock_by_func(G_OBJECT(widget), + G_CALLBACK(hsync_delay_changed), + (gpointer) ctk_gvo_sync); + } break; case NV_CTRL_GVO_SYNC_DELAY_LINES: widget = ctk_gvo_sync->vsync_delay_spin_button; - g_signal_handlers_block_by_func(G_OBJECT(widget), - G_CALLBACK(vsync_delay_changed), - (gpointer) ctk_gvo_sync); - - gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), value); + if (widget) { + g_signal_handlers_block_by_func(G_OBJECT(widget), + G_CALLBACK(vsync_delay_changed), + (gpointer) ctk_gvo_sync); - g_signal_handlers_unblock_by_func(G_OBJECT(widget), - G_CALLBACK(vsync_delay_changed), - (gpointer) ctk_gvo_sync); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), value); + + g_signal_handlers_unblock_by_func(G_OBJECT(widget), + G_CALLBACK(vsync_delay_changed), + (gpointer) ctk_gvo_sync); + } break; case NV_CTRL_GVO_COMPOSITE_TERMINATION: @@ -1458,8 +1437,6 @@ static gint gvo_sync_probe_callback(gpointer data) update_sync_lock_status_text(ctk_gvo_sync); - update_delay_spin_buttons_range(ctk_gvo_sync); - update_gvo_sync_sensitivity(ctk_gvo_sync); return TRUE; @@ -1539,7 +1516,7 @@ GtkTextBuffer* ctk_gvo_sync_create_help(GtkTextTagTable *table, ctk_help_heading(b, &i, "Sync Status"); ctk_help_para(b, &i, __sync_status_help); - if ( ctk_gvo_sync->caps && NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW ) { + if ( ctk_gvo_sync->caps & NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW ) { ctk_help_heading(b, &i, "HSync Advance"); ctk_help_para(b, &i, __hsync_advance_help); ctk_help_heading(b, &i, "VSync Advance"); diff --git a/src/gtk+-2.x/ctkgvo.c b/src/gtk+-2.x/ctkgvo.c index 28ad0c1..64910e3 100644 --- a/src/gtk+-2.x/ctkgvo.c +++ b/src/gtk+-2.x/ctkgvo.c @@ -106,13 +106,12 @@ static void finish_menu(GtkWidget *menu, GtkWidget *table, const gint row); static void fill_output_video_format_menu(CtkGvo *ctk_gvo); -static void trim_output_video_format_menu(CtkGvo *ctk_gvo); static void output_video_format_ui_changed(CtkDropDownMenu *menu, gpointer user_data); static void post_output_video_format_changed(CtkGvo *ctk_gvo); -static void validate_output_data_format(CtkGvo *ctk_gvo); +static void fill_output_data_format_menu(CtkGvo *ctk_gvo); static void output_data_format_ui_changed(CtkDropDownMenu *menu, gpointer user_data); static void post_output_data_format_changed(CtkGvo *ctk_gvo); @@ -232,9 +231,39 @@ static GvoFormatDetails videoFormatDetails[] = { static const GvoFormatName dataFormatNames[] = { - { NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB444, "RGB -> YCrCb (4:4:4)" }, - { NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB422, "RGB -> YCrCb (4:2:2)" }, - { NV_CTRL_GVO_DATA_FORMAT_X8X8X8_444_PASSTHRU,"RGB (4:4:4)" }, + + /* Valid for Clone Mode */ + { NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB444, "RGB -> YCrCb (4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB422, "RGB -> YCrCb (4:2:2)" }, + { NV_CTRL_GVO_DATA_FORMAT_X8X8X8_444_PASSTHRU, "RGB (4:4:4)" }, + + /* Invalid for Clone Mode usage */ + { NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_YCRCBA4444, "RGBA -> YCrCbA (4:4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_YCRCBZ4444, "RGBZ -> YCrCbZ (4:4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_YCRCBA4224, "RGBA -> YCrCbA (4:2:2:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_YCRCBZ4224, "RGBZ -> YCrCbZ (4:2:2:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X8X8X8A8_4444_PASSTHRU, "RGBA (4:4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X8X8X8Z8_4444_PASSTHRU, "RGBZ (4:4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X10X10X10_444_PASSTHRU, "RGBA (4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X10X8X8_444_PASSTHRU, "RGB (4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X10X8X8A10_4444_PASSTHRU, "RGBA (4:4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X10X8X8Z10_4444_PASSTHRU, "RGBZ (4:4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_DUAL_R8G8B8_TO_DUAL_YCRCB422, "Dual RGB -> Dual YCrCb (4:2:2)" }, + { NV_CTRL_GVO_DATA_FORMAT_DUAL_X8X8X8_TO_DUAL_422_PASSTHRU, "Dual RGB (4:2:2)" }, + { NV_CTRL_GVO_DATA_FORMAT_R10G10B10_TO_YCRCB422, "RGB -> YCrCb (4:2:2)" }, + { NV_CTRL_GVO_DATA_FORMAT_R10G10B10_TO_YCRCB444, "RGB -> YCrCb (4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X12X12X12_444_PASSTHRU, "RGB (4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_R12G12B12_TO_YCRCB444, "RGB -> YCrCb (4:4:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X8X8X8_422_PASSTHRU, "RGB (4:2:2)" }, + { NV_CTRL_GVO_DATA_FORMAT_X8X8X8A8_4224_PASSTHRU, "RGB (4:2:2:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X8X8X8Z8_4224_PASSTHRU, "RGB (4:2:2:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X10X10X10_422_PASSTHRU, "RGB (4:2:2)" }, + { NV_CTRL_GVO_DATA_FORMAT_X10X8X8_422_PASSTHRU, "RGB (4:2:2)" }, + { NV_CTRL_GVO_DATA_FORMAT_X10X8X8A10_4224_PASSTHRU, "RGBA (4:2:2:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X10X8X8Z10_4224_PASSTHRU, "RGBZ (4:2:2:4)" }, + { NV_CTRL_GVO_DATA_FORMAT_X12X12X12_422_PASSTHRU, "RGB (4:2:2)" }, + { NV_CTRL_GVO_DATA_FORMAT_R12G12B12_TO_YCRCB422, "RGB -> YCrCb (4:2:2)" }, + { -1, NULL }, }; @@ -244,36 +273,6 @@ static const GvoFormatName dataFormatNames[] = { /* - * get_first_available_output_video_format() - returns the first available - * output video format from the dropdown menu. This is needed since when - * Frame Lock/Genlock are enabled, the default case of 487i may not be - * appropriate. - */ - -static gint get_first_available_output_video_format(CtkGvo *ctk_gvo) -{ - CtkDropDownMenu *dmenu = - CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu); - int i; - - /* look through the output video format dropdown for the first - * available selection. - */ - for (i = 0; i < dmenu->num_entries; i++) { - if (GTK_WIDGET_IS_SENSITIVE(dmenu->values[i].menu_item)) { - return dmenu->values[i].value; - } - } - - /* There are no available video formats? Fallback to 487i. */ - - return NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC; - -} /* get_first_available_output_video_format() */ - - - -/* * ctk_gvo_get_video_format_name() - return the name of the given video format */ @@ -294,26 +293,6 @@ const char *ctk_gvo_get_video_format_name(const gint format) /* - * ctk_gvo_get_data_format_name() - return the name of the given data format - */ - -const char *ctk_gvo_get_data_format_name(const gint format) -{ - gint i; - - for (i = 0; dataFormatNames[i].name; i++) { - if (dataFormatNames[i].format == format) { - return dataFormatNames[i].name; - } - } - - return "Unknown"; - -} /* ctk_gvo_get_data_format_name() */ - - - -/* * ctk_gvo_get_video_format_resolution() - return the width and height of the * given video format */ @@ -336,299 +315,179 @@ void ctk_gvo_get_video_format_resolution(const gint format, gint *w, gint *h) /* - * ctk_gvo_get_type() - Returns the CtkGvo "class" type + * ctk_gvo_get_video_format_refresh() - return the refresh rate of the + * given video format */ -GType ctk_gvo_get_type(void) +void ctk_gvo_get_video_format_refresh(const gint format, gint *r) { - static GType ctk_gvo_type = 0; - - if (!ctk_gvo_type) { - static const GTypeInfo ctk_gvo_info = { - sizeof (CtkGvoClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - NULL, /* constructor */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (CtkGvo), - 0, /* n_preallocs */ - NULL, /* instance_init */ - }; + gint i; + + *r = 0; - ctk_gvo_type = - g_type_register_static(GTK_TYPE_VBOX, "CtkGvo", - &ctk_gvo_info, 0); + for (i = 0; videoFormatDetails[i].format != -1; i++) { + if (videoFormatDetails[i].format == format) { + *r = videoFormatDetails[i].rate; + return; + } } - - return ctk_gvo_type; - -} /* ctk_gvo_get_type() */ +} /* ctk_gvo_get_video_format_refresh() */ /* - * trim_output_video_format_menu() - given the current - * OUTPUT_VIDEO_FORMAT and SYNC_MODE, set the sensitivity of each menu - * entry and possibly update which of the output video mode dropdown - * entries is currently selected. + * ctk_gvo_video_format_valid() - returns a bitmask indicating whether or not + * the currently selected video format is valid for clone mode based on the + * current X screen resolution and current sync method. Returns a bitmask + * indicating possible valid/invalid state of the mode. */ -static void trim_output_video_format_menu(CtkGvo *ctk_gvo) -{ - ReturnStatus ret; - NVCTRLAttributeValidValuesRec valid; - gint bitmask, bitmask2, i, refresh_rate; - gboolean sensitive, current_available; +#define GVO_VIDEO_FORMAT_INVALID 0x00000000 +#define GVO_VIDEO_FORMAT_MODE_VALID 0x00000001 +#define GVO_VIDEO_FORMAT_RESOLUTION_VALID 0x00000002 +#define GVO_VIDEO_FORMAT_REFRESH_VALID 0x00000004 - /* retrieve the currently available values */ +#define GVO_VIDEO_FORMAT_VALID \ + (GVO_VIDEO_FORMAT_MODE_VALID | \ + GVO_VIDEO_FORMAT_RESOLUTION_VALID | \ + GVO_VIDEO_FORMAT_REFRESH_VALID) - ret = NvCtrlGetValidAttributeValues(ctk_gvo->handle, - NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, - &valid); +guint ctk_gvo_video_format_valid(CtkGvo *ctk_gvo, const gint format) +{ + gint width, height, refresh_rate, input_refresh_rate; + guint valid = GVO_VIDEO_FORMAT_VALID; - /* if we failed to get the available values; assume none are valid */ - if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_INT_BITS)) { - bitmask = 0; - } else { - bitmask = valid.u.bits.ints; - } - - /* retrieve additional available values */ + /* Keep track of whether we'll need to re-set the video format + * when enabling clone mode. + */ - ret = NvCtrlGetValidAttributeValues(ctk_gvo->handle, - NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2, - &valid); + /* Check to make sure the format size <= current screen size */ + ctk_gvo_get_video_format_resolution(format, &width, &height); - /* if we failed to get the available values; assume none are valid */ - - if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_INT_BITS)) { - bitmask2 = 0; - } else { - bitmask2 = valid.u.bits.ints; + /* Make sure the resolution fits */ + if ((width > ctk_gvo->screen_width) || (height > ctk_gvo->screen_height)) { + valid &= ~(GVO_VIDEO_FORMAT_RESOLUTION_VALID); } - - /* - * if the SyncMode is genlock or framelock, trim the bitmask - * accordingly: if GENLOCK, then the only bit allowed is the bit - * that corresponds to the exact input mode; if FRAMELOCK, then - * only modes with the same refresh rate as the input mode are - * allowed. - */ - if ((ctk_gvo->sync_mode == NV_CTRL_GVO_SYNC_MODE_GENLOCK) && - (ctk_gvo->input_video_format != NV_CTRL_GVO_VIDEO_FORMAT_NONE)) { + /* Check that format is supported */ + if (((format < 32) && + !((1 << format) & ctk_gvo->valid_output_video_format_mask[0])) || + ((format >= 32) && + !((1 << (format -32)) & ctk_gvo->valid_output_video_format_mask[1]))) { + valid &= ~(GVO_VIDEO_FORMAT_MODE_VALID); + } - if (ctk_gvo->input_video_format < 32) { - bitmask &= (1 << ctk_gvo->input_video_format); - bitmask2 = 0; - } else { - bitmask = 0; - bitmask2 &= (1 << (ctk_gvo->input_video_format - 32)); - } + /* Check that formats match if Genlock is enabled */ + else if ((ctk_gvo->sync_mode == NV_CTRL_GVO_SYNC_MODE_GENLOCK) && + (ctk_gvo->input_video_format != NV_CTRL_GVO_VIDEO_FORMAT_NONE) && + (ctk_gvo->input_video_format != format)) { + valid &= ~(GVO_VIDEO_FORMAT_REFRESH_VALID); } - - if ((ctk_gvo->sync_mode == NV_CTRL_GVO_SYNC_MODE_FRAMELOCK) && - (ctk_gvo->input_video_format != NV_CTRL_GVO_VIDEO_FORMAT_NONE)) { - refresh_rate = 0; + + /* Check that format refresh rates match if Frame Lock is enabled */ + else if ((ctk_gvo->sync_mode == NV_CTRL_GVO_SYNC_MODE_FRAMELOCK) && + (ctk_gvo->input_video_format != NV_CTRL_GVO_VIDEO_FORMAT_NONE)) { + + /* Get the refresh rate */ + ctk_gvo_get_video_format_refresh(format, &refresh_rate); /* Get the current input refresh rate */ - for (i = 0; videoFormatDetails[i].format != -1; i++) { - if (videoFormatDetails[i].format == ctk_gvo->input_video_format) { - refresh_rate = videoFormatDetails[i].rate; - break; - } - } + ctk_gvo_get_video_format_refresh(ctk_gvo->input_video_format, + &input_refresh_rate); - /* Mask out refresh rates that don't match */ - for (i = 0; videoFormatDetails[i].format != -1; i++) { - gboolean match = FALSE; - - if (videoFormatDetails[i].rate == refresh_rate) { - match = TRUE; - - } else if (ctk_gvo->caps & - NV_CTRL_GVO_CAPABILITIES_MULTIRATE_SYNC) { - - /* Some GVO devices support multi-rate synchronization. - * For these devices, we just need to check that the - * fractional part of the rate are either both zero or - * both non-zero. - */ - if (((videoFormatDetails[i].rate % 1000) ? TRUE : FALSE) == - ((refresh_rate % 1000) ? TRUE : FALSE)) { - match = TRUE; - } - } else { - match = FALSE; - } + /* Check that the refresh rates are the same, or, for those + * GVO devices that support multi-rate synchronization, check + * that the fractional part of the rates are either both zero + * or both non-zero. + */ - if (!match) { - if (videoFormatDetails[i].format < 32) { - bitmask &= ~(1 << videoFormatDetails[i].format); - } else { - bitmask2 &= ~(1 << (videoFormatDetails[i].format - 32)); - } - } + if ((refresh_rate != input_refresh_rate) && + (!(ctk_gvo->caps & NV_CTRL_GVO_CAPABILITIES_MULTIRATE_SYNC) || + (((refresh_rate % 1000) ? TRUE : FALSE) != + ((input_refresh_rate % 1000) ? TRUE : FALSE)))) { + valid &= ~(GVO_VIDEO_FORMAT_REFRESH_VALID); } } - /* - * loop over each video format; if that format is set in the - * bitmask, then it is available - */ + return valid; - current_available = FALSE; - for (i = 0; videoFormatNames[i].name; i++) { - if (((videoFormatNames[i].format < 32) && - ((1 << videoFormatNames[i].format) & bitmask)) || - ((videoFormatNames[i].format >= 32) && - (((1 << (videoFormatNames[i].format - 32)) & bitmask2)))) { - sensitive = TRUE; - } else { - sensitive = FALSE; - } +} /* ctk_gvo_video_format_valid() */ - ctk_drop_down_menu_set_value_sensitive - (CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu), - videoFormatNames[i].format, sensitive); - /* if the current video is not sensitive, take note */ - - if ((ctk_gvo->output_video_format == videoFormatNames[i].format) && - sensitive) { - current_available = TRUE; - } - } - - /* - * if the current video is not available, then make the first - * available format current - */ - - if (!current_available && bitmask) { - - for (i = 0; videoFormatNames[i].name; i++) { - if (((videoFormatNames[i].format < 32) && - ((1 << videoFormatNames[i].format) & bitmask)) || - ((videoFormatNames[i].format >= 32) && - ((1 << (videoFormatNames[i].format - 32)) & bitmask2))) { - - /* Invalidate the format so it gets set when clone mode is - * enabled. - */ - ctk_gvo->output_video_format_valid = FALSE; - - g_signal_handlers_block_by_func - (G_OBJECT(ctk_gvo->output_video_format_menu), - G_CALLBACK(output_video_format_ui_changed), - (gpointer) ctk_gvo); - ctk_drop_down_menu_set_current_value - (CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu), - videoFormatNames[i].format); +/* + * ctk_gvo_get_data_format_name() - return the name of the given data format + */ - g_signal_handlers_unblock_by_func - (G_OBJECT(ctk_gvo->output_video_format_menu), - G_CALLBACK(output_video_format_ui_changed), - (gpointer) ctk_gvo); - break; - } +const char *ctk_gvo_get_data_format_name(const gint format) +{ + gint i; + + for (i = 0; dataFormatNames[i].name; i++) { + if (dataFormatNames[i].format == format) { + return dataFormatNames[i].name; } } - /* - * cache the bitmask - */ + return "Unknown"; - ctk_gvo->valid_output_video_format_mask[0] = bitmask; - ctk_gvo->valid_output_video_format_mask[1] = bitmask2; - -} /* trim_output_video_format_menu() */ +} /* ctk_gvo_get_data_format_name() */ /* - * validate_output_video_format() - Keep tabs on the output - * video format. If some other client sets the output video format to - * something clone mode can't do, we'll just need to make sure that - * we re-set the output video format when the user selects to enable - * clone mode. - * - * NOTE: The gtk signal handler for the video format menu should not - * be enabled while calling this function. + * ctk_gvo_data_format_valid() - return whether or not the given data + * format is valid for clone mode. */ -static void validate_output_video_format(CtkGvo *ctk_gvo) +gboolean ctk_gvo_data_format_valid(const gint format) { - gint bitmask, bitmask2; - gint width, height; - gint format = ctk_gvo->output_video_format; - - /* Keep track of whether we'll need to re-set the video format - * when enabling clone mode. - */ - - /* Check to make sure the format size <= current screen size */ - ctk_gvo_get_video_format_resolution(format, &width, &height); - - /* Don't expose modes bigger than the current X Screen size */ - if ((width > ctk_gvo->screen_width) || - (height > ctk_gvo->screen_height)) { - /* Format is invalid due to screen size limitations */ - ctk_gvo->output_video_format_valid = FALSE; - return; - } - - /* Check to make sure genlock/framelock requirements are ment */ - bitmask = ctk_gvo->valid_output_video_format_mask[0]; - bitmask2 = ctk_gvo->valid_output_video_format_mask[1]; - - if (((format < 32) && !((1 << format) & bitmask)) || - ((format >= 32) && !((1 << (format - 32)) & bitmask2))) { - /* Format is invalid due to genlock/framelock requirements */ - ctk_gvo->output_video_format_valid = FALSE; - return; + gint i; + + for (i = 0; dataFormatNames[i].name; i++) { + if (dataFormatNames[i].format == format) { + /* Only the first three formats are valid */ + return (i < 3) ? TRUE : FALSE; + } } - /* If we got this far, then the format is valid. */ - ctk_gvo->output_video_format_valid = TRUE; + return FALSE; -} /* validate_output_video_format() */ +} /* ctk_gvo_data_format_valid() */ /* - * validate_output_data_format() - Keep tabs on the output - * data format. If some other client sets the output data format to - * something clone mode can't do, we'll just need to make sure that - * we re-set the output data format when the user selects to enable - * clone mode. - * - * NOTE: The gtk signal handler for the data format menu should not - * be enabled while calling this function. + * ctk_gvo_get_type() - Returns the CtkGvo "class" type */ -static void validate_output_data_format(CtkGvo *ctk_gvo) +GType ctk_gvo_get_type(void) { - int i; - - /* Keep track of whether we'll need to re-set the data format - * when enabling clone mode. - */ - for (i = 0; dataFormatNames[i].name; i++) { - if (ctk_gvo->output_data_format == dataFormatNames[i].format) { - /* Value is OK */ - ctk_gvo->output_data_format_valid = TRUE; - return; - } - } + static GType ctk_gvo_type = 0; - ctk_gvo->output_data_format_valid = FALSE; + if (!ctk_gvo_type) { + static const GTypeInfo ctk_gvo_info = { + sizeof (CtkGvoClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, /* constructor */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (CtkGvo), + 0, /* n_preallocs */ + NULL, /* instance_init */ + }; -} /* validate_output_data_format() */ + ctk_gvo_type = + g_type_register_static(GTK_TYPE_VBOX, "CtkGvo", + &ctk_gvo_info, 0); + } + + return ctk_gvo_type; + +} /* ctk_gvo_get_type() */ @@ -647,7 +506,7 @@ GtkWidget* ctk_gvo_new(NvCtrlAttributeHandle *handle, GtkWidget *hbox, *vbox, *alignment, *label; ReturnStatus ret; gchar scratch[64], *firmware, *string; - gint val, i, width, height; + gint val, width, height; GtkWidget *frame, *table, *menu; @@ -776,18 +635,10 @@ GtkWidget* ctk_gvo_new(NvCtrlAttributeHandle *handle, fill_output_video_format_menu(ctk_gvo); finish_menu(menu, table, 0); - - /* Make sure that the video format selected is valid for clone mode */ - - validate_output_video_format(ctk_gvo); - if (ctk_gvo->output_video_format_valid) { - val = ctk_gvo->output_video_format; - } else { - val = get_first_available_output_video_format(ctk_gvo); - } ctk_drop_down_menu_set_current_value - (CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu), val); + (CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu), + ctk_gvo->output_video_format); g_signal_connect(G_OBJECT(ctk_gvo->output_video_format_menu), "changed", G_CALLBACK(output_video_format_ui_changed), @@ -799,26 +650,14 @@ GtkWidget* ctk_gvo_new(NvCtrlAttributeHandle *handle, ctk_gvo->output_data_format_menu = menu; ctk_config_set_tooltip(ctk_config, CTK_DROP_DOWN_MENU(menu)->option_menu, __clone_mode_data_format_help); - - for (i = 0; dataFormatNames[i].name; i++) { - ctk_drop_down_menu_append_item(CTK_DROP_DOWN_MENU(menu), - dataFormatNames[i].name, - dataFormatNames[i].format); - } + + fill_output_data_format_menu(ctk_gvo); finish_menu(menu, table, 1); - /* Make sure that the data format selected is valid for clone mode */ - - validate_output_data_format(ctk_gvo); - if (ctk_gvo->output_data_format_valid) { - val = ctk_gvo->output_data_format; - } else { - val = DEFAULT_OUTPUT_DATA_FORMAT; - } - ctk_drop_down_menu_set_current_value - (CTK_DROP_DOWN_MENU(ctk_gvo->output_data_format_menu), val); + (CTK_DROP_DOWN_MENU(ctk_gvo->output_data_format_menu), + ctk_gvo->output_data_format); g_signal_connect(G_OBJECT(ctk_gvo->output_data_format_menu), "changed", G_CALLBACK(output_data_format_ui_changed), @@ -1075,7 +914,7 @@ static GtkWidget *start_menu(const gchar *name, GtkWidget *table, static void finish_menu(GtkWidget *menu, GtkWidget *table, const gint row) { - ctk_drop_down_menu_finalize(CTK_DROP_DOWN_MENU(menu)); + gtk_widget_show_all(menu); gtk_table_attach(GTK_TABLE(table), menu, 1, 2, row, row+1, GTK_FILL | GTK_EXPAND, GTK_FILL, @@ -1092,10 +931,17 @@ static void finish_menu(GtkWidget *menu, GtkWidget *table, const gint row) static void fill_output_video_format_menu(CtkGvo *ctk_gvo) { int i; - int width, height; CtkDropDownMenu *dmenu = CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu); + GtkWidget *label; + guint valid; + gint num_valid_entries = 0; + gchar *str; + gchar *tmp; + + ctk_drop_down_menu_reset(CTK_DROP_DOWN_MENU(dmenu)); + for (i = 0; videoFormatNames[i].name; i++) { /* @@ -1108,44 +954,187 @@ static void fill_output_video_format_menu(CtkGvo *ctk_gvo) return; } - /* check that the current X screen can support the width and height */ - - width = videoFormatDetails[i].width; - height = videoFormatDetails[i].height; + valid = ctk_gvo_video_format_valid(ctk_gvo, + videoFormatNames[i].format); - /* Don't expose modes bigger than the current X Screen size */ - if ((width > ctk_gvo->screen_width) || - (height > ctk_gvo->screen_height)) { + /* Mode must be supported */ + if (!(valid & GVO_VIDEO_FORMAT_MODE_VALID)) { continue; } - ctk_drop_down_menu_append_item(dmenu, - videoFormatNames[i].name, - videoFormatNames[i].format); + /* Resolution must fit (or this is the selected mode) */ + if (!(valid & GVO_VIDEO_FORMAT_RESOLUTION_VALID) && + (ctk_gvo->output_video_format != videoFormatNames[i].format)) { + continue; + } + + if (valid == GVO_VIDEO_FORMAT_VALID) { + str = (gchar *)videoFormatNames[i].name; + } else { + str = g_strconcat(videoFormatNames[i].name, " -", NULL); + + if (!(valid & GVO_VIDEO_FORMAT_RESOLUTION_VALID)) { + tmp = g_strconcat(str, " Resolution mismatch", NULL); + g_free(str); + str = tmp; + } + if (!(valid & GVO_VIDEO_FORMAT_REFRESH_VALID)) { + if (!(valid & GVO_VIDEO_FORMAT_RESOLUTION_VALID)) { + tmp = g_strconcat(str, ",", NULL); + g_free(str); + str = tmp; + } + tmp = g_strconcat(str, " Refresh mismatch", NULL); + g_free(str); + str = tmp; + } + } + + label = ctk_drop_down_menu_append_item(dmenu, str, + videoFormatNames[i].format); + if (str != videoFormatNames[i].name) { + g_free(str); + } + + /* Gray out entry if it is not valid */ + gtk_widget_set_sensitive(label, (valid == GVO_VIDEO_FORMAT_VALID)); + + if (valid == GVO_VIDEO_FORMAT_VALID) { + num_valid_entries++; + } } - ctk_gvo->has_output_video_formats = - ((dmenu->num_entries > 0) ? TRUE : FALSE); - - if (!ctk_gvo->has_output_video_formats) { - nv_warning_msg("No GVO video formats will fit the current X screen of " - "%d x %d; please create an X screen of atleast " - "720 x 487; not exposing GVO page.\n", + /* Show special menu if there are no valid entries */ + if (num_valid_entries <= 0) { + nv_warning_msg("There are currently no GVO video formats valid for " + "use with Clone Mode. Please make sure that the X " + "screen resolution (currently %d x %d) is at least " + "720 x 487.\n", ctk_gvo->screen_width, ctk_gvo->screen_height); - ctk_drop_down_menu_append_item - (dmenu, - "*** X Screen is smaller than 720x487 ***", - 0); + ctk_drop_down_menu_reset(CTK_DROP_DOWN_MENU(dmenu)); + label = ctk_drop_down_menu_append_item(dmenu, + "*** X screen is smaller than " + "720x487 ***", + ctk_gvo->output_video_format); + gtk_widget_set_sensitive(label, FALSE); } - /* Trim output video format based on sync mode */ - trim_output_video_format_menu(ctk_gvo); - } /* fill_output_video_format_menu() */ +/* + * rebuild_output_video_format_menu() - Reconsutrcts the output data format + * menu. + */ + +static void rebuild_output_video_format_menu(CtkGvo *ctk_gvo) +{ + CtkDropDownMenu *dmenu = + CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu); + + g_signal_handlers_block_by_func + (G_OBJECT(dmenu), + G_CALLBACK(output_video_format_ui_changed), + (gpointer) ctk_gvo); + + fill_output_video_format_menu(ctk_gvo); + + ctk_drop_down_menu_set_current_value + (CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu), + ctk_gvo->output_video_format); + + gtk_widget_show_all(GTK_WIDGET(dmenu)); + + g_signal_handlers_unblock_by_func + (G_OBJECT(dmenu), + G_CALLBACK(output_video_format_ui_changed), + (gpointer) ctk_gvo); + + update_gvo_sensitivity(ctk_gvo); + +} /* rebuild_output_video_format_menu() */ + + + +/* + * fill_output_data_format_menu() - Populates the output data format menu. + */ + +static void fill_output_data_format_menu(CtkGvo *ctk_gvo) +{ + int i; + CtkDropDownMenu *dmenu = + CTK_DROP_DOWN_MENU(ctk_gvo->output_data_format_menu); + GtkWidget *label; + gboolean valid; + gchar *str; + + ctk_drop_down_menu_reset(CTK_DROP_DOWN_MENU(dmenu)); + + for (i = 0; dataFormatNames[i].name; i++) { + valid = ctk_gvo_data_format_valid(dataFormatNames[i].format); + if (!valid && + (ctk_gvo->output_data_format != dataFormatNames[i].format)) { + continue; + } + + if (valid) { + str = (gchar *)dataFormatNames[i].name; + } else { + str = g_strconcat(dataFormatNames[i].name, + " - Invalid for Clone Mode", NULL); + } + + label = ctk_drop_down_menu_append_item(dmenu, str, + dataFormatNames[i].format); + if (str != dataFormatNames[i].name) { + g_free(str); + } + + gtk_widget_set_sensitive(label, (valid ? TRUE : FALSE)); + } + +} /* fill_output_data_format_menu() */ + + + +/* + * rebuild_output_data_format_menu() - Reconsutrcts the output data format + * menu. + */ + +static void rebuild_output_data_format_menu(CtkGvo *ctk_gvo) +{ + CtkDropDownMenu *dmenu = + CTK_DROP_DOWN_MENU(ctk_gvo->output_data_format_menu); + + g_signal_handlers_block_by_func + (G_OBJECT(dmenu), + G_CALLBACK(output_data_format_ui_changed), + (gpointer) ctk_gvo); + + fill_output_data_format_menu(ctk_gvo); + + ctk_drop_down_menu_set_current_value + (CTK_DROP_DOWN_MENU(ctk_gvo->output_data_format_menu), + ctk_gvo->output_data_format); + + gtk_widget_show_all(GTK_WIDGET(dmenu)); + + g_signal_handlers_unblock_by_func + (G_OBJECT(dmenu), + G_CALLBACK(output_data_format_ui_changed), + (gpointer) ctk_gvo); + + update_gvo_sensitivity(ctk_gvo); + +} /* rebuild_output_data_format_menu() */ + + + + /**** Initialization Functions ***********************************************/ /* @@ -1157,6 +1146,7 @@ static gboolean query_init_gvo_state(CtkGvo *ctk_gvo) { gint val; ReturnStatus ret; + NVCTRLAttributeValidValuesRec valid; /* Check if this screen supports GVO */ @@ -1202,6 +1192,27 @@ static gboolean query_init_gvo_state(CtkGvo *ctk_gvo) val = DEFAULT_OUTPUT_VIDEO_FORMAT; } ctk_gvo->output_video_format = val; + + /* Valid output video formats */ + + ret = NvCtrlGetValidAttributeValues(ctk_gvo->handle, + NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, + &valid); + if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_INT_BITS)) { + ctk_gvo->valid_output_video_format_mask[0] = 0; + } else { + ctk_gvo->valid_output_video_format_mask[0] = valid.u.bits.ints; + } + + ret = NvCtrlGetValidAttributeValues(ctk_gvo->handle, + NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2, + &valid); + + if ((ret != NvCtrlSuccess) || (valid.type != ATTRIBUTE_TYPE_INT_BITS)) { + ctk_gvo->valid_output_video_format_mask[1] = 0; + } else { + ctk_gvo->valid_output_video_format_mask[1] = valid.u.bits.ints; + } /* Output data format */ @@ -1323,14 +1334,31 @@ static void output_video_format_ui_changed(CtkDropDownMenu *menu, gpointer user_data) { CtkGvo *ctk_gvo = CTK_GVO(user_data); + guint was_valid; + + was_valid = ctk_gvo_video_format_valid(ctk_gvo, + ctk_gvo->output_video_format); ctk_gvo->output_video_format = ctk_drop_down_menu_get_current_value(menu); - ctk_gvo->output_video_format_valid = TRUE; + + if (ctk_gvo_video_format_valid(ctk_gvo, ctk_gvo->output_video_format) != + GVO_VIDEO_FORMAT_VALID) { + /* Video format is invalid, don't set it */ + update_gvo_sensitivity(ctk_gvo); + return; + } NvCtrlSetAttribute(ctk_gvo->handle, NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, ctk_gvo->output_video_format); + /* Rebuild menu to remove previously invalid entry */ + if (was_valid != GVO_VIDEO_FORMAT_VALID) { + rebuild_output_video_format_menu(ctk_gvo); + } + + update_gvo_sensitivity(ctk_gvo); + post_output_video_format_changed(ctk_gvo); } /* output_video_format_ui_changed() */ @@ -1346,13 +1374,29 @@ static void output_data_format_ui_changed(CtkDropDownMenu *menu, gpointer user_data) { CtkGvo *ctk_gvo = CTK_GVO(user_data); - + gboolean was_valid; + + + was_valid = ctk_gvo_data_format_valid(ctk_gvo->output_data_format); + ctk_gvo->output_data_format = ctk_drop_down_menu_get_current_value(menu); - ctk_gvo->output_data_format_valid = TRUE; + + if (!ctk_gvo_data_format_valid(ctk_gvo->output_data_format)) { + /* Data format is invalid, don't set it */ + update_gvo_sensitivity(ctk_gvo); + return; + } NvCtrlSetAttribute(ctk_gvo->handle, NV_CTRL_GVO_DATA_FORMAT, ctk_gvo->output_data_format); - + + /* Rebuild menu to remove previously invalid entry */ + if (!was_valid) { + rebuild_output_data_format_menu(ctk_gvo); + } + + update_gvo_sensitivity(ctk_gvo); + post_output_data_format_changed(ctk_gvo); } /* output_data_format_ui_changed() */ @@ -1408,39 +1452,11 @@ static void clone_mode_button_ui_toggled(GtkWidget *button, gpointer user_data) gint val; enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); - - - /* - * When enabling clone mode, we must make sure that the output - * video format and output data format are something clone mode - * can support. - */ - - if (enabled) { - if (!ctk_gvo->output_video_format_valid) { - val = ctk_drop_down_menu_get_current_value - (CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu)); - ctk_gvo->output_video_format = val; - ctk_gvo->output_video_format_valid = TRUE; - NvCtrlSetAttribute(ctk_gvo->handle, - NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT, - ctk_gvo->output_video_format); - } - if (!ctk_gvo->output_data_format_valid) { - val = ctk_drop_down_menu_get_current_value - (CTK_DROP_DOWN_MENU(ctk_gvo->output_data_format_menu)); - ctk_gvo->output_data_format = val; - ctk_gvo->output_data_format_valid = TRUE; - NvCtrlSetAttribute(ctk_gvo->handle, - NV_CTRL_GVO_DATA_FORMAT, - val); - } - } if (enabled) val = NV_CTRL_GVO_DISPLAY_X_SCREEN_ENABLE; else val = NV_CTRL_GVO_DISPLAY_X_SCREEN_DISABLE; NvCtrlSetAttribute(ctk_gvo->handle, NV_CTRL_GVO_DISPLAY_X_SCREEN, val); - + /* * XXX NV_CTRL_GVO_DISPLAY_X_SCREEN can silently fail if GLX * locked GVO output for use by pbuffer(s). Check that the @@ -1662,6 +1678,8 @@ static void update_offset_spin_button_ranges(CtkGvo *ctk_gvo) static void update_gvo_sensitivity(CtkGvo *ctk_gvo) { gboolean sensitive; + guint video_format_valid; + gboolean data_format_valid; sensitive = ((ctk_gvo->lock_owner == NV_CTRL_GVO_LOCK_OWNER_NONE) || (ctk_gvo->lock_owner == NV_CTRL_GVO_LOCK_OWNER_CLONE)); @@ -1673,17 +1691,23 @@ static void update_gvo_sensitivity(CtkGvo *ctk_gvo) /* Video & data formats */ sensitive = (ctk_gvo->lock_owner == NV_CTRL_GVO_LOCK_OWNER_NONE); + gtk_widget_set_sensitive(ctk_gvo->output_video_format_menu, sensitive); gtk_widget_set_sensitive(ctk_gvo->output_data_format_menu, sensitive); - sensitive = (sensitive && ctk_gvo->has_output_video_formats); - gtk_widget_set_sensitive(ctk_gvo->output_video_format_menu, sensitive); - /* Enable/Disable clone mode button */ + video_format_valid = + ctk_gvo_video_format_valid(ctk_gvo, ctk_gvo->output_video_format); + + data_format_valid = + ctk_gvo_data_format_valid(ctk_gvo->output_data_format); + sensitive = + (ctk_gvo->lock_owner == NV_CTRL_GVO_LOCK_OWNER_CLONE) || ((ctk_gvo->lock_owner == NV_CTRL_GVO_LOCK_OWNER_NONE) && - ctk_gvo->has_output_video_formats) || - (ctk_gvo->lock_owner == NV_CTRL_GVO_LOCK_OWNER_CLONE); + (video_format_valid == GVO_VIDEO_FORMAT_VALID) && + data_format_valid); + gtk_widget_set_sensitive(ctk_gvo->toggle_clone_mode_button, sensitive); } @@ -1694,7 +1718,7 @@ static void update_gvo_sensitivity(CtkGvo *ctk_gvo) /**** Event Handlers *********************************************************/ /* - * gvo_event_received(() - Handles GVO NV-CONTROL events. + * gvo_event_received() - Handles GVO NV-CONTROL events. */ static void gvo_event_received(GtkObject *object, @@ -1714,53 +1738,21 @@ static void gvo_event_received(GtkObject *object, case NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT: widget = ctk_gvo->output_video_format_menu; - g_signal_handlers_block_by_func - (G_OBJECT(widget), - G_CALLBACK(output_video_format_ui_changed), - (gpointer) ctk_gvo); - ctk_gvo->output_video_format = value; - validate_output_video_format(ctk_gvo); - - /* Update the dropdown with a reasonable value */ - if (!ctk_gvo->output_video_format_valid) { - value = get_first_available_output_video_format(ctk_gvo); - } - ctk_drop_down_menu_set_current_value - (CTK_DROP_DOWN_MENU(widget), value); - post_output_video_format_changed(ctk_gvo); + rebuild_output_video_format_menu(ctk_gvo); - g_signal_handlers_unblock_by_func - (G_OBJECT(widget), - G_CALLBACK(output_video_format_ui_changed), - (gpointer) ctk_gvo); + post_output_video_format_changed(ctk_gvo); break; case NV_CTRL_GVO_DATA_FORMAT: widget = ctk_gvo->output_data_format_menu; - - g_signal_handlers_block_by_func - (G_OBJECT(widget), - G_CALLBACK(output_data_format_ui_changed), - (gpointer) ctk_gvo); ctk_gvo->output_data_format = value; - validate_output_data_format(ctk_gvo); - - /* Update the dropdown with a reasonable value */ - if (!ctk_gvo->output_data_format_valid) { - value = DEFAULT_OUTPUT_DATA_FORMAT; - } - ctk_drop_down_menu_set_current_value - (CTK_DROP_DOWN_MENU(widget), value); - post_output_data_format_changed(ctk_gvo); + rebuild_output_data_format_menu(ctk_gvo); - g_signal_handlers_unblock_by_func - (G_OBJECT(widget), - G_CALLBACK(output_data_format_ui_changed), - (gpointer) ctk_gvo); + post_output_data_format_changed(ctk_gvo); break; case NV_CTRL_GVO_X_SCREEN_PAN_X: @@ -1825,59 +1817,17 @@ static void screen_changed_handler(GtkWidget *widget, gpointer data) { CtkGvo *ctk_gvo = CTK_GVO(data); - CtkDropDownMenu *dmenu; - gint val; /* Cache the new screen dimensions */ ctk_gvo->screen_width = ev->width; ctk_gvo->screen_height = ev->height; - /* Update the output video format drop down menu and reset the list */ - - dmenu = CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu); - - /* Get the currently selected value */ - - val = ctk_drop_down_menu_get_current_value - (CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu)); - - /* Reset the drop down menu */ - - ctk_drop_down_menu_reset(dmenu); - - /* Fill the menu with the new valid video modes */ - - fill_output_video_format_menu(ctk_gvo); - - /* Finalize and load the menu */ - - g_signal_handlers_block_by_func - (G_OBJECT(ctk_gvo->output_video_format_menu), - G_CALLBACK(output_video_format_ui_changed), - (gpointer) ctk_gvo); - - ctk_drop_down_menu_finalize(dmenu); - - /* Set best valid output video format value possible. - * Revalidate here since the screen change could cause - * the current output video mode to now be valid. - */ - - validate_output_video_format(ctk_gvo); - if (ctk_gvo->output_video_format_valid) { - val = ctk_gvo->output_video_format; - } - - ctk_drop_down_menu_set_current_value - (CTK_DROP_DOWN_MENU(ctk_gvo->output_video_format_menu), val); + /* Update UI */ - g_signal_handlers_unblock_by_func - (G_OBJECT(ctk_gvo->output_video_format_menu), - G_CALLBACK(output_video_format_ui_changed), - (gpointer) ctk_gvo); + rebuild_output_video_format_menu(ctk_gvo); - /* Update UI */ + rebuild_output_data_format_menu(ctk_gvo); update_gvo_current_info(ctk_gvo); @@ -1925,7 +1875,7 @@ gint ctk_gvo_probe_callback(gpointer data) /* update the available output video formats */ - trim_output_video_format_menu(ctk_gvo); + rebuild_output_video_format_menu(ctk_gvo); } return TRUE; @@ -2009,7 +1959,12 @@ GtkTextBuffer* ctk_gvo_create_help(GtkTextTagTable *table) "Free-Running (see Synchronization Options page for more " "information).", __clone_mode_video_format_help); ctk_help_heading(b, &i, "Data Format"); - ctk_help_para(b, &i, __clone_mode_data_format_help); + ctk_help_para(b, &i, "%s Note that other NV-CONTROL clients are still " + "able to select a data format that is not supported with " + "clone mode. In this case, the current data format will " + "be shown as \"Invalid for Clone Mode\" and you will need " + "to select a valid data format in order to enable Clone " + "Mode.", __clone_mode_data_format_help); ctk_help_heading(b, &i, "X Offset"); ctk_help_para(b, &i, __clone_mode_x_offset_help); ctk_help_heading(b, &i, "Y Offset"); diff --git a/src/gtk+-2.x/ctkgvo.h b/src/gtk+-2.x/ctkgvo.h index d2201d7..ac3727f 100644 --- a/src/gtk+-2.x/ctkgvo.h +++ b/src/gtk+-2.x/ctkgvo.h @@ -75,25 +75,9 @@ struct _CtkGvo gint input_video_format; gint output_video_format; - gint valid_output_video_format_mask[2]; - gboolean has_output_video_formats; // XXX Show show non-valid as gray? - gboolean output_video_format_valid; /* If the output video format was - changed by another client to - something clone mode doesn't - support, we should ignore it, - but we should make sure that we - set the output_video_format when - we enable clone mode. */ - - + guint valid_output_video_format_mask[2]; + gint output_data_format; - gboolean output_data_format_valid; /* If the output data format was - changed by another client to - something clone mode doesn't - support, we should ignore it, - but we should make sure that we - set the output_data_format when - we enable clone mode. */ gint screen_width; gint screen_height; diff --git a/src/gtk+-2.x/ctkmultisample.c b/src/gtk+-2.x/ctkmultisample.c index db90775..9bb4b16 100644 --- a/src/gtk+-2.x/ctkmultisample.c +++ b/src/gtk+-2.x/ctkmultisample.c @@ -203,6 +203,8 @@ GtkWidget *ctk_multisample_new(NvCtrlAttributeHandle *handle, GtkWidget *check_button; GtkWidget *menu; GtkWidget *scale; + GtkObject *adjustment; + gint min, max; gint val, app_control, override, enhance, i; @@ -305,6 +307,8 @@ GtkWidget *ctk_multisample_new(NvCtrlAttributeHandle *handle, gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0); + + ctk_multisample->fsaa_app_override_check_button = check_button; } g_signal_connect(G_OBJECT(ctk_event), @@ -315,9 +319,13 @@ GtkWidget *ctk_multisample_new(NvCtrlAttributeHandle *handle, /* Antialiasing scale */ - scale = gtk_hscale_new_with_range - (0, ctk_multisample->fsaa_translation_table_size - 1, 1); - gtk_range_set_value(GTK_RANGE(scale), val); + min = 0; + max = ctk_multisample->fsaa_translation_table_size - 1; + + /* create the slider */ + adjustment = gtk_adjustment_new(val, min, max, 1, 1, 0.0); + scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment)); + gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustment), val); gtk_scale_set_draw_value(GTK_SCALE(scale), TRUE); gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP); @@ -414,9 +422,13 @@ GtkWidget *ctk_multisample_new(NvCtrlAttributeHandle *handle, /* Aniso scale */ - scale = gtk_hscale_new_with_range(valid.u.range.min, - valid.u.range.max, 1); - gtk_range_set_value(GTK_RANGE(scale), val); + min = valid.u.range.min; + max = valid.u.range.max; + + /* create the slider */ + adjustment = gtk_adjustment_new(val, min, max, 1, 1, 0.0); + scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment)); + gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustment), val); gtk_scale_set_draw_value(GTK_SCALE(scale), TRUE); gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP); diff --git a/src/gtk+-2.x/ctkopengl.c b/src/gtk+-2.x/ctkopengl.c index b130f3b..8ea1a68 100644 --- a/src/gtk+-2.x/ctkopengl.c +++ b/src/gtk+-2.x/ctkopengl.c @@ -28,6 +28,7 @@ #include "ctkbanner.h" #include "ctkopengl.h" +#include "ctkscale.h" #include "ctkconfig.h" #include "ctkhelp.h" @@ -44,6 +45,8 @@ static void post_show_sli_hud_button_toggled(CtkOpenGL *, gboolean); static void post_xinerama_stereo_button_toggled(CtkOpenGL *, gboolean); +static void post_stereo_eyes_exchange_button_toggled(CtkOpenGL *, gboolean); + static void post_aa_line_gamma_toggled(CtkOpenGL *, gboolean); static void allow_flipping_button_toggled(GtkWidget *, gpointer); @@ -52,6 +55,8 @@ static void force_stereo_button_toggled (GtkWidget *, gpointer); static void xinerama_stereo_button_toggled (GtkWidget *, gpointer); +static void stereo_eyes_exchange_button_toggled (GtkWidget *, gpointer); + static void aa_line_gamma_toggled (GtkWidget *, gpointer); static void show_sli_hud_button_toggled (GtkWidget *, gpointer); @@ -63,6 +68,11 @@ static const gchar *get_image_settings_string(gint val); static gchar *format_image_settings_value(GtkScale *scale, gdouble arg1, gpointer user_data); +static void post_slider_value_changed(CtkOpenGL *ctk_opengl, gint val); + +static void aa_line_gamma_update_received(GtkObject *object, + gpointer arg1, gpointer user_data); + static void post_image_settings_value_changed(CtkOpenGL *ctk_opengl, gint val); static void image_settings_value_changed(GtkRange *range, gpointer user_data); @@ -70,6 +80,15 @@ static void image_settings_value_changed(GtkRange *range, gpointer user_data); static void image_settings_update_received(GtkObject *object, gpointer arg1, gpointer user_data); +static GtkWidget *create_slider(CtkOpenGL *ctk_opengl, + GtkWidget *vbox, + const gchar *name, + const char *help, + gint attribute, + unsigned int bit); + +static void slider_changed(GtkAdjustment *adjustment, gpointer user_data); + #define FRAME_PADDING 5 static const char *__sync_to_vblank_help = @@ -78,6 +97,17 @@ static const char *__sync_to_vblank_help = "applied to OpenGL applications that are started after " "this option is set."; +static const char *__aa_line_gamma_checkbox_help = +"Enable the antialiased lines gamma correction checkbox to make the " +"gamma correction slider active."; + +static const char *__aa_line_gamma_slider_help = +"This option allows Gamma-corrected " +"antialiased lines to consider variances in the color " +"display capabilities of output devices when rendering " +"smooth lines. This option is applied to OpenGL applications " +"that are started after this option is set."; + static const char *__image_settings_slider_help = "The Image Settings slider controls the image quality setting."; @@ -90,7 +120,7 @@ static const char *__force_stereo_help = static const char *__xinerama_stereo_help = "Enabling this option causes OpenGL to allow " "stereo flipping on multiple X screens configured " -"with Xinerama. This option is applied immediately."; +"with Xinerama. This option is applied immediately."; static const char *__show_sli_hud_help = "Enabling this option causes OpenGL to draw " @@ -99,14 +129,21 @@ static const char *__show_sli_hud_help = "applications that are started after this option is " "set."; -#define __SYNC_TO_VBLANK (1 << 1) -#define __ALLOW_FLIPPING (1 << 2) -#define __AA_LINE_GAMMA (1 << 3) -#define __FORCE_GENERIC_CPU (1 << 4) -#define __FORCE_STEREO (1 << 5) -#define __IMAGE_SETTINGS (1 << 6) -#define __XINERAMA_STEREO (1 << 7) -#define __SHOW_SLI_HUD (1 << 8) +static const char *__stereo_eyes_exchange_help = +"Enabling this option causes OpenGL to draw the left " +"eye image in the right eye and vice versa for stereo " +"drawables. This option is applied immediately."; + +#define __SYNC_TO_VBLANK (1 << 1) +#define __ALLOW_FLIPPING (1 << 2) +#define __AA_LINE_GAMMA_VALUE (1 << 3) +#define __AA_LINE_GAMMA (1 << 4) +#define __FORCE_GENERIC_CPU (1 << 5) +#define __FORCE_STEREO (1 << 6) +#define __IMAGE_SETTINGS (1 << 7) +#define __XINERAMA_STEREO (1 << 8) +#define __SHOW_SLI_HUD (1 << 9) +#define __STEREO_EYES_EXCHANGE (1 << 9) @@ -150,11 +187,13 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, GtkWidget *vbox; GtkWidget *check_button; GtkWidget *scale; + GtkObject *adjustment; gint sync_to_vblank; gint flipping_allowed; gint force_stereo; gint xinerama_stereo; + gint stereo_eyes_exchange; NVCTRLAttributeValidValuesRec image_settings_valid; gint image_settings_value; gint aa_line_gamma; @@ -164,8 +203,9 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, ReturnStatus ret_flipping_allowed; ReturnStatus ret_force_stereo; ReturnStatus ret_xinerama_stereo; + ReturnStatus ret_stereo_eyes_exchange; ReturnStatus ret_image_settings; - ReturnStatus ret_aa_line_gama; + ReturnStatus ret_aa_line_gamma; ReturnStatus ret_show_sli_hud; /* Query OpenGL settings */ @@ -183,6 +223,10 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, ret_xinerama_stereo = NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA_STEREO, &xinerama_stereo); + ret_stereo_eyes_exchange = + NvCtrlGetAttribute(handle, NV_CTRL_STEREO_EYES_EXCHANGE, + &stereo_eyes_exchange); + ret_image_settings = NvCtrlGetValidAttributeValues(handle, NV_CTRL_IMAGE_SETTINGS, &image_settings_valid); @@ -195,8 +239,8 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, ret_image_settings = NvCtrlError; } - ret_aa_line_gama = NvCtrlGetAttribute(handle, NV_CTRL_OPENGL_AA_LINE_GAMMA, - &aa_line_gamma); + ret_aa_line_gamma = NvCtrlGetAttribute(handle, NV_CTRL_OPENGL_AA_LINE_GAMMA, + &aa_line_gamma); ret_show_sli_hud = NvCtrlGetAttribute(handle, NV_CTRL_SHOW_SLI_HUD, &show_sli_hud); @@ -205,8 +249,9 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, (ret_flipping_allowed != NvCtrlSuccess) && (ret_force_stereo != NvCtrlSuccess) && (ret_xinerama_stereo != NvCtrlSuccess) && + (ret_stereo_eyes_exchange != NvCtrlSuccess) && (ret_image_settings != NvCtrlSuccess) && - (ret_aa_line_gama != NvCtrlSuccess) && + (ret_aa_line_gamma != NvCtrlSuccess) && (ret_show_sli_hud != NvCtrlSuccess)) { return NULL; } @@ -368,6 +413,34 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, ctk_opengl->xinerama_stereo_button = check_button; } + if (ret_stereo_eyes_exchange == NvCtrlSuccess) { + + label = gtk_label_new("Exchange Stereo Eyes"); + + check_button = gtk_check_button_new(); + gtk_container_add(GTK_CONTAINER(check_button), label); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), + stereo_eyes_exchange); + + gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0); + + g_signal_connect(G_OBJECT(check_button), "toggled", + G_CALLBACK(stereo_eyes_exchange_button_toggled), + (gpointer) ctk_opengl); + + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_STEREO_EYES_EXCHANGE), + G_CALLBACK(value_changed), (gpointer) ctk_opengl); + + ctk_config_set_tooltip(ctk_config, check_button, + __stereo_eyes_exchange_help); + + ctk_opengl->active_attributes |= __STEREO_EYES_EXCHANGE; + + ctk_opengl->stereo_eyes_exchange_button = check_button; + } + /* * Image Quality settings. */ @@ -381,9 +454,13 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, gtk_container_set_border_width(GTK_CONTAINER(hbox), FRAME_PADDING); gtk_container_add(GTK_CONTAINER(frame), hbox); - scale = gtk_hscale_new_with_range(image_settings_valid.u.range.min, - image_settings_valid.u.range.max, 1); - gtk_range_set_value(GTK_RANGE(scale), image_settings_value); + /* create the slider */ + adjustment = gtk_adjustment_new(image_settings_value, + image_settings_valid.u.range.min, + image_settings_valid.u.range.max, + 1, 1, 0.0); + scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment)); + gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustment), image_settings_value); gtk_scale_set_draw_value(GTK_SCALE(scale), TRUE); gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP); @@ -430,7 +507,7 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, * NV_CTRL_OPENGL_AA_LINE_GAMMA */ - if (ret_aa_line_gama == NvCtrlSuccess) { + if (ret_aa_line_gamma == NvCtrlSuccess) { label = gtk_label_new("Enable gamma correction for antialiased lines"); check_button = gtk_check_button_new(); @@ -451,14 +528,26 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle, G_CALLBACK(value_changed), (gpointer) ctk_opengl); ctk_config_set_tooltip(ctk_opengl->ctk_config, - check_button, "Allow Gamma-corrected " - "antialiased lines to consider variances in " - "the color display capabilities of output " - "devices when rendering smooth lines"); - + check_button, __aa_line_gamma_checkbox_help); + + ctk_opengl->aa_line_gamma_button = check_button; ctk_opengl->active_attributes |= __AA_LINE_GAMMA; + + ctk_opengl->aa_line_gamma_scale = + create_slider(ctk_opengl, vbox, "Gamma correction", + __aa_line_gamma_slider_help, + NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE, + __AA_LINE_GAMMA_VALUE); + + g_signal_connect(G_OBJECT(ctk_event), + CTK_EVENT_NAME(NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE), + G_CALLBACK(aa_line_gamma_update_received), + (gpointer) ctk_opengl); - ctk_opengl->aa_line_gamma_button = check_button; + if (ctk_opengl->aa_line_gamma_scale) + gtk_widget_set_sensitive(ctk_opengl->aa_line_gamma_scale, + gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON(check_button))); } if (ret_show_sli_hud == NvCtrlSuccess) { @@ -537,6 +626,14 @@ static void post_xinerama_stereo_button_toggled(CtkOpenGL *ctk_opengl, enabled ? "allowed" : "not allowed"); } +static void post_stereo_eyes_exchange_button_toggled(CtkOpenGL *ctk_opengl, + gboolean enabled) +{ + ctk_config_statusbar_message(ctk_opengl->ctk_config, + "OpenGL Stereo Eyes Exchanged %s.", + enabled ? "enabled" : "disabled"); +} + static void post_aa_line_gamma_toggled(CtkOpenGL *ctk_opengl, gboolean enabled) { @@ -622,6 +719,22 @@ static void xinerama_stereo_button_toggled(GtkWidget *widget, post_xinerama_stereo_button_toggled(ctk_opengl, enabled); } +static void stereo_eyes_exchange_button_toggled(GtkWidget *widget, + gpointer user_data) +{ + CtkOpenGL *ctk_opengl; + gboolean enabled; + + ctk_opengl = CTK_OPENGL(user_data); + + enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + + NvCtrlSetAttribute(ctk_opengl->handle, NV_CTRL_STEREO_EYES_EXCHANGE, + enabled); + + post_stereo_eyes_exchange_button_toggled(ctk_opengl, enabled); +} + static void aa_line_gamma_toggled( GtkWidget *widget, gpointer user_data @@ -639,6 +752,8 @@ static void aa_line_gamma_toggled( NV_CTRL_OPENGL_AA_LINE_GAMMA, enabled); if (ret != NvCtrlSuccess) return; + if (ctk_opengl->aa_line_gamma_scale) + gtk_widget_set_sensitive(ctk_opengl->aa_line_gamma_scale, enabled); post_aa_line_gamma_toggled(ctk_opengl, enabled); } @@ -680,10 +795,18 @@ static void value_changed(GtkObject *object, gpointer arg1, gpointer user_data) func = G_CALLBACK(xinerama_stereo_button_toggled); post_xinerama_stereo_button_toggled(ctk_opengl, event_struct->value); break; + case NV_CTRL_STEREO_EYES_EXCHANGE: + button = GTK_TOGGLE_BUTTON(ctk_opengl->stereo_eyes_exchange_button); + func = G_CALLBACK(stereo_eyes_exchange_button_toggled); + post_stereo_eyes_exchange_button_toggled(ctk_opengl, + event_struct->value); + break; case NV_CTRL_OPENGL_AA_LINE_GAMMA: button = GTK_TOGGLE_BUTTON(ctk_opengl->aa_line_gamma_button); func = G_CALLBACK(aa_line_gamma_toggled); post_aa_line_gamma_toggled(ctk_opengl, event_struct->value); + gtk_widget_set_sensitive(ctk_opengl->aa_line_gamma_scale, + event_struct->value); break; case NV_CTRL_SHOW_SLI_HUD: button = GTK_TOGGLE_BUTTON(ctk_opengl->show_sli_hud_button); @@ -791,6 +914,122 @@ static void image_settings_update_received(GtkObject *object, } /* image_settings_update_received() */ +/* + * post_slider_value_changed() - helper function for + * aa_line_gamma_value_changed(); this does whatever work is necessary + * after the aa line gamma value has changed. + */ + +static void post_slider_value_changed(CtkOpenGL *ctk_opengl, gint val) +{ + ctk_config_statusbar_message(ctk_opengl->ctk_config, + "OpenGL anti-aliased lines edge smoothness " + "changed to %d\%.", + val); + +} /* post_slider_value_changed() */ + + +/* + * slider_changed() - + */ + +static void slider_changed(GtkAdjustment *adjustment, gpointer user_data) +{ + CtkOpenGL *ctk_opengl = CTK_OPENGL(user_data); + gint attribute, value; + user_data = g_object_get_data(G_OBJECT(adjustment), "opengl_attribute"); + attribute = GPOINTER_TO_INT(user_data); + value = (gint) adjustment->value; + NvCtrlSetAttribute(ctk_opengl->handle, attribute, value); + post_slider_value_changed(ctk_opengl, value); +} /* slider_changed() */ + + +/* + * aa_line_gamma_update_received() - this function is called when the + * NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE atribute is changed by another NV-CONTROL + * client. + */ + +static void aa_line_gamma_update_received(GtkObject *object, + gpointer arg1, gpointer user_data) +{ + CtkEventStruct *event_struct = (CtkEventStruct *) arg1; + CtkOpenGL *ctk_opengl = CTK_OPENGL(user_data); + CtkScale *scale = CTK_SCALE(ctk_opengl->aa_line_gamma_scale); + GtkAdjustment *adjustment; + adjustment = GTK_ADJUSTMENT(scale->gtk_adjustment); + g_signal_handlers_block_by_func(G_OBJECT(adjustment), + G_CALLBACK(slider_changed), + (gpointer) ctk_opengl); + + gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustment), + (gint)event_struct->value); + post_slider_value_changed(ctk_opengl, event_struct->value); + + g_signal_handlers_unblock_by_func(G_OBJECT(adjustment), + G_CALLBACK(slider_changed), + (gpointer) ctk_opengl); + +} /* aa_line_gamma_update_received() */ + + + +static GtkWidget *create_slider(CtkOpenGL *ctk_opengl, + GtkWidget *vbox, + const gchar *name, + const char *help, + gint attribute, + unsigned int bit) +{ + GtkObject *adjustment; + GtkWidget *scale, *widget; + gint min, max, val, step_incr, page_incr; + NVCTRLAttributeValidValuesRec range; + ReturnStatus ret; + /* get the attribute value */ + + ret = NvCtrlGetAttribute(ctk_opengl->handle, attribute, &val); + if (ret != NvCtrlSuccess) return NULL; + /* get the range for the attribute */ + + NvCtrlGetValidAttributeValues(ctk_opengl->handle, attribute, &range); + + if (range.type != ATTRIBUTE_TYPE_RANGE) return NULL; + min = range.u.range.min; + max = range.u.range.max; + + step_incr = ((max) - (min))/10; + if (step_incr <= 0) step_incr = 1; + page_incr = ((max) - (min))/25; + if (page_incr <= 0) page_incr = 1; + + /* create the slider */ + adjustment = gtk_adjustment_new(val, min, max, + step_incr, page_incr, 0.0); + + g_object_set_data(G_OBJECT(adjustment), "opengl_attribute", + GINT_TO_POINTER(attribute)); + + g_signal_connect(G_OBJECT(adjustment), "value_changed", + G_CALLBACK(slider_changed), + (gpointer) ctk_opengl); + + scale = ctk_scale_new(GTK_ADJUSTMENT(adjustment), name, + ctk_opengl->ctk_config, G_TYPE_INT); + + gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0); + + ctk_opengl->active_attributes |= bit; + + widget = CTK_SCALE(scale)->gtk_scale; + ctk_config_set_tooltip(ctk_opengl->ctk_config, widget, help); + + return scale; +} /* create_slider() */ + + GtkTextBuffer *ctk_opengl_create_help(GtkTextTagTable *table, CtkOpenGL *ctk_opengl) { @@ -835,6 +1074,11 @@ GtkTextBuffer *ctk_opengl_create_help(GtkTextTagTable *table, ctk_help_para(b, &i, __xinerama_stereo_help); } + if (ctk_opengl->active_attributes & __STEREO_EYES_EXCHANGE) { + ctk_help_heading(b, &i, "Exchange Stereo Eyes"); + ctk_help_para(b, &i, __stereo_eyes_exchange_help); + } + if (ctk_opengl->active_attributes & __IMAGE_SETTINGS) { ctk_help_heading(b, &i, "Image Settings"); ctk_help_para(b, &i, "This setting gives you full control over the " @@ -871,13 +1115,13 @@ GtkTextBuffer *ctk_opengl_create_help(GtkTextTagTable *table, if (ctk_opengl->active_attributes & __AA_LINE_GAMMA) { ctk_help_heading(b, &i, "Enable gamma correction for " "antialiased lines"); - ctk_help_para(b, &i, "Enabling this option allows Gamma-corrected " - "antialiased lines to consider variances in the color " - "display capabilities of output devices when rendering " - "smooth lines. This option is available only on " - "Quadro FX or newer NVIDIA GPUs. This option is " - "applied to OpenGL applications that are started after " - "this option is set."); + ctk_help_para(b, &i, __aa_line_gamma_checkbox_help ); + } + + if (ctk_opengl->active_attributes & __AA_LINE_GAMMA_VALUE) { + ctk_help_heading(b, &i, "Set gamma correction for " + "antialiased lines"); + ctk_help_para(b, &i, __aa_line_gamma_slider_help); } if (ctk_opengl->active_attributes & __SHOW_SLI_HUD) { diff --git a/src/gtk+-2.x/ctkopengl.h b/src/gtk+-2.x/ctkopengl.h index ff37a0c..0a693dc 100644 --- a/src/gtk+-2.x/ctkopengl.h +++ b/src/gtk+-2.x/ctkopengl.h @@ -62,8 +62,10 @@ struct _CtkOpenGL GtkWidget *allow_flipping_button; GtkWidget *force_stereo_button; GtkWidget *xinerama_stereo_button; + GtkWidget *stereo_eyes_exchange_button; GtkWidget *image_settings_scale; GtkWidget *aa_line_gamma_button; + GtkWidget *aa_line_gamma_scale; GtkWidget *show_sli_hud_button; unsigned int active_attributes; diff --git a/src/gtk+-2.x/ctkslimm.c b/src/gtk+-2.x/ctkslimm.c index ebd4732..1f6b1bd 100644 --- a/src/gtk+-2.x/ctkslimm.c +++ b/src/gtk+-2.x/ctkslimm.c @@ -74,6 +74,10 @@ static const GridConfig gridConfigs[] = { {3, 1}, {3, 2}, {1, 3}, + {2, 1}, + {1, 2}, + {4, 1}, + {1, 4}, {0, 0} }; diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c index 3eed0e6..cb93c33 100644 --- a/src/gtk+-2.x/ctkwindow.c +++ b/src/gtk+-2.x/ctkwindow.c @@ -387,6 +387,9 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **screen_handles, GtkWidget *toggle_button; GtkWidget *statusbar; GtkWidget *eventbox; + GtkWidget *label; + GtkRequisition req; + gint width; GtkTreeViewColumn *column; GtkCellRenderer *renderer; @@ -591,7 +594,8 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **screen_handles, CTK_DISPLAY_CONFIG(child)), ctk_window, NULL, NULL, "X Server Display Configuration", - NULL, NULL, NULL); + NULL, ctk_display_config_selected, + ctk_display_config_unselected); } } } @@ -965,6 +969,31 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **screen_handles, gtk_widget_show_all(GTK_WIDGET(object)); + + /* Set the minimum width of the tree view window to be something + * reasonable. To do that, check the size of a label widget + * with a reasonably long string and limit the tree view scroll + * window's initial width to not extent past this. + */ + + label = gtk_label_new("XXXXXX Server Display ConfigurationXXXX"); + gtk_widget_size_request(label, &req); + width = req.width; + gtk_widget_destroy(label); + + /* Get the width of the tree view scroll window */ + gtk_widget_size_request(sw, &req); + + /* If the scroll window is too wide, make it slimmer and + * allow users to scroll horizontally (also allow resizing). + */ + if ( width < req.width ) { + gtk_widget_set_size_request(sw, width, -1); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + } + return GTK_WIDGET(object); } /* ctk_window_new() */ @@ -1291,16 +1320,15 @@ static void update_display_devices(GtkObject *object, gpointer arg1, gtk_tree_selection_select_iter(tree_selection, &parent_iter); } - /* unref the page so we don't leak memory */ + /* Remove the entry */ gtk_tree_model_get(GTK_TREE_MODEL(ctk_window->tree_store), iter, CTK_WINDOW_WIDGET_COLUMN, &widget, -1); - g_object_unref(widget); - - /* XXX Call a widget-specific cleanup function? */ - - /* Remove the entry */ + gtk_tree_store_remove(ctk_window->tree_store, iter); + /* unref the page so we don't leak memory */ + g_object_unref(GTK_OBJECT(widget)); + data->num_displays--; } diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h index 8082311..5e79a88 100644 --- a/src/libXNVCtrl/NVCtrl.h +++ b/src/libXNVCtrl/NVCtrl.h @@ -3322,6 +3322,23 @@ #define NV_CTRL_DEPTH_30_ALLOWED 279 /* R--G */ /* + * NV_CTRL_MODE_SET_EVENT This attribute is sent as an event + * when hotkey, ctrl-alt-+/- or randr event occurs. Note that + * This attribute cannot be set or queried and is meant to + * be received by clients that wish to be notified of when + * mode set events occur. + */ + +#define NV_CTRL_MODE_SET_EVENT 280 /* --- */ + +/* + * NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE - the gamma value used by + * OpenGL when NV_CTRL_OPENGL_AA_LINE_GAMMA is enabled + */ + +#define NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE 281 /* RW-X */ + +/* * NV_CTRL_DISPLAYPORT_LINK_RATE - returns the negotiated lane bandwidth of the * DisplayPort main link. * This attribute is only available for DisplayPort flat panels. @@ -3332,7 +3349,35 @@ #define NV_CTRL_DISPLAYPORT_LINK_RATE_1_62GBPS 0x6 #define NV_CTRL_DISPLAYPORT_LINK_RATE_2_70GBPS 0xA -#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_DISPLAYPORT_LINK_RATE +/* + * NV_CTRL_STEREO_EYES_EXCHANGE - Controls whether or not the left and right + * eyes of a stereo image are flipped. + */ + +#define NV_CTRL_STEREO_EYES_EXCHANGE 292 /* RW-X */ +#define NV_CTRL_STEREO_EYES_EXCHANGE_OFF 0 +#define NV_CTRL_STEREO_EYES_EXCHANGE_ON 1 + +/* + * NV_CTRL_NO_SCANOUT - returns whether the special "NoScanout" mode is + * enabled on the specified X screen or GPU; for details on this mode, + * see the description of the "none" value for the "UseDisplayDevice" + * X configuration option in the NVIDIA driver README. + */ + +#define NV_CTRL_NO_SCANOUT 293 /* R--G */ +#define NV_CTRL_NO_SCANOUT_DISABLED 0 +#define NV_CTRL_NO_SCANOUT_ENABLED 1 + +/* + * NV_CTRL_GVO_CSC_CHANGED_EVENT This attribute is sent as an event + * when the color space conversion matrix has been altered by another + * client. + */ + +#define NV_CTRL_GVO_CSC_CHANGED_EVENT 294 /* --- */ + +#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_GVO_CSC_CHANGED_EVENT /**************************************************************************/ diff --git a/src/lscf.c b/src/lscf.c new file mode 100644 index 0000000..cf4e66b --- /dev/null +++ b/src/lscf.c @@ -0,0 +1,275 @@ +#include <stdio.h> +#if defined(NV_SUNOS) + +/* Interface to the Solaris Service Management Facility. + * This facility is responsible for running programs and services + * and store their configuration informations (named properties) + * The configuration informations for the X server are managed by + * this facility. The functions in this source file use the library + * libscf (Service Configuration Facility) to access and modify + * the properties for the X server, more specifically the default depth. + * On Solaris, changing the default depth in the xorg.conf file is not + * enough. The session manager overrides the xorg.conf default depth: + * it passes the option -defdepth to the X server with the value + * retrieved from the Service Management Facility. + * + * For more information refer to the manpages of fmf(5), libsfc(3LIB), + * and to the source code of svccfg(1M) available on cvs.opensolaris.org. + */ + + +#include <libscf.h> + +static int lscf_init_handle(scf_handle_t **scf_handle, + scf_scope_t **scf_scope); +static int lscf_select(scf_handle_t *scf_handle, + scf_scope_t *scf_scope, + const char *selection, + scf_service_t **current_svc); +static int lscf_setprop_int(scf_handle_t *scf_handle, + scf_scope_t *scf_scope, + scf_service_t *current_svc, + const char *group, + const char *name, int value); + +/* UPDATE THE DEFAULT DEPTH PROPERTY IN SMF WITH THE LIBSCF FUNCTIONS */ +int update_scf_depth(int depth) +{ + static scf_handle_t *scf_handle = NULL; + static scf_scope_t *scf_scope = NULL; + scf_service_t *curren_svc = NULL; + int status = 1; + + // Initialization of the handles + lscf_init_handle(&scf_handle, &scf_scope); + if (scf_handle == NULL) { + status =0; + goto done; + } + + // Set the current selection + if(!lscf_select(scf_handle, scf_scope, "application/x11/x11-server", + ¤_svc)) { + status =0; + goto done; + } + + // Set the depth property of the current selection + if(!lscf_setprop_int(scf_handle, scf_scope, curren_svc, + "options", "default_depth", depth)) { + status =0; + goto done; + } + +done: + if(curren_svc) scf_service_destroy(curren_svc); + if(scf_scope) scf_scope_destroy(scf_scope); + if(scf_handle) { + scf_handle_unbind(scf_handle); + scf_handle_destroy(scf_handle); + } + if (!status) { + fmterr("Unable to set X server default depth through " + "Solaris Service Management Facility"); + } + return status; +} + +/* INITIALIZATION OF THE HANDLES */ +static int lscf_init_handle(scf_handle_t **scf_handle, + scf_scope_t **scf_scope) +{ + scf_handle_t *handle = NULL; + scf_scope_t *scope = NULL;; + + *scf_handle = NULL; + *scf_scope = NULL; + + // Create a new Service Configuration Facility + // handle, needed for the communication with the + // configuration repository. + handle = scf_handle_create(SCF_VERSION); + if (handle == NULL) { + return 0; + } + + // Bind the handle to the running svc.config daemon + if (scf_handle_bind(handle) != 0) { + scf_handle_destroy(handle); + return 0; + } + + + // Allocate a new scope. A scope is a top level of the + // SCF repository tree. + scope = scf_scope_create(handle); + if (scope == NULL) { + scf_handle_unbind(handle); + scf_handle_destroy(handle); + return 0; + } + + // Set the scope to the root of the local SCF repository tree. + if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) !=0) { + scf_scope_destroy(scope); + scf_handle_unbind(handle); + scf_handle_destroy(handle); + return 0; + } + + *scf_handle = handle; + *scf_scope = scope; + + return 1; +} + + +/* EQUIVALENT TO THE SVCCFG SELECT COMMAND */ +static int lscf_select(scf_handle_t *scf_handle, + scf_scope_t *scf_scope, + const char *selection, + scf_service_t **current_svc) +{ + scf_service_t *svc; + + // Services are childrens of a scope, and + // contain configuration informations for + // the service. + svc = scf_service_create(scf_handle); + if (svc == NULL) { + return 0; + } + + // Set the service 'svc' to the service specified + // by 'selection', in the scope 'scf_scope'. + if (scf_scope_get_service(scf_scope, selection, svc) == SCF_SUCCESS) { + *current_svc = svc; + return 1; + } + + scf_service_destroy(svc); + return 0; +} + +/* EQUIVALENT TO THE SVCCFG SETPROP COMMAND FOR AN INTEGER TYPED VALUE */ +static int lscf_setprop_int(scf_handle_t *scf_handle, + scf_scope_t *scf_scope, + scf_service_t *current_svc, + const char *group, + const char *name, int value) +{ + scf_transaction_entry_t *entry=NULL; + scf_propertygroup_t *pg = NULL; + scf_property_t *prop = NULL; + scf_transaction_t *transax = NULL; + scf_value_t *v = NULL; + int status = 1; + + // Allocate a new transaction entry handle + entry = scf_entry_create(scf_handle); + if (entry == NULL) { + status=0; + goto done; + } + + // Allocate a property group. + pg = scf_pg_create(scf_handle); + if (pg == NULL) { + status=0; + goto done; + } + + // Allocate a property. A property is a named set + // of values. + prop = scf_property_create(scf_handle); + if (prop == NULL) { + status=0; + goto done; + } + + // Allocate a transaction, used to change + // property groups. + transax = scf_transaction_create(scf_handle); + if (transax == NULL) { + status=0; + goto done; + } + + // Allocate a value. + v = scf_value_create(scf_handle); + if (v == NULL) { + status=0; + goto done; + } + + // Set the the property group 'pg' to the + // groups specified by 'group' in the service + // specified by 'current_svc' + if (scf_service_get_pg(current_svc, group, pg) != SCF_SUCCESS) { + status=0; + goto done; + } + + // Update the property group. + if (scf_pg_update(pg) == -1) { + status=0; + goto done; + } + + // Set up the transaction to modify the property group. + if (scf_transaction_start(transax, pg) != SCF_SUCCESS) { + status=0; + goto done; + } + + // Set the property 'prop' to the property + // specified ny 'name' in the property group 'pg' + if (scf_pg_get_property(pg, name, prop) == SCF_SUCCESS) { + // Found + // It should be already of integer type. + // To be secure, reset the property type to integer. + if (scf_transaction_property_change_type(transax, entry, + name, SCF_TYPE_INTEGER) == -1) { + status=0; + goto done; + } + } else { + // Not found + // Add a new property to the property group. + if (scf_transaction_property_new(transax, entry, + name, SCF_TYPE_INTEGER) + == -1) { + status=0; + goto done; + } + } + + // Set the integer value + scf_value_set_integer(v, value); + + // Set up the value to the property. + if (scf_entry_add_value(entry, v) != SCF_SUCCESS) { + status=0; + goto done; + } + + // Commit the transaction + if (scf_transaction_commit(transax) < 0) { + status=0; + } + +done: + if (entry) scf_entry_destroy(entry); + if (pg) scf_pg_destroy(pg); + if (prop) scf_property_destroy(prop); + if (transax) scf_transaction_destroy(transax); + if (v) scf_value_destroy(v); + return status; +} + +#else // NOT SOLARIS +int update_scf_depth(int depth) +{ + return 1; +} +#endif diff --git a/src/lscf.h b/src/lscf.h new file mode 100644 index 0000000..936817d --- /dev/null +++ b/src/lscf.h @@ -0,0 +1,31 @@ +/* + * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix + * and Linux systems. + * + * Copyright (C) 2004 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307, USA + * + */ + +#ifndef __LSCF_H__ +#define __LSCF_H__ + +/* lscf.c */ +int update_scf_depth(int depth); + +#endif /* __LSCF_H__ */ diff --git a/src/parse.c b/src/parse.c index d55b146..ec19f0b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -88,6 +88,7 @@ AttributeTableEntry attributeTable[] = { { "Overlay", NV_CTRL_OVERLAY, 0 }, { "HWOverlay", NV_CTRL_HWOVERLAY, 0 }, { "Stereo", NV_CTRL_STEREO, 0 }, + { "StereoEyesExchange", NV_CTRL_STEREO_EYES_EXCHANGE, 0 }, { "TwinView", NV_CTRL_TWINVIEW, 0 }, { "ConnectedDisplays", NV_CTRL_CONNECTED_DISPLAYS, D }, { "EnabledDisplays", NV_CTRL_ENABLED_DISPLAYS, D }, @@ -97,7 +98,9 @@ AttributeTableEntry attributeTable[] = { { "AssociatedDisplays", NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, N|D }, { "ProbeDisplays", NV_CTRL_PROBE_DISPLAYS, A }, { "Depth30Allowed", NV_CTRL_DEPTH_30_ALLOWED, N }, + { "NoScanout", NV_CTRL_NO_SCANOUT, N }, { "ForceGenericCpu", NV_CTRL_FORCE_GENERIC_CPU, N }, + { "GammaCorrectedAALinesValue", NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE, 0 }, { "GammaCorrectedAALines", NV_CTRL_OPENGL_AA_LINE_GAMMA, 0 }, { "ShowSLIHUD", NV_CTRL_SHOW_SLI_HUD, 0 }, { "CursorShadow", NV_CTRL_CURSOR_SHADOW, 0 }, @@ -260,7 +263,7 @@ AttributeTableEntry attributeTable[] = { * about. */ -#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_DISPLAYPORT_LINK_RATE +#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GVO_CSC_CHANGED_EVENT #warning "Have you forgotten to add a new integer attribute to attributeTable?" #endif @@ -318,7 +321,6 @@ int nv_parse_attribute_string(const char *str, int query, ParsedAttribute *a) int len, ret; #define stop(x) { if (no_spaces) free(no_spaces); return (x); } - if (!a) stop(NV_PARSER_STATUS_BAD_ARGUMENT); /* clear the ParsedAttribute struct */ @@ -415,11 +417,14 @@ int nv_parse_attribute_string(const char *str, int query, ParsedAttribute *a) /* * Either a single 32-bit integer or two 16-bit * integers, separated by ','. + * Passing base as 0 allows packed values to be specified + * in hex (Bug 377242) */ - a->val = strtol(s, &tmp, 10); + a->val = strtol(s, &tmp, 0); + if (tmp && *tmp == ',') { a->val = (a->val & 0xffff) << 16; - a->val |= strtol((tmp + 1), &tmp, 10) & 0xffff; + a->val |= strtol((tmp + 1), &tmp, 0) & 0xffff; } } else if (a->flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY) { if (nv_strcasecmp(s, "alldisplays")) { |