From 2ff82733227428136ed9d8978ab54cf2e0a5a235 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 23 Apr 2003 15:01:16 +0000 Subject: [PATCH] Initial import. UI not fully polished yet. 2003-04-23 Alexander Larsson * .cvsignore: * display-capplet.png: * display-properties.desktop.in: * main.c: * Makefile.am: Initial import. UI not fully polished yet. 2003-04-23 Alexander Larsson * capplets/Makefile.am: * configure.in: * capplets/display/* Check for XRandR support. Add display capplet. --- ChangeLog | 8 + capplets/Makefile.am | 12 +- capplets/display/.cvsignore | 6 + capplets/display/Makefile.am | 26 + capplets/display/display-capplet.png | Bin 0 -> 4353 bytes .../display/display-properties.desktop.in | 13 + capplets/display/main.c | 778 ++++++++++++++++++ configure.in | 24 + 8 files changed, 864 insertions(+), 3 deletions(-) create mode 100644 capplets/display/.cvsignore create mode 100644 capplets/display/Makefile.am create mode 100644 capplets/display/display-capplet.png create mode 100644 capplets/display/display-properties.desktop.in create mode 100644 capplets/display/main.c diff --git a/ChangeLog b/ChangeLog index fb1ca0306..e7a67388d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2003-04-23 Alexander Larsson + + * capplets/Makefile.am: + * configure.in: + * capplets/display/* + Check for XRandR support. + Add display capplet. + 2003-03-21 Guntupalli Karunakar * configure.in: Added "ml" in ALL_LINGUAS. diff --git a/capplets/Makefile.am b/capplets/Makefile.am index 5db9da3c8..b370bbafd 100644 --- a/capplets/Makefile.am +++ b/capplets/Makefile.am @@ -3,12 +3,18 @@ always_built_SUBDIRS = \ default-applications desktop-links font \ background keyboard mouse sound \ file-types theme-switcher ui-properties \ - keybindings network windows + keybindings network windows -SUBDIRS = $(always_built_SUBDIRS) +if HAVE_RANDR +randr_SUBDIRS = display +else +randr_SUBDIRS = +endif + +SUBDIRS = $(always_built_SUBDIRS) $(randr_SUBDIRS) DIST_SUBDIRS = \ - $(always_built_SUBDIRS) + $(always_built_SUBDIRS) display diff --git a/capplets/display/.cvsignore b/capplets/display/.cvsignore new file mode 100644 index 000000000..b0d2b5028 --- /dev/null +++ b/capplets/display/.cvsignore @@ -0,0 +1,6 @@ +Makefile +Makefile.in +.deps +.libs +gnome-display-properties +display-properties.desktop diff --git a/capplets/display/Makefile.am b/capplets/display/Makefile.am new file mode 100644 index 000000000..e179722b5 --- /dev/null +++ b/capplets/display/Makefile.am @@ -0,0 +1,26 @@ +bin_PROGRAMS = gnome-display-properties + +gnome_display_properties_LDADD = $(DISPLAY_CAPPLET_LIBS) $(top_builddir)/capplets/common/libcommon.la +gnome_display_properties_SOURCES = \ + main.c +gnome_display_properties_LDFLAGS = -export-dynamic + +@INTLTOOL_DESKTOP_RULE@ + +iconsdir = $(GNOMECC_ICONS_DIR) +icons_DATA = display-capplet.png + +desktop_iconsdir = $(datadir)/pixmaps +desktop_icons_DATA = display-capplet.png + +desktopdir = $(GNOMECC_DESKTOP_DIR) +Desktop_in_files = display-properties.desktop.in +desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop) + +INCLUDES = $(DISPLAY_CAPPLET_CFLAGS) \ + $(GNOMECC_CAPPLETS_CFLAGS) \ + -DGLADEDIR=\""$(gladedir)"\" \ + -DPIXMAPDIR=\""$(pixmapdir)"\" + +CLEANFILES = $(GNOMECC_CAPPLETS_CLEANFILES) +EXTRA_DIST = $(Desktop_in_files) $(icons_DATA) diff --git a/capplets/display/display-capplet.png b/capplets/display/display-capplet.png new file mode 100644 index 0000000000000000000000000000000000000000..90c25fb76aba031f048e21d4fb9bb6cc5a26f0fd GIT binary patch literal 4353 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 literal 0 HcmV?d00001 diff --git a/capplets/display/display-properties.desktop.in b/capplets/display/display-properties.desktop.in new file mode 100644 index 000000000..80fdd2d45 --- /dev/null +++ b/capplets/display/display-properties.desktop.in @@ -0,0 +1,13 @@ +[Desktop Entry] +Encoding=UTF-8 +_Name=Screen Resolution +_Comment=Change screen resolution +Exec=gnome-display-properties +Icon=display-capplet.png +Terminal=false +Type=Application +StartupNotify=true +Categories=GNOME;Settings;Appearance; +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=control-center +X-GNOME-Bugzilla-Component=display properties diff --git a/capplets/display/main.c b/capplets/display/main.c new file mode 100644 index 000000000..fe892d6a1 --- /dev/null +++ b/capplets/display/main.c @@ -0,0 +1,778 @@ +#include + +#include +#include +#include +#include +#include + +#include + +#include "capplet-util.h" + +#define REVERT_COUNT 20 + +struct ScreenInfo { + int current_width; + int current_height; + SizeID current_size; + short current_rate; + Rotation current_rotation; + + XRRScreenConfiguration *config; + XRRScreenSize *sizes; + int n_sizes; + + GtkWidget *resolution_widget; + GtkWidget *rate_widget; +}; + +struct DisplayInfo { + int n_screens; + struct ScreenInfo *screens; + + GtkWidget *per_computer_check; + gboolean was_per_computer; +}; + + +struct DisplayInfo * +read_display_info (GdkDisplay *display) +{ + struct DisplayInfo *info; + struct ScreenInfo *screen_info; + GdkScreen *screen; + GdkWindow *root_window; + int i; + + info = g_new (struct DisplayInfo, 1); + info->n_screens = gdk_display_get_n_screens (display); + info->screens = g_new (struct ScreenInfo, info->n_screens); + + for (i = 0; i < info->n_screens; i++) + { + screen = gdk_display_get_screen (display, i); + + screen_info = &info->screens[i]; + screen_info->current_width = gdk_screen_get_width (screen); + screen_info->current_height = gdk_screen_get_height (screen); + + root_window = gdk_screen_get_root_window (screen); + screen_info->config = XRRGetScreenInfo (gdk_x11_display_get_xdisplay (display), + gdk_x11_drawable_get_xid (GDK_DRAWABLE (root_window))); + + screen_info->current_rate = XRRConfigCurrentRate (screen_info->config); + screen_info->current_size = XRRConfigCurrentConfiguration (screen_info->config, &screen_info->current_rotation); + screen_info->sizes = XRRConfigSizes (screen_info->config, &screen_info->n_sizes); + } + + return info; +} + +static int +get_current_resolution (struct ScreenInfo *screen_info) +{ + GtkWidget *menu; + GList *children; + GList *child; + int i; + + i = gtk_option_menu_get_history (GTK_OPTION_MENU (screen_info->resolution_widget)); + menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (screen_info->resolution_widget)); + children = gtk_container_get_children (GTK_CONTAINER (menu)); + child = g_list_nth (children, i); + + if (child != NULL) + return GPOINTER_TO_INT (g_object_get_data (child->data, "screen_nr")); + else + return 0; +} + +static int +get_current_rate (struct ScreenInfo *screen_info) +{ + GtkWidget *menu; + GList *children; + GList *child; + int i; + + i = gtk_option_menu_get_history (GTK_OPTION_MENU (screen_info->rate_widget)); + menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (screen_info->rate_widget)); + children = gtk_container_get_children (GTK_CONTAINER (menu)); + child = g_list_nth (children, i); + + if (child != NULL) + return GPOINTER_TO_INT (g_object_get_data (child->data, "rate")); + else + return 0; +} + +static gboolean +apply_config (struct DisplayInfo *info) +{ + int i; + GdkDisplay *display; + Display *xdisplay; + GdkScreen *screen; + gboolean changed; + + display = gdk_display_get_default (); + xdisplay = gdk_x11_display_get_xdisplay (display); + + changed = FALSE; + for (i = 0; i < info->n_screens; i++) + { + struct ScreenInfo *screen_info = &info->screens[i]; + Status status; + GdkWindow *root_window; + int new_res, new_rate; + + screen = gdk_display_get_screen (display, i); + root_window = gdk_screen_get_root_window (screen); + + new_res = get_current_resolution (screen_info); + new_rate = get_current_rate (screen_info); + + if (new_res != screen_info->current_size || + new_rate != screen_info->current_rate) + { + changed = TRUE; + status = XRRSetScreenConfigAndRate (xdisplay, + screen_info->config, + gdk_x11_drawable_get_xid (GDK_DRAWABLE (root_window)), + new_res, + screen_info->current_rotation, + new_rate, + GDK_CURRENT_TIME); + } + } + + return changed; +} + +static int +revert_config (struct DisplayInfo *info) +{ + int i; + GdkDisplay *display; + Display *xdisplay; + GdkScreen *screen; + + display = gdk_display_get_default (); + xdisplay = gdk_x11_display_get_xdisplay (display); + + for (i = 0; i < info->n_screens; i++) + { + struct ScreenInfo *screen_info = &info->screens[i]; + Status status; + GdkWindow *root_window; + + screen = gdk_display_get_screen (display, i); + root_window = gdk_screen_get_root_window (screen); + + status = XRRSetScreenConfigAndRate (xdisplay, + screen_info->config, + gdk_x11_drawable_get_xid (GDK_DRAWABLE (root_window)), + screen_info->current_size, + screen_info->current_rotation, + screen_info->current_rate, + GDK_CURRENT_TIME); + } + return 0; +} + +static GtkWidget * +wrap_in_label (GtkWidget *child, char *text) +{ + GtkWidget *vbox, *hbox; + GtkWidget *label; + char *str; + + vbox = gtk_vbox_new (FALSE, 6); + label = 0; + + label = gtk_label_new (""); + + str = g_strdup_printf ("%s", text); + gtk_label_set_markup (GTK_LABEL (label), str); + g_free (str); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (vbox), + label, + FALSE, FALSE, 0); + + hbox = gtk_hbox_new (FALSE, 0); + + label = gtk_label_new (" "); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (hbox), + label, + FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (hbox), + child, + TRUE, TRUE, 0); + + gtk_widget_show (hbox); + + gtk_box_pack_start (GTK_BOX (vbox), + hbox, + FALSE, FALSE, 0); + + gtk_widget_show (vbox); + + return vbox; +} + +static gboolean +show_resolution (int width, int height) +{ + if (width >= 800 && height >= 600) + return TRUE; + + if (width == 640 && height == 480) + return TRUE; + + return FALSE; +} + +static void +generate_rate_menu (struct ScreenInfo *screen_info) +{ + GtkWidget *menu; + GtkWidget *menuitem; + short *rates; + int nrates, i; + int size_nr; + char *str; + int closest_rate_nr; + + gtk_option_menu_remove_menu (GTK_OPTION_MENU (screen_info->rate_widget)); + + menu = gtk_menu_new (); + + size_nr = get_current_resolution (screen_info); + + closest_rate_nr = -1; + rates = XRRConfigRates (screen_info->config, size_nr, &nrates); + for (i = 0; i < nrates; i++) + { + str = g_strdup_printf (_("%d Hz"), rates[i]); + + if ((closest_rate_nr < 0) || + (ABS (rates[i] - screen_info->current_rate) < + ABS (rates[closest_rate_nr] - screen_info->current_rate))) + closest_rate_nr = i; + + menuitem = gtk_menu_item_new_with_label (str); + + g_object_set_data (G_OBJECT (menuitem), "rate", GINT_TO_POINTER ((int)rates[i])); + + g_free (str); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + } + + gtk_option_menu_set_menu (GTK_OPTION_MENU (screen_info->rate_widget), menu); + gtk_option_menu_set_history (GTK_OPTION_MENU (screen_info->rate_widget), + closest_rate_nr); +} + +static void +resolution_changed_callback (GtkWidget *optionmenu, + struct ScreenInfo *screen_info) +{ + generate_rate_menu (screen_info); +} + +static GtkWidget * +create_resolution_menu (struct ScreenInfo *screen_info) +{ + GtkWidget *optionmenu; + GtkWidget *menu; + GtkWidget *menuitem; + int i, item, current_item; + XRRScreenSize *sizes; + char *str; + SizeID current_size; + Rotation rot; + + screen_info->resolution_widget = optionmenu = gtk_option_menu_new (); + + menu = gtk_menu_new (); + + current_size = XRRConfigCurrentConfiguration (screen_info->config, &rot); + + current_item = 0; + item = 0; + sizes = screen_info->sizes; + for (i = 0; i < screen_info->n_sizes; i++) + { + if (i == current_size || show_resolution (sizes[i].width, sizes[i].height)) + { + str = g_strdup_printf ("%dx%d", sizes[i].width, sizes[i].height); + + if (i == current_size) + current_item = item; + + menuitem = gtk_menu_item_new_with_label (str); + + g_object_set_data (G_OBJECT (menuitem), "screen_nr", GINT_TO_POINTER (i)); + + g_free (str); + gtk_widget_show (menuitem); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + item++; + } + } + + gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu); + gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), + current_item); + + g_signal_connect (optionmenu, "changed", + G_CALLBACK (resolution_changed_callback), screen_info); + + gtk_widget_show (optionmenu); + return optionmenu; +} + +static GtkWidget * +create_rate_menu (struct ScreenInfo *screen_info) +{ + GtkWidget *optionmenu; + + screen_info->rate_widget = optionmenu = gtk_option_menu_new (); + + generate_rate_menu (screen_info); + + gtk_widget_show (optionmenu); + return optionmenu; +} + +static GtkWidget * +create_screen_widgets (struct ScreenInfo *screen_info, int nr, gboolean no_header) +{ + GtkWidget *table; + GtkWidget *label; + GtkWidget *option_menu; + char *str; + + table = gtk_table_new (2, 2, FALSE); + + gtk_table_set_row_spacings ( GTK_TABLE (table), 6); + gtk_table_set_col_spacings ( GTK_TABLE (table), 12); + + label = gtk_label_new (_("Resolution:")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_widget_show (label); + gtk_table_attach (GTK_TABLE (table), + label, + 0, 1, + 0, 1, + GTK_FILL, 0, + 0, 0); + + option_menu = create_resolution_menu (screen_info); + gtk_table_attach (GTK_TABLE (table), + option_menu, + 1, 2, + 0, 1, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + + label = gtk_label_new (_("Refresh rate:")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_widget_show (label); + gtk_table_attach (GTK_TABLE (table), + label, + 0, 1, + 1, 2, + GTK_FILL, 0, + 0, 0); + gtk_widget_show (table); + + option_menu = create_rate_menu (screen_info); + gtk_table_attach (GTK_TABLE (table), + option_menu, + 1, 2, + 1, 2, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + + if (nr == 0) + str = g_strdup (_("Default Settings")); + else + str = g_strdup_printf (_("Screen %d Settings\n"), nr+1); + return wrap_in_label (table, str); + + g_free (str); +} + + +static GtkWidget * +create_dialog (struct DisplayInfo *info) +{ + GtkWidget *dialog; + GtkWidget *screen_widget; + GtkWidget *per_computer_check; + int i; + GtkWidget *wrapped; + GConfClient *client; + char *key; + char *resolution; + char *str; +#ifdef HOST_NAME_MAX + char hostname[HOST_NAME_MAX + 1]; +#else + char hostname[256]; +#endif + + dialog = gtk_dialog_new_with_buttons (_("Screen Resolution Preferences"), + NULL, + GTK_DIALOG_NO_SEPARATOR, + "gtk-apply", + GTK_RESPONSE_APPLY, + "gtk-help", + GTK_RESPONSE_HELP, + NULL); + + gtk_container_set_border_width (GTK_CONTAINER (dialog), 12); + gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12); + capplet_set_icon (dialog, "display-capplet.png"); + + for (i = 0; i < info->n_screens; i++) + { + screen_widget = create_screen_widgets (&info->screens[i], i, info->n_screens == 1); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + screen_widget, FALSE, FALSE, 0); + gtk_widget_show (screen_widget); + } + + per_computer_check = NULL; + info->was_per_computer = FALSE; + if (gethostname (hostname, sizeof (hostname)) == 0 && + strcmp (hostname, "localhost") != 0 && + strcmp (hostname, "localhost.localdomain") != 0) + { + + str = g_strdup_printf (_("Make default for this _computer (%s) only"), hostname); + per_computer_check = gtk_check_button_new_with_mnemonic (str); + + /* If we previously set the resolution specifically for this hostname, default + to it on */ + client = gconf_client_get_default (); + key = g_strconcat ("/desktop/gnome/screen/", hostname, "/0/resolution",NULL); + resolution = gconf_client_get_string (client, key, NULL); + g_free (resolution); + g_free (key); + g_object_unref (client); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (per_computer_check), + resolution != NULL); + info->was_per_computer = resolution != NULL; + + gtk_widget_show (per_computer_check); + + wrapped = wrap_in_label (per_computer_check, _("Options")); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + wrapped, FALSE, FALSE, 0); + gtk_widget_show (wrapped); + } + + info->per_computer_check = per_computer_check; + + return dialog; +} + +struct TimeoutData { + int time; + GtkLabel *label; + GtkDialog *dialog; + gboolean timed_out; +}; + +char * +timeout_string (int time) +{ + return g_strdup_printf (_("Testing the new settings. If you don't respond in %d seconds the previous settings will be restored."), time); +} + +gboolean +save_timeout_callback (gpointer _data) +{ + struct TimeoutData *data = _data; + char *str; + + data->time--; + + if (data->time == 0) + { + gtk_dialog_response (data->dialog, GTK_RESPONSE_NO); + data->timed_out = TRUE; + return FALSE; + } + + str = timeout_string (data->time); + gtk_label_set_text (data->label, str); + g_free (str); + + return TRUE; +} + +static int +run_revert_dialog (struct DisplayInfo *info, + GtkWidget *parent) +{ + GtkWidget *dialog; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *label; + GtkWidget *label_sec; + GtkWidget *image; + int res; + struct TimeoutData timeout_data; + guint timeout; + char *str; + + dialog = gtk_dialog_new (); + gtk_window_set_transient_for (GTK_WINDOW (dialog), + GTK_WINDOW (parent)); + gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 12); + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + gtk_window_set_title (GTK_WINDOW (dialog), ""); + + label = gtk_label_new (NULL); + str = g_strdup_printf ("%s", _("Do you want to keep this resolution?")); + gtk_label_set_markup (GTK_LABEL (label), str); + g_free (str); + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0); + + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_label_set_selectable (GTK_LABEL (label), TRUE); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + + str = timeout_string (REVERT_COUNT); + label_sec = gtk_label_new (str); + g_free (str); + gtk_label_set_line_wrap (GTK_LABEL (label_sec), TRUE); + gtk_label_set_selectable (GTK_LABEL (label_sec), TRUE); + gtk_misc_set_alignment (GTK_MISC (label_sec), 0.0, 0.5); + + hbox = gtk_hbox_new (FALSE, 6); + vbox = gtk_vbox_new (FALSE, 6); + + gtk_box_pack_start (GTK_BOX (vbox), label, + TRUE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX (vbox), label_sec, + TRUE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX (hbox), image, + FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (hbox), vbox, + TRUE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + hbox, + FALSE, FALSE, 0); + + gtk_dialog_add_buttons (GTK_DIALOG (dialog), + _("Use _previous resolution"), + GTK_RESPONSE_NO, + _("_Keep resolution"), + GTK_RESPONSE_YES, + NULL); + + gtk_widget_show_all (hbox); + + timeout_data.time = REVERT_COUNT; + timeout_data.label = GTK_LABEL (label_sec); + timeout_data.dialog = GTK_DIALOG (dialog); + timeout_data.timed_out = FALSE; + + timeout = g_timeout_add (1000, + save_timeout_callback, + &timeout_data); + + res = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (!timeout_data.timed_out) + g_source_remove (timeout); + + gtk_widget_destroy (dialog); + + return res == GTK_RESPONSE_YES; +} + +static void +save_to_gconf (struct DisplayInfo *info, gboolean save_computer, gboolean clear_computer) +{ + GConfClient *client; + gboolean res; +#ifdef HOST_NAME_MAX + char hostname[HOST_NAME_MAX + 1]; +#else + char hostname[256]; +#endif + char *path, *key, *str; + int i; + + gethostname (hostname, sizeof(hostname)); + + client = gconf_client_get_default (); + + if (clear_computer) + { + for (i = 0; i < info->n_screens; i++) + { + key = g_strdup_printf ("/desktop/gnome/screen/%s/%d/resolution", + hostname, i); + gconf_client_unset (client, key, NULL); + g_free (key); + key = g_strdup_printf ("/desktop/gnome/screen/%s/%d/rate", + hostname, i); + gconf_client_unset (client, key, NULL); + g_free (key); + } + } + + if (save_computer) + { + path = g_strconcat ("/desktop/gnome/screen/", + hostname, + "/", + NULL); + } + else + path = g_strdup ("/desktop/gnome/screen/default/"); + + for (i = 0; i < info->n_screens; i++) + { + struct ScreenInfo *screen_info = &info->screens[i]; + int new_res, new_rate; + + new_res = get_current_resolution (screen_info); + new_rate = get_current_rate (screen_info); + + key = g_strdup_printf ("%s%d/resolution", path, i); + str = g_strdup_printf ("%dx%d", + screen_info->sizes[new_res].width, + screen_info->sizes[new_res].height); + + res = gconf_client_set_string (client, key, str, NULL); + g_free (str); + g_free (key); + + key = g_strdup_printf ("%s%d/rate", path, i); + res = gconf_client_set_int (client, key, new_rate, NULL); + g_free (key); + } + + g_free (path); + g_object_unref (client); +} + +static void +cb_dialog_response (GtkDialog *dialog, gint response_id, struct DisplayInfo *info) +{ + gboolean save_computer, clear_computer; + + switch (response_id) + { + case GTK_RESPONSE_DELETE_EVENT: + gtk_main_quit (); + break; + case GTK_RESPONSE_HELP: + /* FIXME: This needs to be changed to the right section + * when the docs have been written. */ + capplet_help (GTK_WINDOW (dialog), + "wgoscustdesk.xml", + "goscustdesk-38"); + break; + case GTK_RESPONSE_APPLY: + save_computer = info->per_computer_check != NULL && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (info->per_computer_check)); + clear_computer = !save_computer && info->was_per_computer; + + if (apply_config (info)) + { + if (!run_revert_dialog (info, GTK_WIDGET (dialog))) + { + revert_config (info); + return; + } + } + + save_to_gconf (info, save_computer, clear_computer); + gtk_main_quit (); + break; + } +} + + +int +main (int argc, char *argv[]) +{ + int major, minor; + int event_base, error_base; + GdkDisplay *display; + GtkWidget *dialog; + struct DisplayInfo *info; + Display *xdisplay; + + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + gnome_program_init ("gnome-display-properties", VERSION, + LIBGNOMEUI_MODULE, argc, argv, + GNOME_PARAM_APP_DATADIR, GNOMECC_DATA_DIR, + NULL); + + display = gdk_display_get_default (); + xdisplay = gdk_x11_display_get_xdisplay (display); + + if (!XRRQueryExtension (xdisplay, &event_base, &error_base) || + XRRQueryVersion (xdisplay, &major, &minor) == 0) + { + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("The Xserver doesn't support the XRandR extension, runtime resolution changes aren't possible.")); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + exit (0); + } + + if (major != 1 || minor < 1) + { + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("The version of the XRandR extension is incompatible with this program, runtime resolution changes aren't possible.")); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + exit (0); + } + + info = read_display_info (display); + + dialog = create_dialog (info); + + g_signal_connect (G_OBJECT (dialog), + "response", + G_CALLBACK (cb_dialog_response), info); + + gtk_widget_show (dialog); + + gtk_main (); + + return 0; +} diff --git a/configure.in b/configure.in index ba70e6a40..29fe13b31 100644 --- a/configure.in +++ b/configure.in @@ -47,6 +47,7 @@ AC_SUBST(XF86MISC_LIBS) AC_CHECK_HEADERS(X11/extensions/XKB.h) CPPFLAGS=$savecppflags + dnl ============================================== dnl Check that we meet the dependencies dnl ============================================== @@ -72,7 +73,26 @@ if $PKG_CONFIG --exists xft ; then fi PKG_CHECK_MODULES(FONT_CAPPLET, $COMMON_MODULES $xft_modules) + +dnl +dnl Check for XRandR, needed for display capplet +dnl + +have_randr=no +AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration, + [AC_CHECK_HEADER(X11/extensions/Xrandr.h, + have_randr=yes + RANDR_LIBS="-lXrandr -lXrender" + AC_DEFINE(HAVE_RANDR, 1, Have the Xrandr extension library), + :, [#include ])], : , + -lXrandr -lXrender $x_libs) +AM_CONDITIONAL(HAVE_RANDR, [test $have_randr = yes]) + +PKG_CHECK_MODULES(DISPLAY_CAPPLET, $COMMON_MODULES) +DISPLAY_CAPPLET_LIBS="$DISPLAY_CAPPLET_LIBS $RANDR_LIBS" + + CAPPLET_LIBS="$CAPPLET_LIBS $x_libs" GNOMECC_LIBS="$GNOMECC_LIBS $x_libs" GNOME_SETTINGS_DAEMON_LIBS="$GNOME_SETTINGS_DAEMON_LIBS $x_libs" @@ -168,6 +188,9 @@ AC_SUBST(SOUND_CAPPLET_LIBS) AC_SUBST(FONT_CAPPLET_CFLAGS) AC_SUBST(FONT_CAPPLET_LIBS) +AC_SUBST(DISPLAY_CAPPLET_CFLAGS) +AC_SUBST(DISPLAY_CAPPLET_LIBS) + AC_SUBST(GNOMECC_CFLAGS) AC_SUBST(GNOMECC_LIBS) @@ -249,6 +272,7 @@ capplets/common/Makefile capplets/background/Makefile capplets/default-applications/Makefile capplets/desktop-links/Makefile +capplets/display/Makefile capplets/file-types/Makefile capplets/file-types/libuuid/Makefile capplets/font/Makefile