338db4d
diff -up gnome-settings-daemon-2.23.1.1/plugins/xrandr/gsd-xrandr-manager.c.add-randr-12 gnome-settings-daemon-2.23.1.1/plugins/xrandr/gsd-xrandr-manager.c
338db4d
--- gnome-settings-daemon-2.23.1.1/plugins/xrandr/gsd-xrandr-manager.c.add-randr-12	2008-04-23 06:38:37.000000000 -0400
338db4d
+++ gnome-settings-daemon-2.23.1.1/plugins/xrandr/gsd-xrandr-manager.c	2008-04-26 14:57:00.000000000 -0400
338db4d
@@ -35,7 +35,10 @@
54d84ec
 #include <gdk/gdk.h>
a7325d2
 #include <gdk/gdkx.h>
a7325d2
 #include <gtk/gtk.h>
54d84ec
-#include <gconf/gconf-client.h>
54d84ec
+
a7325d2
+#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA
a7325d2
+#include <libgnomeui/monitor-db.h>
a7325d2
+#include <libgnomeui/randrwrap.h>
54d84ec
 
a7325d2
 #ifdef HAVE_RANDR
a7325d2
 #include <X11/extensions/Xrandr.h>
338db4d
@@ -48,6 +51,22 @@
338db4d
 #define HOST_NAME_MAX   255
e24287c
 #endif
e24287c
 
54d84ec
+#define GSD_XRANDR_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_XRANDR_MANAGER, GsdXrandrManagerPrivate))
54d84ec
+
2946d2f
+#define VIDEO_KEYSYM    "XF86Display"
2946d2f
+
54d84ec
+struct GsdXrandrManagerPrivate
54d84ec
+{
338db4d
+	/* Key code of the fn-F7 video key (XF86Display) */
338db4d
+	guint keycode;
338db4d
+	RWScreen *rw_screen;
338db4d
+	gboolean running;
54d84ec
+};
338db4d
+ 
54d84ec
+enum {
338db4d
+	PROP_0,
54d84ec
+};
54d84ec
+
54d84ec
 static void     gsd_xrandr_manager_class_init  (GsdXrandrManagerClass *klass);
54d84ec
 static void     gsd_xrandr_manager_init        (GsdXrandrManager      *xrandr_manager);
54d84ec
 static void     gsd_xrandr_manager_finalize    (GObject             *object);
