Index: gnome-settings-daemon-2.28.2/plugins/xrandr/gsd-xrandr-manager.c
===================================================================
--- gnome-settings-daemon-2.28.2.orig/plugins/xrandr/gsd-xrandr-manager.c
+++ gnome-settings-daemon-2.28.2/plugins/xrandr/gsd-xrandr-manager.c
@@ -57,6 +57,7 @@
 
 #include "gnome-settings-profile.h"
 #include "gsd-xrandr-manager.h"
+#include "gsd-xrandr-window.h"
 
 #ifndef HOST_NAME_MAX
 #define HOST_NAME_MAX   255
@@ -67,6 +68,7 @@
 #define CONF_DIR "/apps/gnome_settings_daemon/xrandr"
 #define CONF_KEY_SHOW_NOTIFICATION_ICON		(CONF_DIR "/show_notification_icon")
 #define CONF_KEY_ROTATE_TABLET_WITH_MONITOR	(CONF_DIR "/rotate_tablet_with_monitor")
+#define CONF_KEY_WHEEL_SELECT_OSD		(CONF_DIR "/wheel_select_osd")
 
 #define VIDEO_KEYSYM    "XF86Display"
 #define ROTATE_KEYSYM   "XF86RotateWindows"
@@ -131,6 +133,13 @@ struct GsdXrandrManagerPrivate
 
         /* Last time at which we got a "screen got reconfigured" event; see on_randr_event() */
         guint32 last_config_timestamp;
