From d1c4a2797498ef3434cb64e11b7b7f9ae9952d23 Mon Sep 17 00:00:00 2001 From: Jens Granseuer Date: Sun, 18 Nov 2007 13:25:13 +0000 Subject: [PATCH] Patch by: Dan Winship Lucas Rocha 2007-11-18 Jens Granseuer Patch by: Dan Winship Lucas Rocha * Makefile.am: * gnome-settings-daemon.c: (gnome_settings_daemon_init): * gnome-settings-xrandr.c: move display settings here from gnome-session (bug #434982) svn path=/trunk/; revision=8291 --- gnome-settings-daemon/ChangeLog | 10 + gnome-settings-daemon/Makefile.am | 1 + gnome-settings-daemon/gnome-settings-daemon.c | 2 + gnome-settings-daemon/gnome-settings-xrandr.c | 334 ++++++++++++++++++ 4 files changed, 347 insertions(+) create mode 100644 gnome-settings-daemon/gnome-settings-xrandr.c diff --git a/gnome-settings-daemon/ChangeLog b/gnome-settings-daemon/ChangeLog index a155fb788..dc087fff1 100644 --- a/gnome-settings-daemon/ChangeLog +++ b/gnome-settings-daemon/ChangeLog @@ -1,3 +1,13 @@ +2007-11-18 Jens Granseuer + + Patch by: Dan Winship + Lucas Rocha + + * Makefile.am: + * gnome-settings-daemon.c: (gnome_settings_daemon_init): + * gnome-settings-xrandr.c: move display settings here from + gnome-session (bug #434982) + 2007-11-18 Jens Granseuer Patch by: Bastien Nocera diff --git a/gnome-settings-daemon/Makefile.am b/gnome-settings-daemon/Makefile.am index 06b23e360..4861634e7 100644 --- a/gnome-settings-daemon/Makefile.am +++ b/gnome-settings-daemon/Makefile.am @@ -46,6 +46,7 @@ gnome_settings_daemon_SOURCES = \ gnome-settings-typing-break.c \ gnome-settings-xmodmap.c \ gnome-settings-xmodmap.h \ + gnome-settings-xrandr.c \ gnome-settings-xrdb.c \ gnome-settings-xsettings.c \ gsd-media-keys-window.c \ diff --git a/gnome-settings-daemon/gnome-settings-daemon.c b/gnome-settings-daemon/gnome-settings-daemon.c index 2a6dc4a61..6b930fc69 100644 --- a/gnome-settings-daemon/gnome-settings-daemon.c +++ b/gnome-settings-daemon/gnome-settings-daemon.c @@ -42,6 +42,7 @@ GType gnome_settings_module_accessibility_keyboard_get_type (void); GType gnome_settings_module_background_get_type (void); GType gnome_settings_module_clipboard_get_type (void); GType gnome_settings_module_default_editor_get_type (void); +GType gnome_settings_module_xrandr_get_type (void); GType gnome_settings_module_font_get_type (void); GType gnome_settings_module_gtk1_get_type (void); GType gnome_settings_module_keybindings_get_type (void); @@ -185,6 +186,7 @@ gnome_settings_daemon_init (GnomeSettingsDaemon *settings) || !gnome_settings_module_background_get_type () || !gnome_settings_module_clipboard_get_type () || !gnome_settings_module_default_editor_get_type () + || !gnome_settings_module_xrandr_get_type () || !gnome_settings_module_font_get_type () || !gnome_settings_module_gtk1_get_type () || !gnome_settings_module_keybindings_get_type () diff --git a/gnome-settings-daemon/gnome-settings-xrandr.c b/gnome-settings-daemon/gnome-settings-xrandr.c new file mode 100644 index 000000000..92590c03d --- /dev/null +++ b/gnome-settings-daemon/gnome-settings-xrandr.c @@ -0,0 +1,334 @@ +/* -*- mode: c; style: linux -*- */ + +/* gnome-settings-display.c + * + * Most of this code comes from the old gnome-session/gsm-xrandr.c. + * + * Copyright (C) 2003 Red Hat, Inc. + * Copyright (C) 2007 Novell, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * 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 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_RANDR +#include +#include +#include +#include +#include +#include +#endif + +#include "gnome-settings-module.h" + +typedef struct { + GnomeSettingsModule parent; +} GnomeSettingsModuleDisplay; + +typedef struct { + GnomeSettingsModuleClass parent_class; +} GnomeSettingsModuleDisplayClass; + +static GnomeSettingsModuleRunlevel gnome_settings_module_xrandr_get_runlevel (GnomeSettingsModule *module); +static gboolean gnome_settings_module_xrandr_initialize (GnomeSettingsModule *module, GConfClient *config_client); +static gboolean gnome_settings_module_xrandr_start (GnomeSettingsModule *module); +static gboolean gnome_settings_module_xrandr_stop (GnomeSettingsModule *module); + +static void +gnome_settings_module_xrandr_class_init (GnomeSettingsModuleDisplayClass *klass) +{ + GnomeSettingsModuleClass *module_class; + + module_class = (GnomeSettingsModuleClass *) klass; + module_class->get_runlevel = gnome_settings_module_xrandr_get_runlevel; + module_class->initialize = gnome_settings_module_xrandr_initialize; + module_class->start = gnome_settings_module_xrandr_start; + module_class->stop = gnome_settings_module_xrandr_stop; +} + +static void +gnome_settings_module_xrandr_init (GnomeSettingsModuleDisplay *module) +{ +} + +GType +gnome_settings_module_xrandr_get_type (void) +{ + static GType module_type = 0; + + if (!module_type) { + const GTypeInfo module_info = { + sizeof (GnomeSettingsModuleDisplayClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gnome_settings_module_xrandr_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GnomeSettingsModuleDisplay), + 0, /* n_preallocs */ + (GInstanceInitFunc) gnome_settings_module_xrandr_init, + }; + + module_type = g_type_register_static (GNOME_SETTINGS_TYPE_MODULE, + "GnomeSettingsModuleDisplay", + &module_info, 0); + } + + return module_type; +} + +static GnomeSettingsModuleRunlevel +gnome_settings_module_xrandr_get_runlevel (GnomeSettingsModule *module) +{ + return GNOME_SETTINGS_MODULE_RUNLEVEL_XSETTINGS; +} + +#ifdef HAVE_RANDR +static int +get_rotation (GConfClient *client, char *display, int screen) +{ + char *key; + int val; + GError *error = NULL; + + key = g_strdup_printf ("%s/%d/rotation", display, screen); + val = gconf_client_get_int (client, key, &error); + g_free (key); + + if (error == NULL) + return val; + + g_error_free (error); + + return 0; +} + +static int +get_resolution (GConfClient *gconf, 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 (gconf, key, NULL); + g_free (key); + + if (val != NULL) + break; + } + + if (val == NULL) + return -1; + + if (sscanf (val, "%dx%d", &w, &h) != 2) { + g_free (val); + return -1; + } + + g_free (val); + + *width = w; + *height = h; + + return i; +} + +static int +get_rate (GConfClient *gconf, char *display, int screen) +{ + char *key; + int val; + GError *error = NULL; + + key = g_strdup_printf ("%s/%d/rate", display, screen); + val = gconf_client_get_int (gconf, 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 /* HAVE_RANDR */ + +static void +apply_settings (GnomeSettingsModule *module) +{ +#ifdef HAVE_RANDR + GdkDisplay *display; + Display *xdisplay; + int major, minor; + int event_base, error_base; + GConfClient *gconf; + int n_screens; + GdkScreen *screen; + GdkWindow *root_window; + int width, height, rate, rotation; +#ifdef HOST_NAME_MAX + char hostname[HOST_NAME_MAX + 1]; +#else + char hostname[256]; +#endif + char *specific_path; + char *keys[3]; + int i, residx; + + 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; + } + + gconf = gnome_settings_module_get_config_client (module); + + i = 0; + specific_path = NULL; + if (gethostname (hostname, sizeof (hostname)) == 0) { + specific_path = g_strconcat ("/desktop/gnome/screen/", hostname, NULL); + keys[i++] = specific_path; + } + keys[i++] = "/desktop/gnome/screen/default"; + keys[i++] = NULL; + + n_screens = gdk_display_get_n_screens (display); + for (i = 0; i < n_screens; i++) { + screen = gdk_display_get_screen (display, i); + root_window = gdk_screen_get_root_window (screen); + residx = get_resolution (gconf, i, keys, &width, &height); + + if (residx != -1) { + 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 (gconf, keys[residx], i); + + 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; + + rotation = get_rotation (gconf, keys[residx], i); + if (rotation == 0) + rotation = RR_Rotate_0; + + current_size = XRRConfigCurrentConfiguration (config, ¤t_rotation); + current_rate = XRRConfigCurrentRate (config); + + if (closest != current_size || + rate != current_rate || + rotation != current_rotation) { + status = XRRSetScreenConfigAndRate (xdisplay, + config, + gdk_x11_drawable_get_xid (GDK_DRAWABLE (root_window)), + closest, + (Rotation) rotation, + rate, + GDK_CURRENT_TIME); + } + + XRRFreeScreenConfigInfo (config); + } + } + + 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 /* HAVE_RANDR */ +} + +static gboolean +gnome_settings_module_xrandr_initialize (GnomeSettingsModule *module, GConfClient *config_client) +{ + return TRUE; +} + +static gboolean +gnome_settings_module_xrandr_start (GnomeSettingsModule *module) +{ + apply_settings (module); + + return TRUE; +} + +static gboolean +gnome_settings_module_xrandr_stop (GnomeSettingsModule *module) +{ + return TRUE; +}