338db4d
@@ -56,248 +75,74 @@ G_DEFINE_TYPE (GsdXrandrManager, gsd_xra
a7325d2
 
a7325d2
 static gpointer manager_object = NULL;
a7325d2
 
a7325d2
-#ifdef HAVE_RANDR
a7325d2
-static int
a7325d2
-get_rotation (GConfClient *client,
a7325d2
-              char        *display,
a7325d2
-              int          screen)
a7325d2
-{
a7325d2
-        char   *key;
a7325d2
-        int     val;
a7325d2
-        GError *error;
a7325d2
-
a7325d2
-        key = g_strdup_printf ("%s/%d/rotation", display, screen);
a7325d2
-        error = NULL;
a7325d2
-        val = gconf_client_get_int (client, key, &error);
a7325d2
-        g_free (key);
a7325d2
-
a7325d2
-        if (error == NULL) {
a7325d2
-                return val;
a7325d2
-        }
a7325d2
-
a7325d2
-        g_error_free (error);
a7325d2
-
a7325d2
-        return 0;
2946d2f
+static GdkAtom
2946d2f
+gnome_randr_atom (void)
2946d2f
+{
338db4d
+	return gdk_atom_intern ("_GNOME_RANDR_ATOM", FALSE);
2946d2f
 }
2946d2f
 
a7325d2
-static int
a7325d2
-get_resolution (GConfClient *client,
a7325d2
-                int          screen,
a7325d2
-                char        *keys[],
a7325d2
-                int         *width,
a7325d2
-                int         *height)
a7325d2
-{
a7325d2
-        int   i;
a7325d2
-        char *key;
a7325d2
-        char *val;
a7325d2
-        int   w;
a7325d2
-        int   h;
a7325d2
-
a7325d2
-        val = NULL;
a7325d2
-        for (i = 0; keys[i] != NULL; i++) {
a7325d2
-                key = g_strdup_printf ("%s/%d/resolution", keys[i], screen);
a7325d2
-                val = gconf_client_get_string (client, key, NULL);
a7325d2
-                g_free (key);
a7325d2
-
a7325d2
-                if (val != NULL) {
a7325d2
-                        break;
a7325d2
-                }
a7325d2
-        }
a7325d2
-
a7325d2
-        if (val == NULL) {
a7325d2
-                return -1;
a7325d2
-        }
e24287c
+static Atom
e24287c
+gnome_randr_xatom (void)
e24287c
+{
338db4d
+	return gdk_x11_atom_to_xatom (gnome_randr_atom());
e24287c
+}
e24287c
 
a7325d2
-        if (sscanf (val, "%dx%d", &w, &h) != 2) {
a7325d2
-                g_free (val);
a7325d2
-                return -1;
338db4d
-        }
e24287c
+static GdkFilterReturn
e24287c
+on_client_message (GdkXEvent  *xevent,
e24287c
+		   GdkEvent   *event,
e24287c
+		   gpointer    data)
e24287c
+{
338db4d
+	RWScreen *screen = data;
338db4d
+	XEvent *ev = (XEvent *)xevent;
338db4d
+         
338db4d
+	if (ev->type == ClientMessage         &&
338db4d
+	    ev->xclient.message_type == gnome_randr_xatom()) {
338db4d
 
a7325d2
-        g_free (val);
338db4d
+		configuration_apply_stored (screen);
338db4d
 
a7325d2
-        *width = w;
a7325d2
-        *height = h;
338db4d
+		return GDK_FILTER_REMOVE;
338db4d
+	}
338db4d
 
a7325d2
-        return i;
338db4d
+	/* Pass the event on to GTK+ */
338db4d
+	return GDK_FILTER_CONTINUE;
a7325d2
 }
a7325d2
 
a7325d2
-static int
a7325d2
-get_rate (GConfClient *client,
a7325d2
-          char        *display,
a7325d2
-          int          screen)
2946d2f
+static GdkFilterReturn
e24287c
+event_filter (GdkXEvent           *xevent,
338db4d
+	      GdkEvent            *event,
338db4d
+	      gpointer             data)
a7325d2
 {
a7325d2
-        char   *key;
a7325d2
-        int     val;
a7325d2
-        GError *error;
338db4d
+	GsdXrandrManager *manager = data;
338db4d
+	XEvent *xev = (XEvent *) xevent;
54d84ec
 
a7325d2
-        key = g_strdup_printf ("%s/%d/rate", display, screen);
a7325d2
-        error = NULL;
a7325d2
-        val = gconf_client_get_int (client, key, &error);
a7325d2
-        g_free (key);
338db4d
+	if (!manager->priv->running)
338db4d
+		return GDK_FILTER_CONTINUE;
2946d2f
 
a7325d2
-        if (error == NULL) {
a7325d2
-                return val;
a7325d2
-        }
338db4d
+	/* verify we have a key event */
338db4d
+	if (xev->xany.type != KeyPress && xev->xany.type != KeyRelease)
338db4d
+		return GDK_FILTER_CONTINUE;
338db4d
 
54d84ec
-        g_error_free (error);
338db4d
+	if (xev->xkey.keycode == manager->priv->keycode) {
338db4d
+		/* FIXME: here we should cycle between valid
338db4d
+		 * configurations, and save them
338db4d
+		 */
338db4d
+		configuration_apply_stored (manager->priv->rw_screen);
a7325d2
 
54d84ec
-        return 0;
54d84ec
-}
54d84ec
-
a7325d2
-static int
a7325d2
-find_closest_size (XRRScreenSize *sizes,
a7325d2
-                   int            nsizes,
a7325d2
-                   int            width,
a7325d2
-                   int            height)
a7325d2
-{
a7325d2
-        int closest;
a7325d2
-        int closest_width;
a7325d2
-        int closest_height;
a7325d2
-        int i;
a7325d2
-
a7325d2
-        closest = 0;
a7325d2
-        closest_width = sizes[0].width;
a7325d2
-        closest_height = sizes[0].height;
a7325d2
-        for (i = 1; i < nsizes; i++) {
a7325d2
-                if (ABS (sizes[i].width - width) < ABS (closest_width - width) ||
a7325d2
-                    (sizes[i].width == closest_width &&
a7325d2
-                     ABS (sizes[i].height - height) < ABS (closest_height - height))) {
a7325d2
-                        closest = i;
a7325d2
-                        closest_width = sizes[i].width;
a7325d2
-                        closest_height = sizes[i].height;
a7325d2
-                }
338db4d
-        }
338db4d
+		return GDK_FILTER_CONTINUE;
338db4d
+	}
2946d2f
 
a7325d2
-        return closest;
338db4d
+	return GDK_FILTER_CONTINUE;
a7325d2
 }
a7325d2
-#endif /* HAVE_RANDR */
a7325d2
 
e24287c
 static void
a7325d2
-apply_settings (GsdXrandrManager *manager)
e24287c
+on_randr_event (RWScreen *screen, gpointer data)
a7325d2
 {
a7325d2
-#ifdef HAVE_RANDR
a7325d2
-        GdkDisplay  *display;
a7325d2
-        Display     *xdisplay;
a7325d2
-        int          major;
a7325d2
-        int          minor;
a7325d2
-        int          event_base;
a7325d2
-        int          error_base;
a7325d2
-        GConfClient *client;
a7325d2
-        int          n_screens;
a7325d2
-        GdkScreen   *screen;
a7325d2
-        GdkWindow   *root_window;
a7325d2
-        int          width;
a7325d2
-        int          height;
a7325d2
-        int          rate;
a7325d2
-        int          rotation;
a7325d2
-        char         hostname[HOST_NAME_MAX + 1];
a7325d2
-        char        *specific_path;
a7325d2
-        char        *keys[3];
a7325d2
-        int          i;
a7325d2
-        int          residx;
a7325d2
-
William Jon McCann 6c32b09
-        gnome_settings_profile_start (NULL);
William Jon McCann 6c32b09
-
a7325d2
-        display = gdk_display_get_default ();
a7325d2
-        xdisplay = gdk_x11_display_get_xdisplay (display);
a7325d2
-
a7325d2
-        /* Check if XRandR is supported on the display */
a7325d2
-        if (!XRRQueryExtension (xdisplay, &event_base, &error_base)
a7325d2
-            || XRRQueryVersion (xdisplay, &major, &minor) == 0) {
William Jon McCann 6c32b09
-                goto out;
a7325d2
-        }
William Jon McCann 6c32b09
-
a7325d2
-        if (major != 1 || minor < 1) {
a7325d2
-                g_message ("Display has unsupported version of XRandR (%d.%d), not setting resolution.", major, minor);
William Jon McCann 6c32b09
-                goto out;
a7325d2
-        }
e24287c
-
a7325d2
-        client = gconf_client_get_default ();
e24287c
-
a7325d2
-        i = 0;
a7325d2
-        specific_path = NULL;
a7325d2
-        if (gethostname (hostname, sizeof (hostname)) == 0) {
a7325d2
-                specific_path = g_strconcat ("/desktop/gnome/screen/", hostname,  NULL);
a7325d2
-                keys[i++] = specific_path;
a7325d2
-        }
a7325d2
-        keys[i++] = "/desktop/gnome/screen/default";
a7325d2
-        keys[i++] = NULL;
e24287c
-
a7325d2
-        n_screens = gdk_display_get_n_screens (display);
a7325d2
-        for (i = 0; i < n_screens; i++) {
a7325d2
-                screen = gdk_display_get_screen (display, i);
a7325d2
-                root_window = gdk_screen_get_root_window (screen);
a7325d2
-                residx = get_resolution (client, i, keys, &width, &height);
a7325d2
-
a7325d2
-                if (residx != -1) {
a7325d2
-                        XRRScreenSize          *sizes;
a7325d2
-                        int                     nsizes;
a7325d2
-                        int                     j;
a7325d2
-                        int                     closest;
a7325d2
-                        short                  *rates;
a7325d2
-                        int                     nrates;
a7325d2
-                        int                     status;
a7325d2
-                        int                     current_size;
a7325d2
-                        short                   current_rate;
a7325d2
-                        XRRScreenConfiguration *config;
a7325d2
-                        Rotation                current_rotation;
a7325d2
-
a7325d2
-                        config = XRRGetScreenInfo (xdisplay, gdk_x11_drawable_get_xid (GDK_DRAWABLE (root_window)));
a7325d2
-
a7325d2
-                        rate = get_rate (client, keys[residx], i);
a7325d2
-
a7325d2
-                        sizes = XRRConfigSizes (config, &nsizes);
a7325d2
-                        closest = find_closest_size (sizes, nsizes, width, height);
a7325d2
-
a7325d2
-                        rates = XRRConfigRates (config, closest, &nrates);
a7325d2
-                        for (j = 0; j < nrates; j++) {
a7325d2
-                                if (rates[j] == rate)
a7325d2
-                                        break;
a7325d2
-                        }
a7325d2
-
a7325d2
-                        /* Rate not supported, let X pick */
a7325d2
-                        if (j == nrates)
a7325d2
-                                rate = 0;
a7325d2
-
a7325d2
-                        rotation = get_rotation (client, keys[residx], i);
a7325d2
-                        if (rotation == 0)
a7325d2
-                                rotation = RR_Rotate_0;
a7325d2
-
a7325d2
-                        current_size = XRRConfigCurrentConfiguration (config, &current_rotation);
a7325d2
-                        current_rate = XRRConfigCurrentRate (config);
a7325d2
-
a7325d2
-                        if (closest != current_size ||
a7325d2
-                            rate != current_rate ||
a7325d2
-                            rotation != current_rotation) {
a7325d2
-                                status = XRRSetScreenConfigAndRate (xdisplay,
a7325d2
-                                                                    config,
a7325d2
-                                                                    gdk_x11_drawable_get_xid (GDK_DRAWABLE (root_window)),
a7325d2
-                                                                    closest,
a7325d2
-                                                                    (Rotation) rotation,
a7325d2
-                                                                    rate,
a7325d2
-                                                                    GDK_CURRENT_TIME);
a7325d2
-                        }
e24287c
-
a7325d2
-                        XRRFreeScreenConfigInfo (config);
a7325d2
-                }
e24287c
-        }
a7325d2
-
338db4d
-        g_free (specific_path);
338db4d
+	GsdXrandrManager *manager = data;
338db4d
 
a7325d2
-        /* We need to make sure we process the screen resize event. */
a7325d2
-        gdk_display_sync (display);
e24287c
-
a7325d2
-        while (gtk_events_pending ()) {
a7325d2
-                gtk_main_iteration ();
a7325d2
-        }
e24287c
-
a7325d2
-        if (client != NULL) {
a7325d2
-                g_object_unref (client);
a7325d2
-        }
William Jon McCann 6c32b09
- out:
William Jon McCann 6c32b09
-        gnome_settings_profile_end (NULL);
e24287c
-
e24287c
-#endif /* HAVE_RANDR */
338db4d
+	if (!manager->priv->running)
338db4d
+		return;
e24287c
+        
338db4d
+	/* FIXME: Set up any new screens here */
a7325d2
 }
a7325d2
 
a7325d2
 gboolean
338db4d
@@ -306,8 +151,30 @@ gsd_xrandr_manager_start (GsdXrandrManag
a7325d2
 {
a7325d2
         g_debug ("Starting xrandr manager");
a7325d2
 
a7325d2
-        apply_settings (manager);
e24287c
-
2946d2f
+        manager->priv->running = TRUE;
e24287c
+        
2946d2f
+        if (manager->priv->keycode) {
e24287c
+                gdk_error_trap_push ();
e24287c
+                
2946d2f
+                XGrabKey (gdk_x11_get_default_xdisplay(),
2946d2f
+                          manager->priv->keycode, AnyModifier,
2946d2f
+                          gdk_x11_get_default_root_xwindow(),
2946d2f
+                          True, GrabModeAsync, GrabModeAsync);
William Jon McCann 6c32b09
+
e24287c
+                gdk_flush ();
e24287c
+                gdk_error_trap_pop ();
e24287c
+        }
e24287c
+        
2946d2f
+        configuration_apply_stored (manager->priv->rw_screen);
e24287c
+        
2946d2f
+        gdk_window_add_filter (gdk_get_default_root_window(),
2946d2f
+                               (GdkFilterFunc)event_filter,
2946d2f
+                               manager);
e24287c
+        
a7325d2
+        gdk_add_client_message_filter (gnome_randr_atom(),
a7325d2
+                                       on_client_message,
2946d2f
+                                       manager->priv->rw_screen);
e24287c
+        
a7325d2
         return TRUE;
a7325d2
 }
e24287c
 
338db4d
@@ -315,6 +182,16 @@ void
2946d2f
 gsd_xrandr_manager_stop (GsdXrandrManager *manager)
2946d2f
 {
2946d2f
         g_debug ("Stopping xrandr manager");
2946d2f
+
2946d2f
+        manager->priv->running = FALSE;
e24287c
+        
e24287c
+        gdk_error_trap_push ();
e24287c
+        
2946d2f
+        XUngrabKey (gdk_x11_get_default_xdisplay(),
2946d2f
+                    manager->priv->keycode, AnyModifier,
2946d2f
+                    gdk_x11_get_default_root_xwindow());
e24287c
+
e24287c
+        gdk_error_trap_pop ();
2946d2f
 }
2946d2f
 
2946d2f
 static void
338db4d
@@ -388,11 +265,22 @@ gsd_xrandr_manager_class_init (GsdXrandr
54d84ec
         object_class->constructor = gsd_xrandr_manager_constructor;
54d84ec
         object_class->dispose = gsd_xrandr_manager_dispose;
54d84ec
         object_class->finalize = gsd_xrandr_manager_finalize;
54d84ec
+
54d84ec
+        g_type_class_add_private (klass, sizeof (GsdXrandrManagerPrivate));
54d84ec
 }
54d84ec
 
2946d2f
 static void
2946d2f
 gsd_xrandr_manager_init (GsdXrandrManager *manager)
2946d2f
 {
2946d2f
+        Display *dpy = gdk_x11_get_default_xdisplay ();
2946d2f
+        guint keyval = gdk_keyval_from_name (VIDEO_KEYSYM);
2946d2f
+        guint keycode = XKeysymToKeycode (dpy, keyval);
e24287c
+        
54d84ec
+        manager->priv = GSD_XRANDR_MANAGER_GET_PRIVATE (manager);
54d84ec
+
2946d2f
+        manager->priv->keycode = keycode;
2946d2f
+        manager->priv->rw_screen = rw_screen_new (
2946d2f
+                gdk_screen_get_default(), on_randr_event, NULL);
2946d2f
 }
2946d2f
 
2946d2f
 static void
338db4d
@@ -405,6 +293,8 @@ gsd_xrandr_manager_finalize (GObject *ob
54d84ec
 
54d84ec
         xrandr_manager = GSD_XRANDR_MANAGER (object);
54d84ec
 
54d84ec
+        g_return_if_fail (xrandr_manager->priv != NULL);
54d84ec
+
54d84ec
         G_OBJECT_CLASS (gsd_xrandr_manager_parent_class)->finalize (object);
54d84ec
 }
54d84ec