XRandR integration patch
- From: Alexander Larsson <alexl redhat com>
- To: desktop-devel-list gnome org
- Subject: XRandR integration patch
- Date: Thu, 17 Apr 2003 13:34:17 -0400 (EDT)
Here is a first cut at a XRandR integration patch. The UI needs some
polish, but it seems to work well. The control-center patch adds a capplet
for setting the resolution and refresh rate. The gnome-session patch reads
the settings and sets the resolution on login.
I also want to add a launcher for the capplet from the nautilus desktop
context menu.
Comments?
--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Alexander Larsson Red Hat, Inc
alexl redhat com alla lysator liu se
He's a sword-wielding coffee-fuelled dwarf haunted by an iconic dead American
confidante She's a pregnant psychic archaeologist from a different time and
place. They fight crime!
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-session/configure.in,v
retrieving revision 1.432
diff -u -p -r1.432 configure.in
--- configure.in 26 Mar 2003 05:44:17 -0000 1.432
+++ configure.in 17 Apr 2003 17:21:43 -0000
@@ -120,6 +120,13 @@ if test $pango_omitted_x_deps = yes ; th
fi
fi
+AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
+ [AC_CHECK_HEADER(X11/extensions/Xrandr.h,
+ X_LIBS="-lXrandr -lXrender $X_LIBS"
+ AC_DEFINE(HAVE_RANDR, 1, Have the Xrandr extension library),
+ :, [#include <X11/Xlib.h>])], : ,
+ -lXrandr -lXrender $X_LIBS)
+
AC_SUBST(X_LIBS)
dnl -----------------------------------------------------------
Index: gnome-session/main.c
===================================================================
RCS file: /cvs/gnome/gnome-session/gnome-session/main.c,v
retrieving revision 1.52
diff -u -p -r1.52 main.c
--- gnome-session/main.c 6 Jan 2003 06:33:40 -0000 1.52
+++ gnome-session/main.c 17 Apr 2003 17:21:43 -0000
@@ -35,6 +35,11 @@
#include <libgnomeui/gnome-window-icon.h>
+#ifdef HAVE_RANDR
+#include <gdk/gdkx.h>
+#include <X11/extensions/Xrandr.h>
+#endif
+
#include "manager.h"
#include "ice.h"
#include "save.h"
@@ -233,6 +238,201 @@ gnome_login_check (void)
}
}
+#ifdef HAVE_RANDR
+static gboolean
+get_resolution (GConfClient *client, int screen, char *keys[], int *width, int *height)
+{
+ int i;
+ char *key;
+ char *val;
+ int w, h;
+
+ val = NULL;
+ for (i = 0; keys[i] != NULL; i++)
+ {
+ key = g_strdup_printf ("%s/%d/resolution", keys[i], screen);
+ val = gconf_client_get_string (client, key, NULL);
+ g_free (key);
+
+ if (val != NULL)
+ break;
+ }
+
+ if (val == NULL)
+ return FALSE;
+
+ if (sscanf (val, "%dx%d", &w, &h) != 2)
+ return FALSE;
+
+ *width = w;
+ *height = h;
+
+ return TRUE;
+}
+
+static int
+get_rate (GConfClient *client, int screen, char *keys[])
+{
+ int i;
+ char *key;
+ int val;
+ GError *error;
+
+ for (i = 0; keys[i] != NULL; i++)
+ {
+ key = g_strdup_printf ("%s/%d/rate", keys[i], screen);
+ error = NULL;
+ val = gconf_client_get_int (client, key, &error);
+ g_free (key);
+
+ if (error == NULL)
+ return val;
+
+ g_error_free (error);
+ }
+
+ return 0;
+}
+
+static int
+find_closest_size (XRRScreenSize *sizes, int nsizes, int width, int height)
+{
+ int closest;
+ int closest_width, closest_height;
+ int i;
+
+ closest = 0;
+ closest_width = sizes[0].width;
+ closest_height = sizes[0].height;
+ for (i = 1; i < nsizes; i++)
+ {
+ if (ABS (sizes[i].width - width) < ABS (closest_width - width) ||
+ (sizes[i].width == closest_width &&
+ ABS (sizes[i].height - height) < ABS (closest_height - height)))
+ {
+ closest = i;
+ closest_width = sizes[i].width;
+ closest_height = sizes[i].height;
+ }
+ }
+
+ return closest;
+}
+
+
+#endif
+
+static void
+set_display_properties (void)
+{
+#ifdef HAVE_RANDR
+ GdkDisplay *display;
+ Display *xdisplay;
+ int major, minor;
+ int event_base, error_base;
+ int n_screens;
+ GdkScreen *screen;
+ GdkWindow *root_window;
+ int width, height, rate;
+ GConfClient *client;
+#ifdef HOST_NAME_MAX
+ char hostname[HOST_NAME_MAX + 1];
+#else
+ char hostname[256];
+#endif
+ char *specific_path;
+ char *keys[3];
+ int i;
+
+ display = gdk_display_get_default ();
+ xdisplay = gdk_x11_display_get_xdisplay (display);
+
+ /* Check if XRandR is supported on the display */
+ if (!XRRQueryExtension (xdisplay, &event_base, &error_base) ||
+ XRRQueryVersion (xdisplay, &major, &minor) == 0)
+ return;
+
+ if (major != 1 || minor < 1)
+ {
+ g_message ("Display has unsupported version of XRandR (%d.%d), not setting resolution.", major, minor);
+ return;
+ }
+
+ client = gconf_client_get_default ();
+
+ keys[0] = "/desktop/gnome/screen/default";
+ specific_path = NULL;
+ if (gethostname (hostname, sizeof (hostname)) != 0)
+ specific_path = g_strconcat ("/desktop/gnome/screen/", hostname, NULL);
+ keys[1] = specific_path;
+ keys[2] = NULL;
+
+ n_screens = gdk_display_get_n_screens (display);
+ for (i = 0; i < n_screens; i++)
+ {
+ g_message ("screen %d:\n", i);
+ screen = gdk_display_get_screen (display, i);
+ root_window = gdk_screen_get_root_window (screen);
+
+ if (get_resolution (client, i, keys, &width, &height))
+ {
+ XRRScreenSize *sizes;
+ int nsizes, j;
+ int closest;
+ short *rates;
+ int nrates;
+ int status;
+ int current_size;
+ short current_rate;
+ XRRScreenConfiguration *config;
+ Rotation current_rotation;
+
+ config = XRRGetScreenInfo (xdisplay, gdk_x11_drawable_get_xid (GDK_DRAWABLE (root_window)));
+
+ rate = get_rate (client, i, keys);
+
+ sizes = XRRConfigSizes (config, &nsizes);
+ closest = find_closest_size (sizes, nsizes, width, height);
+
+ rates = XRRConfigRates (config, closest, &nrates);
+ for (j = 0; j < nrates; j++)
+ {
+ if (rates[j] == rate)
+ break;
+ }
+ /* Rate not supported, let X pick */
+ if (j == nrates)
+ rate = 0;
+
+ current_size = XRRConfigCurrentConfiguration (config, ¤t_rotation);
+ current_rate = XRRConfigCurrentRate (config);
+
+ if (closest != current_size ||
+ rate != current_rate)
+ {
+ status = XRRSetScreenConfigAndRate (xdisplay,
+ config,
+ gdk_x11_drawable_get_xid (GDK_DRAWABLE (root_window)),
+ closest,
+ current_rotation,
+ rate,
+ GDK_CURRENT_TIME);
+ }
+ }
+ }
+
+ g_object_unref (client);
+
+ g_free (specific_path);
+
+ /* We need to make sure we process the screen resize event. */
+ gdk_display_sync (display);
+ while (gtk_events_pending ())
+ gtk_main_iteration();
+
+#endif
+}
+
int
main (int argc, char *argv[])
{
@@ -259,6 +459,10 @@ main (int argc, char *argv[])
* gnome yet
*/
gtk_init (&argc, &argv);
+
+ /* We need to do this as early as possible */
+ set_display_properties ();
+
gnome_login_check ();
err = NULL;
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-control-center/configure.in,v
retrieving revision 1.378
diff -u -p -r1.378 configure.in
--- configure.in 21 Mar 2003 10:39:27 -0000 1.378
+++ configure.in 17 Apr 2003 17:16:41 -0000
@@ -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 <X11/Xlib.h>])], : ,
+ -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
Index: capplets/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-control-center/capplets/Makefile.am,v
retrieving revision 1.64
diff -u -p -r1.64 Makefile.am
--- capplets/Makefile.am 8 Aug 2002 07:17:12 -0000 1.64
+++ capplets/Makefile.am 17 Apr 2003 17:16:41 -0000
@@ -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
--- /dev/null 2003-01-30 11:24:37.000000000 +0100
+++ capplets/display/main.c 2003-04-17 18:30:37.000000000 +0200
@@ -0,0 +1,787 @@
+#include <config.h>
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+#include <glade/glade.h>
+#include <gdk/gdkx.h>
+
+#include <X11/extensions/Xrandr.h>
+
+#include "capplet-util.h"
+
+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;
+};
+
+
+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, int nr)
+{
+ GtkWidget *vbox, *hbox;
+ GtkWidget *label;
+ char *str;
+ char *str2;
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ label = 0;
+
+ label = gtk_label_new ("");
+
+ str = g_strdup_printf (_("Screen %d"), nr + 1);
+ str2 = g_strdup_printf ("<b>%s</b>", str);
+ gtk_label_set_markup (GTK_LABEL (label), str2);
+ g_free (str);
+ g_free (str2);
+ 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;
+
+ 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, 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, 0,
+ 0, 0);
+
+ if (no_header)
+ return table;
+ else
+ return wrap_in_label (table, nr);
+}
+
+
+static GtkWidget *
+create_dialog (struct DisplayInfo *info)
+{
+ GtkWidget *dialog;
+ GtkWidget *screen_widget;
+ int i;
+
+ dialog = gtk_dialog_new_with_buttons (_("Change Resolution"),
+ NULL,
+ GTK_DIALOG_NO_SEPARATOR,
+ "gtk-apply",
+ GTK_RESPONSE_APPLY,
+ NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12);
+
+ 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);
+ }
+
+ return dialog;
+}
+
+static void
+default_check_toggled_callback (GtkToggleButton *default_check,
+ GtkWidget *computer_check)
+{
+ if (computer_check)
+ gtk_widget_set_sensitive (computer_check,
+ gtk_toggle_button_get_active (default_check));
+}
+
+struct TimeoutData {
+ int time;
+ GtkLabel *label;
+ GtkDialog *dialog;
+ gboolean timed_out;
+};
+
+char *
+timeout_string (int time)
+{
+ return g_strdup_printf (_("If you don't respond in %d seconds the old 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,
+ gboolean *save,
+ gboolean *save_computer,
+ gboolean *clear_computer)
+{
+ GtkWidget *dialog;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *label_sec;
+ GtkWidget *image;
+ GtkWidget *default_check;
+ GtkWidget *computer_check;
+ gboolean was_computer_specific;
+ int res;
+ struct TimeoutData timeout_data;
+ guint timeout;
+ char *str;
+#ifdef HOST_NAME_MAX
+ char hostname[HOST_NAME_MAX + 1];
+#else
+ char hostname[256];
+#endif
+
+ 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_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Keep resolution?"));
+
+ label = gtk_label_new (_("Testing the new settings. Do you want to keep using this resolution?"));
+ 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 (15);
+ 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);
+
+ default_check = gtk_check_button_new_with_mnemonic (_("Make _default resolution next time you log in"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (default_check),
+ TRUE);
+
+ 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 (vbox), default_check,
+ 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 old resolution"),
+ GTK_RESPONSE_NO,
+ _("Keep resolution"),
+ GTK_RESPONSE_YES,
+ NULL);
+
+ was_computer_specific = FALSE;
+ computer_check = NULL;
+ if (gethostname (hostname, sizeof(hostname)) == 0 &&
+ strcmp (hostname, "localhost") != 0 &&
+ strcmp (hostname, "l") != 0)
+ {
+ GtkWidget *hbox2;
+ GtkWidget *label2;
+ GConfClient *client;
+ char *key;
+ char *resolution;
+
+ str = g_strdup_printf (_("Make default for this _computer (%s) only"), hostname);
+ 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_print ("key: %s was: %s\n", key, resolution);
+ was_computer_specific = resolution != NULL;
+ g_free (resolution);
+ g_free (key);
+ g_object_unref (client);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (computer_check),
+ was_computer_specific);
+
+ hbox2 = gtk_hbox_new (FALSE, 6);
+ label2 = gtk_label_new (" ");
+ gtk_box_pack_start (GTK_BOX (hbox2), label2,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox2), computer_check,
+ TRUE, TRUE, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), hbox2,
+ TRUE, TRUE, 0);
+ }
+
+ gtk_widget_show_all (hbox);
+
+ g_signal_connect (default_check, "toggled", G_CALLBACK (default_check_toggled_callback), computer_check);
+
+ timeout_data.time = 15;
+ 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);
+
+ *save = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (default_check));
+ *save_computer = FALSE;
+ *clear_computer = FALSE;
+ if (computer_check)
+ {
+ *save_computer = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (computer_check));
+ if (was_computer_specific && !*save_computer)
+ *clear_computer = TRUE;
+ }
+
+ 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);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int major, minor;
+ int event_base, error_base;
+ GdkDisplay *display;
+ GtkWidget *dialog;
+ struct DisplayInfo *info;
+ Display *xdisplay;
+ gboolean save, save_computer, clear_computer;
+ int res;
+
+ 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);
+
+ save = FALSE;
+ save_computer = FALSE;
+ while (TRUE)
+ {
+ res = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (res == GTK_RESPONSE_DELETE_EVENT)
+ break;
+
+ if (res == GTK_RESPONSE_APPLY)
+ {
+ if (apply_config (info))
+ {
+ save = FALSE;
+ save_computer = FALSE;
+ if (!run_revert_dialog (info, dialog, &save, &save_computer, &clear_computer))
+ revert_config (info);
+ else
+ break;
+ }
+ else
+ break;
+ }
+ }
+ if (save)
+ save_to_gconf (info, save_computer, clear_computer);
+
+ gtk_widget_destroy (dialog);
+
+ return 0;
+}
--- /dev/null 2003-01-30 11:24:37.000000000 +0100
+++ capplets/display/Makefile.am 2003-04-15 16:54:05.000000000 +0200
@@ -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) $(glade_DATA) $(pixmap_DATA)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]