+
+	/* OSD select mode stuff */
+	GtkWidget	*dialog;
+        GdkScreen       *current_screen;
+        GSList          *screens;
+	guint32		 xkey_time;
+        int		 next_stock_config;             /* -1 if no configs */
 };
 
 static const GnomeRRRotation possible_rotations[] = {
@@ -165,6 +174,26 @@ static FILE *log_file;
 #define NTH_STOCK_CONFIG(array, n) ((StockConfig *) array->pdata[n])
 
 static void
+init_screens (GsdXrandrManager *manager)
+{
+        GdkDisplay *display;
+        int i;
+
+        display = gdk_display_get_default ();
+        for (i = 0; i < gdk_display_get_n_screens (display); i++) {
+                GdkScreen *screen;
+
+                screen = gdk_display_get_screen (display, i);
+                if (screen == NULL) {
+                        continue;
+                }
+                manager->priv->screens = g_slist_append (manager->priv->screens, screen);
+        }
+
+        manager->priv->current_screen = manager->priv->screens->data;
+}
+
+static void
 log_open (void)
 {
         char *toggle_filename;
@@ -301,7 +330,7 @@ log_configurations (StockConfig **config
 
         for (i = 0; configs[i]; i++) {
                 log_msg ("    Configuration %d\n", i);
-                log_configuration (configs[i]);
+                log_configuration (configs[i]->rr_config);
         }
 }
 
@@ -1207,6 +1236,10 @@ sanitize (GsdXrandrManager *manager, GPt
                         GnomeRRConfig *other        = other_config ? other_config->rr_config : NULL;
 
                         if (this && other && gnome_rr_config_equal (this, other)) {
+				/* set real type enum to current config*/
+				if (other_config->type == STOCK_CONFIG_CURRENT)
+					other_config->type = this_config->type;
+
                                 g_debug ("removing duplicate configuration");
                                 stock_config_free (this_config);
                                 array->pdata[j] = NULL;
@@ -1299,6 +1332,7 @@ generate_stock_configs (GsdXrandrManager
 
 		mgr->priv->stock_configs = NULL;
 		mgr->priv->current_stock_config = -1;
+		mgr->priv->next_stock_config = -1;
         }
 
         if (have_non_laptop(screen))
@@ -1315,6 +1349,7 @@ generate_stock_configs (GsdXrandrManager
         if (array) {
 		mgr->priv->stock_configs = (StockConfig **) g_ptr_array_free (array, FALSE);
 		mgr->priv->current_stock_config = 0;
+		mgr->priv->next_stock_config = 0;
         }
 }
 
@@ -1353,6 +1388,162 @@ error_message (GsdXrandrManager *mgr, co
 }
 
 static void
+handle_stock_config_hotkey_cb (GsdXrandrManager *mgr, guint32 timestamp)
+{
+        GsdXrandrManagerPrivate *priv = mgr->priv;
+        GnomeRRScreen *screen = priv->rw_screen;
+        GError *error;
+
+        g_debug ("Handling XF86Display Call Back");
+
+        gdk_error_trap_push (); /* avoid BadMatch error */
+
+        log_open ();
+        log_msg ("Handling XF86Display hotkey - timestamp %u\n", timestamp);
+
+        error = NULL;
+	if (priv->stock_configs) {
+                guint32 server_timestamp;
+
+                if (!have_non_laptop(screen) || priv->stock_configs[mgr->priv->next_stock_config] == NULL)
+                        mgr->priv->next_stock_config = 0;
+
+                g_debug ("current configuration (%d)", mgr->priv->current_stock_config);
+                g_debug ("next configuration (%d) applying", mgr->priv->next_stock_config);
+
+                /* See https://bugzilla.gnome.org/show_bug.cgi?id=610482
+                 *
+                 * Sometimes we'll get two rapid XF86Display keypress events,
+                 * but their timestamps will be out of order with respect to the
+                 * RANDR timestamps.  This *may* be due to stupid BIOSes sending
+                 * out display-switch keystrokes "to make Windows work".
+                 *
+                 * The X server will error out if the timestamp provided is
+                 * older than a previous change configuration timestamp. We
+                 * assume here that we do want this event to go through still,
+                 * since kernel timestamps may be skewed wrt the X server.
+                 */
+                gnome_rr_screen_get_timestamps (screen, NULL, &server_timestamp);
+                if (timestamp < server_timestamp)
+                        timestamp = server_timestamp;
+
+		if (!gnome_rr_config_apply_with_time (priv->stock_configs[mgr->priv->next_stock_config]->rr_config, screen, timestamp, &error)) {
+			mgr->priv->next_stock_config = mgr->priv->current_stock_config;
+                          error_message (mgr, _("Could not switch the monitor configuration"), error, NULL);
+                          g_error_free (error);
+		} else {
+			mgr->priv->current_stock_config = mgr->priv->next_stock_config;
+		}
+        }
+        else {
+                g_debug ("no configurations for apply");
+        }
+
+        log_close ();
+
+        gdk_flush ();
+        gdk_error_trap_pop ();
+
+	g_debug ("done handling XF86Display Call Back");
+}
+
+static void
+_dialog_hide_cb (GtkWidget           *dialog,
+                 GsdXrandrManager *manager)
+{
+        g_debug ("got dialog hide cb");
+
+        if (gconf_client_get_bool (manager->priv->client, CONF_KEY_WHEEL_SELECT_OSD, NULL))	//TODO
+		handle_stock_config_hotkey_cb (manager, manager->priv->xkey_time);
+}
+
+static void
+dialog_init (GsdXrandrManager *manager)
+{
+        if (manager->priv->dialog != NULL
+            && !gsd_xrandr_window_is_valid (GSD_XRANDR_WINDOW (manager->priv->dialog))) {
+                gtk_widget_destroy (manager->priv->dialog);
+                manager->priv->dialog = NULL;
+        }
+
+        if (manager->priv->dialog == NULL) {
+                manager->priv->dialog = gsd_xrandr_window_new ();
+                g_signal_connect (GSD_XRANDR_WINDOW (manager->priv->dialog),
+                                  "hide-timeout",
+                                  (GCallback)_dialog_hide_cb,
+                                  manager);
+        }
+}
+
+static void
+dialog_show (GsdXrandrManager *manager)
+{
+        int            orig_w;
+        int            orig_h;
+        int            screen_w;
+        int            screen_h;
+        int            x;
+        int            y;
+        int            pointer_x;
+        int            pointer_y;
+        GtkRequisition win_req;
+        GdkScreen     *pointer_screen;
+        GdkRectangle   geometry;
+        int            monitor;
+
+        gtk_window_set_screen (GTK_WINDOW (manager->priv->dialog),
+                               manager->priv->current_screen);
+
+        /*
+         * get the window size
+         * if the window hasn't been mapped, it doesn't necessarily
+         * know its true size, yet, so we need to jump through hoops
+         */
+        gtk_window_get_default_size (GTK_WINDOW (manager->priv->dialog), &orig_w, &orig_h);
+        gtk_widget_size_request (manager->priv->dialog, &win_req);
+
+        if (win_req.width > orig_w) {
+                orig_w = win_req.width;
+        }
+        if (win_req.height > orig_h) {
+                orig_h = win_req.height;
+        }
+
+        pointer_screen = NULL;
+        gdk_display_get_pointer (gdk_screen_get_display (manager->priv->current_screen),
+                                 &pointer_screen,
+                                 &pointer_x,
+                                 &pointer_y,
+                                 NULL);
+        if (pointer_screen != manager->priv->current_screen) {
+                /* The pointer isn't on the current screen, so just
+                 * assume the default monitor
+                 */
+                monitor = 0;
+        } else {
+                monitor = gdk_screen_get_monitor_at_point (manager->priv->current_screen,
+                                                           pointer_x,
+                                                           pointer_y);
+        }
+
+        gdk_screen_get_monitor_geometry (manager->priv->current_screen,
+                                         monitor,
+                                         &geometry);
+
+        screen_w = geometry.width;
+        screen_h = geometry.height;
+
+        x = ((screen_w - orig_w) / 2) + geometry.x;
+        y = geometry.y + (screen_h / 2) + (screen_h / 2 - orig_h) / 2;
+
+        gtk_window_move (GTK_WINDOW (manager->priv->dialog), x, y);
+
+        gtk_widget_show (manager->priv->dialog);
+
+        gdk_display_sync (gdk_screen_get_display (manager->priv->current_screen));
+}
+
+static void
 handle_stock_config_hotkey (GsdXrandrManager *mgr, guint32 timestamp)
 {
         GsdXrandrManagerPrivate *priv = mgr->priv;
@@ -1391,9 +1582,9 @@ handle_stock_config_hotkey (GsdXrandrMan
                 g_free (str);
         }
 
-	if (!priv->stock_configs) {
+        if (!priv->stock_configs) {
                 log_msg ("Generating stock configurations:\n");
-		generate_stock_configs (mgr);
+                generate_stock_configs (mgr);
                 log_configurations (priv->stock_configs);
         }
 
@@ -1405,24 +1596,24 @@ handle_stock_config_hotkey (GsdXrandrMan
                     /* Our view of the world is incorrect, so regenerate the
                      * configurations
                      */
-		    generate_stock_configs (mgr);
+                    generate_stock_configs (mgr);
                     log_msg ("Regenerated stock configurations:\n");
                     log_configurations (priv->stock_configs);
             }
 
         gnome_rr_config_free (current);
 
-	if (priv->stock_configs) {
+        if (priv->stock_configs) {
                 guint32 server_timestamp;
 
-		mgr->priv->current_stock_config++;
+                mgr->priv->current_stock_config++;
 
                 if (!have_non_laptop(screen) || priv->stock_configs[mgr->priv->current_stock_config] == NULL)
                         mgr->priv->current_stock_config = 0;
 
-		g_debug ("cycling to next configuration (%d)", mgr->priv->current_stock_config);
+                g_debug ("cycling to next configuration (%d)", mgr->priv->current_stock_config);
 
-		print_configuration (priv->stock_configs[mgr->priv->current_stock_config]->rr_config, "new config");
+                print_configuration (priv->stock_configs[mgr->priv->current_stock_config]->rr_config, "new config");
 
                 g_debug ("applying");
 
@@ -1442,10 +1633,100 @@ handle_stock_config_hotkey (GsdXrandrMan
                 if (timestamp < server_timestamp)
                         timestamp = server_timestamp;
 
-		if (!gnome_rr_config_apply_with_time (priv->stock_configs[mgr->priv->current_stock_config]->rr_config, screen, timestamp, &error)) {
+                if (!gnome_rr_config_apply_with_time (priv->stock_configs[mgr->priv->current_stock_config]->rr_config, screen, timestamp, &error)) {
                           error_message (mgr, _("Could not switch the monitor configuration"), error, NULL);
                           g_error_free (error);
-		}
+                }
+        }
+        else {
+                g_debug ("no configurations generated");
+        }
+
+        log_close ();
+
+        gdk_flush ();
+        gdk_error_trap_pop ();
+
+        g_debug ("done handling XF86Display");
+}
+
+static void
+handle_stock_config_hotkey_osd (GsdXrandrManager *mgr)
+{
+        GsdXrandrManagerPrivate *priv = mgr->priv;
+        GnomeRRScreen *screen = priv->rw_screen;
+        GnomeRRConfig *current;
+        GError *error;
+
+        /* Theory of operation for the XF86Display hotkey
+         *
+         * We maintain a datastructure "stock_configs", that contains
+         * a list of GnomeRRConfig's. Each of the GnomeRRConfigs has a
+         * mode (or "off") for each connected output.
+         *
+         * When the user hits XF86Display, we cycle to the next GnomeRRConfig
+         * in the data structure. If the data structure does not exist, it
+         * is generated. If the configs in the data structure do not match
+         * the current hardware reality, it is regenerated.
+         *
+         */
+        g_debug ("Handling XF86Display");
+
+        gdk_error_trap_push (); /* avoid BadMatch error */
+
+        log_open ();
+
+        error = NULL;
+        if (!gnome_rr_screen_refresh (screen, &error) && error) {
+                char *str;
+
+                str = g_strdup_printf (_("Could not refresh the screen information: %s"), error->message);
+                g_error_free (error);
+
+                log_msg ("%s\n", str);
+                error_message (mgr, str, NULL, _("Trying to switch the monitor configuration anyway."));
+                g_free (str);
+        }
+
+	if (!priv->stock_configs) {
+                log_msg ("Generating stock configurations:\n");
+		generate_stock_configs (mgr);
+                log_configurations (priv->stock_configs);
+        }
+
+	current = gnome_rr_config_new_current (screen);
+
+        if (priv->stock_configs &&
+            (!gnome_rr_config_match (current, priv->stock_configs[0]->rr_config) ||
+             !gnome_rr_config_equal (current, priv->stock_configs[mgr->priv->current_stock_config]->rr_config))) {
+                    /* Our view of the world is incorrect, so regenerate the
+                     * configurations
+                     */
+		    generate_stock_configs (mgr);
+                    log_msg ("Regenerated stock configurations:\n");
+                    log_configurations (priv->stock_configs);
+            }
+
+        gnome_rr_config_free (current);
+
+	if (priv->stock_configs) {
+		const char *icon_name;
+
+		mgr->priv->next_stock_config++;
+
+                if (!have_non_laptop(screen) || priv->stock_configs[mgr->priv->next_stock_config] == NULL)
+                        mgr->priv->next_stock_config = 0;
+
+		icon_name = get_icon_name_for_stock_config (priv->stock_configs[mgr->priv->next_stock_config]->type);
+
+		g_debug ("cycling to next configuration (%d), (%s)", mgr->priv->next_stock_config, icon_name);
+		print_configuration (priv->stock_configs[mgr->priv->next_stock_config]->rr_config, "new config");
+
+		dialog_init (mgr);
+		gsd_xrandr_window_set_action_custom (GSD_XRANDR_WINDOW (priv->dialog),
+								 icon_name,
+								 FALSE);
+		dialog_show (mgr);
         }
         else {
                 g_debug ("no configurations generated");
@@ -1566,6 +1847,27 @@ out:
         gnome_rr_config_free (current);
 }
 
+static GdkScreen *
+acme_get_screen_from_event (GsdXrandrManager *manager,
+                            XAnyEvent           *xanyev)
+{
+        GdkWindow *window;
+        GdkScreen *screen;
+        GSList    *l;
+
+        /* Look for which screen we're receiving events */
+        for (l = manager->priv->screens; l != NULL; l = l->next) {
+                screen = (GdkScreen *) l->data;
+                window = gdk_screen_get_root_window (screen);
+
+                if (GDK_WINDOW_XID (window) == xanyev->window) {
+                        return screen;
+                }
+        }
+
+        return NULL;
+}
+
 static GdkFilterReturn
 event_filter (GdkXEvent           *xevent,
               GdkEvent            *event,
@@ -1573,6 +1875,7 @@ event_filter (GdkXEvent           *xeven
 {
         GsdXrandrManager *manager = data;
         XEvent *xev = (XEvent *) xevent;
+	XAnyEvent *xany = (XAnyEvent *) xevent;
 
         if (!manager->priv->running)
                 return GDK_FILTER_CONTINUE;
@@ -1582,8 +1885,14 @@ event_filter (GdkXEvent           *xeven
                 return GDK_FILTER_CONTINUE;
 
         if (xev->xany.type == KeyPress) {
-                if (xev->xkey.keycode == manager->priv->switch_video_mode_keycode)
-                        handle_stock_config_hotkey (manager, xev->xkey.time);
+                if (xev->xkey.keycode == manager->priv->switch_video_mode_keycode) {
+			manager->priv->current_screen = acme_get_screen_from_event (manager, xany);
+			manager->priv->xkey_time = xev->xkey.time;
+        		if (!gconf_client_get_bool (manager->priv->client, CONF_KEY_WHEEL_SELECT_OSD, NULL))
+                        	handle_stock_config_hotkey (manager, xev->xkey.time);	//TODO:
+			else
+                        	handle_stock_config_hotkey_osd (manager);
+		}
                 else if (xev->xkey.keycode == manager->priv->rotate_windows_keycode)
                         handle_rotate_windows (manager, xev->xkey.time);
 
@@ -2619,6 +2928,9 @@ gsd_xrandr_manager_stop (GsdXrandrManage
                 manager->priv->dbus_connection = NULL;
         }
 
+        g_slist_free (manager->priv->screens);
+        manager->priv->screens = NULL;
+
         log_open ();
         log_msg ("STOPPING XRANDR PLUGIN\n------------------------------------------------------------\n");
         log_close ();
@@ -2724,7 +3036,10 @@ gsd_xrandr_manager_init (GsdXrandrManage
         manager->priv->rotate_windows_keycode = get_keycode_for_keysym_name (ROTATE_KEYSYM);
 
         manager->priv->current_stock_config = -1;
+        manager->priv->next_stock_config = -1;
         manager->priv->stock_configs = NULL;
+
+	init_screens (manager);
 }
 
 static void
Index: gnome-settings-daemon-2.28.2/data/apps_gnome_settings_daemon_xrandr.schemas.in
===================================================================
--- gnome-settings-daemon-2.28.2.orig/data/apps_gnome_settings_daemon_xrandr.schemas.in
+++ gnome-settings-daemon-2.28.2/data/apps_gnome_settings_daemon_xrandr.schemas.in
@@ -2,6 +2,20 @@
 <gconfschemafile>
     <schemalist>
 	<schema>
+	    <key>/schemas/apps/gnome_settings_daemon/xrandr/wheel_select_osd</key>
+	    <applyto>/apps/gnome_settings_daemon/xrandr/wheel_select_osd</applyto>
+            <owner>gnome</owner>
+	    <type>bool</type>
+            <default>false</default>
+            <locale name="C">
+	        <short>Enable wheel select OSD mode</short>
+                <long>Set this parameter to true can enable the wheel select OSD mode.
+		    User can change next video mode by hotkey before OSD hide.
+		</long>
+            </locale>
+        </schema>
+
+	<schema>
 	    <key>/schemas/apps/gnome_settings_daemon/xrandr/show_notification_icon</key>
 	    <applyto>/apps/gnome_settings_daemon/xrandr/show_notification_icon</applyto>
             <owner>gnome</owner>
Index: gnome-settings-daemon-2.28.2/plugins/xrandr/gsd-xrandr-window.c
===================================================================
--- gnome-settings-daemon-2.28.2.orig/plugins/xrandr/gsd-xrandr-window.c
+++ gnome-settings-daemon-2.28.2/plugins/xrandr/gsd-xrandr-window.c
@@ -77,6 +77,8 @@ fade_timeout (GsdXrandrWindow *window)
                 window->priv->fade_out_alpha = 1.0;
                 window->priv->fade_timeout_id = 0;
 
+		g_signal_emit (G_OBJECT (window), signals[HIDE_TIMEOUT], 0);
+
                 return FALSE;
         } else {
                 GdkRectangle rect;
