diff -Nur gdm-2.23.92/daemon/Makefile.am gdm-2.23.92-new/daemon/Makefile.am
--- gdm-2.23.92/daemon/Makefile.am	2008-08-27 03:04:00.000000000 +0800
+++ gdm-2.23.92-new/daemon/Makefile.am	2008-09-18 10:42:55.095234000 +0800
@@ -300,6 +300,8 @@
 	gdm-static-display.h		\
 	gdm-transient-display.c		\
 	gdm-transient-display.h		\
+	gdm-dynamic-display.c		\
+	gdm-dynamic-display.h		\
 	gdm-static-factory-display.c	\
 	gdm-static-factory-display.h	\
 	gdm-product-display.c		\
diff -Nur gdm-2.23.92/daemon/gdm-display.c gdm-2.23.92-new/daemon/gdm-display.c
--- gdm-2.23.92/daemon/gdm-display.c	2008-09-09 07:00:51.000000000 +0800
+++ gdm-2.23.92-new/daemon/gdm-display.c	2008-09-18 10:49:57.112393000 +0800
@@ -58,6 +58,8 @@
         GTimer               *slave_timer;
         char                 *slave_command;
 
+        char                 *xserver_command;
+
         char                 *x11_cookie;
         gsize                 x11_cookie_size;
         GdmDisplayAccessFile *access_file;
@@ -82,6 +84,7 @@
         PROP_X11_AUTHORITY_FILE,
         PROP_IS_LOCAL,
         PROP_SLAVE_COMMAND,
+        PROP_XSERVER_COMMAND,
 };
 
 static void     gdm_display_class_init  (GdmDisplayClass *klass);
@@ -491,7 +494,18 @@
         gdm_slave_proxy_set_log_path (display->priv->slave_proxy, log_path);
         g_free (log_path);
 
-        command = g_strdup_printf ("%s --display-id %s",
+        /* Use --xserver-command only when custom Xserver is
+         * specified. Because X_SERVER needs extra arguments
+         * like "-br -verbose", leave it to gdm-server.
+         */
+        if (display->priv->xserver_command != NULL
+            && strcmp (display->priv->xserver_command, X_SERVER) != 0)
+                command = g_strdup_printf ("%s --display-id %s --xserver-command %s",
+                                   display->priv->slave_command,
+                                   display->priv->id,
+                                   display->priv->xserver_command);
+        else
+	        command = g_strdup_printf ("%s --display-id %s",
                                    display->priv->slave_command,
                                    display->priv->id);
         gdm_slave_proxy_set_command (display->priv->slave_proxy, command);
@@ -710,6 +724,14 @@
 }
 
 static void
+_gdm_display_set_xserver_command (GdmDisplay     *display,
+                                const char     *command)
+{
+        g_free (display->priv->xserver_command);
+        display->priv->xserver_command = g_strdup (command);
+}
+
+static void
 gdm_display_set_property (GObject        *object,
                           guint           prop_id,
                           const GValue   *value,
@@ -747,6 +769,9 @@
         case PROP_SLAVE_COMMAND:
                 _gdm_display_set_slave_command (self, g_value_get_string (value));
                 break;
+        case PROP_XSERVER_COMMAND:
+                _gdm_display_set_xserver_command (self, g_value_get_string (value));
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -795,6 +820,9 @@
         case PROP_SLAVE_COMMAND:
                 g_value_set_string (value, self->priv->slave_command);
                 break;
+        case PROP_XSERVER_COMMAND:
+                g_value_set_string (value, self->priv->xserver_command);
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -977,6 +1005,14 @@
                                                            G_MAXINT,
                                                            GDM_DISPLAY_UNMANAGED,
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+		
+        g_object_class_install_property (object_class,
+                                         PROP_XSERVER_COMMAND,
+                                         g_param_spec_string ("xserver-command",
+                                                              "xserver command",
+                                                              "xserver command",
+                                                              X_SERVER,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
         g_type_class_add_private (klass, sizeof (GdmDisplayPrivate));
 
@@ -1012,6 +1048,7 @@
         g_free (display->priv->x11_display_name);
         g_free (display->priv->x11_cookie);
         g_free (display->priv->slave_command);
+        g_free (display->priv->xserver_command);
 
         if (display->priv->access_file != NULL) {
                 g_object_unref (display->priv->access_file);
@@ -1023,7 +1060,7 @@
 
         if (display->priv->slave_timer != NULL) {
                 g_timer_destroy (display->priv->slave_timer);
-        }
+        }       
 
         G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object);
 }
diff -Nur gdm-2.23.92/daemon/gdm-dynamic-display.c gdm-2.23.92-new/daemon/gdm-dynamic-display.c
--- gdm-2.23.92/daemon/gdm-dynamic-display.c	1970-01-01 08:00:00.000000000 +0800
+++ gdm-2.23.92-new/daemon/gdm-dynamic-display.c	2008-09-18 10:42:55.096864000 +0800
@@ -0,0 +1,209 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Authors: simon.zheng@sun.com
+ * Copyright (C) 2008 Sun Microsystems, 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 of the License, 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.
+ *
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#include "gdm-common.h"
+#include "gdm-display.h"
+#include "gdm-dynamic-display.h"
+
+#define GDM_DYNAMIC_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DYNAMIC_DISPLAY, GdmDynamicDisplayPrivate))
+
+struct _GdmDynamicDisplayPrivate
+{
+        gpointer dummy;
+};
+
+enum {
+        PROP_0,
+};
+
+static void     gdm_dynamic_display_class_init   (GdmDynamicDisplayClass *klass);
+static void     gdm_dynamic_display_init         (GdmDynamicDisplay      *display);
+static void     gdm_dynamic_display_finalize     (GObject                  *object);
+
+G_DEFINE_TYPE (GdmDynamicDisplay, gdm_dynamic_display, GDM_TYPE_DISPLAY)
+
+static gboolean
+gdm_dynamic_display_create_authority (GdmDisplay *display)
+{
+        g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE);
+
+        GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->create_authority (display);
+
+        return TRUE;
+}
+
+static gboolean
+gdm_dynamic_display_add_user_authorization (GdmDisplay *display,
+                                            const char *username,
+                                            char      **filename,
+                                            GError    **error)
+{
+        return GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->add_user_authorization (display, username, filename, error);
+}
+
+static gboolean
+gdm_dynamic_display_remove_user_authorization (GdmDisplay *display,
+                                               const char *username,
+                                               GError    **error)
+{
+        return GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->remove_user_authorization (display, username, error);
+}
+
+static gboolean
+gdm_dynamic_display_manage (GdmDisplay *display)
+{
+        g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE);
+	
+        GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->manage (display);
+	
+        return TRUE;
+}
+
+static gboolean
+gdm_dynamic_display_finish (GdmDisplay *display)
+{
+        int status;
+
+        g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE);
+
+        /* restart dynamic display */
+        gdm_display_unmanage (display);
+
+        status = gdm_display_get_status (display);
+        if (status != GDM_DISPLAY_FAILED) {
+                gdm_display_manage (display);
+        }
+
+        return TRUE;
+}
+
+static gboolean
+gdm_dynamic_display_unmanage (GdmDisplay *display)
+{
+        g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE);
+
+        GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->unmanage (display);
+
+        return TRUE;
+}
+
+static void
+gdm_dynamic_display_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+        switch (prop_id) {
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gdm_dynamic_display_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+        switch (prop_id) {
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gdm_dynamic_display_class_init (GdmDynamicDisplayClass *klass)
+{
+        GObjectClass    *object_class = G_OBJECT_CLASS (klass);
+        GdmDisplayClass *display_class = GDM_DISPLAY_CLASS (klass);
+
+        object_class->get_property = gdm_dynamic_display_get_property;
+        object_class->set_property = gdm_dynamic_display_set_property;
+        object_class->finalize = gdm_dynamic_display_finalize;
+
+        display_class->create_authority = gdm_dynamic_display_create_authority;
+        display_class->add_user_authorization = gdm_dynamic_display_add_user_authorization;
+        display_class->remove_user_authorization = gdm_dynamic_display_remove_user_authorization;
+        display_class->manage = gdm_dynamic_display_manage;
+        display_class->finish = gdm_dynamic_display_finish;
+        display_class->unmanage = gdm_dynamic_display_unmanage;
+
+        g_type_class_add_private (klass, sizeof (GdmDynamicDisplayPrivate));
+}
+
+static void
+gdm_dynamic_display_init (GdmDynamicDisplay *display)
+{
+
+        display->priv = GDM_DYNAMIC_DISPLAY_GET_PRIVATE (display);
+}
+
+static void
+gdm_dynamic_display_finalize (GObject *object)
+{
+        GdmDynamicDisplay *display;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GDM_IS_DYNAMIC_DISPLAY (object));
+
+        display = GDM_DYNAMIC_DISPLAY (object);
+
+        g_return_if_fail (display->priv != NULL);
+
+        G_OBJECT_CLASS (gdm_dynamic_display_parent_class)->finalize (object);
+}
+
+GdmDisplay *
+gdm_dynamic_display_new (int display_number, char* xserver_command)
+{
+        GObject *object;
+        char    *x11_display;
+
+        x11_display = g_strdup_printf (":%d", display_number);
+        object = g_object_new (GDM_TYPE_DYNAMIC_DISPLAY,
+                               "x11-display-number", display_number,
+                               "x11-display-name", x11_display,
+                               "xserver-command", xserver_command,
+                               NULL);
+        g_free (x11_display);
+
+        return GDM_DISPLAY (object);
+}
diff -Nur gdm-2.23.92/daemon/gdm-dynamic-display.h gdm-2.23.92-new/daemon/gdm-dynamic-display.h
--- gdm-2.23.92/daemon/gdm-dynamic-display.h	1970-01-01 08:00:00.000000000 +0800
+++ gdm-2.23.92-new/daemon/gdm-dynamic-display.h	2008-09-18 10:42:55.097101000 +0800
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Authors: simon.zheng@sun.com
+ * Copyright (C) 2008 Sun Microsystems, 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 of the License, 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.
+ *
+ */
+
+
+#ifndef __GDM_DYNAMIC_DISPLAY_H
+#define __GDM_DYNAMIC_DISPLAY_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "gdm-display.h"
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_DYNAMIC_DISPLAY         (gdm_dynamic_display_get_type ())
+#define GDM_DYNAMIC_DISPLAY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_DYNAMIC_DISPLAY, GdmDynamicDisplay))
+#define GDM_DYNAMIC_DISPLAY_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_DYNAMIC_DISPLAY, GdmDynamicDisplayClass))
+#define GDM_IS_DYNAMIC_DISPLAY(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_DYNAMIC_DISPLAY))
+#define GDM_IS_DYNAMIC_DISPLAY_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_DYNAMIC_DISPLAY))
+#define GDM_DYNAMIC_DISPLAY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_DYNAMIC_DISPLAY, GdmDynamicDisplayClass))
+
+typedef struct _GdmDynamicDisplayPrivate GdmDynamicDisplayPrivate;
+
+typedef struct
+{
+        GdmDisplay                parent;
+        GdmDynamicDisplayPrivate *priv;
+} GdmDynamicDisplay;
+
+typedef struct
+{
+        GdmDisplayClass   parent_class;
+
+} GdmDynamicDisplayClass;
+
+GType               gdm_dynamic_display_get_type                (void);
+GdmDisplay *        gdm_dynamic_display_new                     (int display_number, char* xserver_command);
+
+
+G_END_DECLS
+
+#endif /* __GDM_DYNAMIC_DISPLAY_H */
diff -Nur gdm-2.23.92/daemon/gdm-local-display-factory.c gdm-2.23.92-new/daemon/gdm-local-display-factory.c
--- gdm-2.23.92/daemon/gdm-local-display-factory.c	2008-08-27 03:04:00.000000000 +0800
+++ gdm-2.23.92-new/daemon/gdm-local-display-factory.c	2008-09-18 10:42:55.097781000 +0800
@@ -34,6 +34,7 @@
 #include "gdm-display-store.h"
 #include "gdm-static-display.h"
 #include "gdm-transient-display.h"
+#include "gdm-dynamic-display.h"
 #include "gdm-static-factory-display.h"
 #include "gdm-product-display.h"
 
@@ -118,7 +119,7 @@
 static guint32
 take_next_display_number (GdmLocalDisplayFactory *factory)
 {
-        GList  *list;
+        GList  *list = NULL;
         GList  *l;
         guint32 ret;
 
@@ -185,6 +186,62 @@
         g_hash_table_insert (factory->priv->displays, GUINT_TO_POINTER (num), NULL);
 }
 
+static void
+store_remove_display (GdmLocalDisplayFactory *factory,
+                      guint32                 num,
+                      GdmDisplay             *display)
+{
+        GdmDisplayStore *store;
+
+        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+        gdm_display_store_remove (store, display);
+
+        /* remove from our reserved spot */
+        g_hash_table_remove (factory->priv->displays, GUINT_TO_POINTER (num));
+}
+
+static gboolean
+lookup_by_display_number (const char *id,
+                          GdmDisplay *display,
+                          gpointer    data)
+{
+        gint32 number;
+        gint32 display_number = -1;
+
+        number = GPOINTER_TO_INT (data);
+
+        if (! GDM_IS_DISPLAY (display)) {
+                return FALSE;
+        }
+
+        gdm_display_get_x11_display_number (display, &display_number, NULL);
+
+        if (display_number == number) {
+                return TRUE;
+        }
+
+        return FALSE;
+}
+
+static GdmDisplay *
+gdm_local_display_lookup_by_number (GdmLocalDisplayFactory *factory,
+                                    gint32                  number)
+{
+        GdmDisplay      *display;
+        GdmDisplayStore *store;
+
+        if (number < 0)
+                return NULL;
+		
+        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+        display = gdm_display_store_find (store,
+                                          (GdmDisplayStoreFunc)lookup_by_display_number,
+                                          GINT_TO_POINTER (number));
+
+        return display;
+}
+
+
 /*
   Example:
   dbus-send --system --dest=org.gnome.DisplayManager \
@@ -281,6 +338,152 @@
         return ret;
 }
 
+gboolean
+gdm_local_display_factory_create_dynamic_display (GdmLocalDisplayFactory *factory,
+                                                  gint32          display_number,
+                                                  char           *xserver_command,
+                                                  char          **id,                                                    
+                                                  GError        **error)
+{
+        gboolean        ret;
+        GdmDisplay     *display;
+
+        g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
+
+        ret = FALSE;
+
+        /* Make sure number doesn't exist */
+        if (g_hash_table_lookup_extended (factory->priv->displays,
+                                          GINT_TO_POINTER (display_number),
+                                          NULL,
+                                          NULL)) {
+                g_debug ("GdmLocalDisplayFactory: display number already exists");
+                goto out;
+        }
+
+        g_debug ("GdmLocalDisplayFactory: Creating dynamic display %d", display_number);
+
+        display = gdm_dynamic_display_new (display_number, xserver_command);
+
+        store_display (factory, display_number, display);
+
+        if (! gdm_display_manage (display)) {
+                display = NULL;
+                goto out;
+        }
+
+        if (! gdm_display_get_id (display, id, NULL)) {
+                display = NULL;
+                goto out;
+        }
+
+        ret = TRUE;
+ out:
+        g_object_unref (display);
+
+        return ret;
+}
+
+gboolean
+gdm_local_display_factory_remove_dynamic_display (GdmLocalDisplayFactory *factory,
+                                                  gint32                  display_number,
+                                                  GError                **error)
+{
+        gboolean         ret;
+        GdmDisplay      *display;
+
+        g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
+
+        ret = FALSE;
+
+        /* Make sure number already exist */
+        if (! g_hash_table_lookup_extended (factory->priv->displays,
+                                        GINT_TO_POINTER (display_number),
+                                        NULL,
+                                        NULL)) {
+                g_debug ("GdmLocalDisplayFactory: display number doesn't exists");
+                goto out;
+        }
+
+        g_debug ("GdmLocalDisplayFactory: Removing dynamic display %d", display_number);
+
+        display = gdm_local_display_lookup_by_number (factory, display_number);
+
+        if (! gdm_display_unmanage (display)) {
+                display = NULL;
+                goto out;
+        }
+
+        store_remove_display (factory, display_number, display);
+
+        ret = TRUE;
+ out:
+        return ret;
+}
+
+
+gboolean
+gdm_local_display_factory_list_displays (GdmLocalDisplayFactory *factory,
+                                         char                   *pattern,
+                                         char                  **display_list,
+                                         GError                **error)
+{
+        gboolean        ret;
+        GdmDisplay     *display;
+        GList          *list = NULL;
+        GList          *l;
+        GString        *ret_msg;
+
+        g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
+
+        ret = FALSE;
+
+        /* Get display number list from our reserved spot */
+        g_hash_table_foreach (factory->priv->displays, (GHFunc)listify_hash, &list);
+        if (list == NULL) {
+                goto out;
+        }
+        /* sort low to high */
+        list = g_list_sort (list, (GCompareFunc)sort_nums);
+
+        g_debug ("GdmLocalDisplayFactory: Listing X displays");
+
+        ret_msg = g_string_new ("");
+
+        for (l = list; l != NULL; l = l->next) {
+                gint32 number = GPOINTER_TO_INT (l->data);
+                GdmDisplay *display = NULL;
+                char *xserver_cmd = NULL;
+                char *name = NULL;
+			
+                g_debug ("GdmLocalDisplayFactory: %d", number);
+                display = gdm_local_display_lookup_by_number (factory, number);
+                if (GDM_IS_DYNAMIC_DISPLAY (display) == FALSE) {
+                        g_debug ("It's a non-dynamic display!");
+                        continue;
+                }
+                g_object_get (display, "xserver-command", &xserver_cmd, NULL);
+
+                if (xserver_cmd && g_pattern_match_simple (pattern, xserver_cmd)) {
+                        /* Each entry of output format is "DisplayName;" */
+                        gdm_display_get_x11_display_name (display, &name, NULL);
+                        g_string_append_printf (ret_msg, "%s;", name?name:"None");
+                        g_free (name);
+                	g_free (xserver_cmd);
+                }
+        }
+
+        if (ret_msg->str[0])
+                *display_list = g_strdup (ret_msg->str);
+        else
+                *display_list = g_strdup ("No matching display!");
+        g_string_free (ret_msg, TRUE);
+	
+        ret = TRUE;
+ out:
+        return ret;
+}
+
 static void
 on_static_display_status_changed (GdmDisplay             *display,
                                   GParamSpec             *arg1,
diff -Nur gdm-2.23.92/daemon/gdm-local-display-factory.h gdm-2.23.92-new/daemon/gdm-local-display-factory.h
--- gdm-2.23.92/daemon/gdm-local-display-factory.h	2008-08-27 03:04:00.000000000 +0800
+++ gdm-2.23.92-new/daemon/gdm-local-display-factory.h	2008-09-18 10:42:55.118771000 +0800
@@ -71,6 +71,21 @@
                                                                                char                  **id,
                                                                                GError                **error);
 
+gboolean                  gdm_local_display_factory_create_dynamic_display (GdmLocalDisplayFactory *factory,
+                                                                            gint32                  display_number,
+                                                                            char                   *xserver_command,
+                                                                            char                  **id,
+                                                                            GError                **error);
+
+gboolean                  gdm_local_display_factory_remove_dynamic_display (GdmLocalDisplayFactory *factory,
+                                                                            gint32                  display_number,
+                                                                            GError                **error);
+
+gboolean                  gdm_local_display_factory_list_displays (GdmLocalDisplayFactory *factory,
+                                                                   char                   *pattern,
+                                                                   char                  **display_list,
+                                                                   GError                **error);
+
 G_END_DECLS
 
 #endif /* __GDM_LOCAL_DISPLAY_FACTORY_H */
diff -Nur gdm-2.23.92/daemon/gdm-local-display-factory.xml gdm-2.23.92-new/daemon/gdm-local-display-factory.xml
--- gdm-2.23.92/daemon/gdm-local-display-factory.xml	2008-08-27 03:04:00.000000000 +0800
+++ gdm-2.23.92-new/daemon/gdm-local-display-factory.xml	2008-09-18 10:42:55.119001000 +0800
@@ -9,5 +9,17 @@
     <method name="CreateTransientDisplay">
       <arg name="id" direction="out" type="o"/>
     </method>
+    <method name="CreateDynamicDisplay">
+      <arg name="display_number" direction="in" type="i"/>
+      <arg name="xserver_command" direction="in" type="s"/>
+      <arg name="id" direction="out" type="o"/>
+    </method>
+    <method name="RemoveDynamicDisplay">
+      <arg name="display_number" direction="in" type="i"/>
+    </method>
+    <method name="ListDisplays">
+      <arg name="pattern" direction="in" type="s"/>
+      <arg name="display_list" direction="out" type="s"/>
+    </method>
   </interface>
 </node>
diff -Nur gdm-2.23.92/daemon/gdm-server.c gdm-2.23.92-new/daemon/gdm-server.c
--- gdm-2.23.92/daemon/gdm-server.c	2008-09-18 10:56:45.783571000 +0800
+++ gdm-2.23.92-new/daemon/gdm-server.c	2008-09-18 10:42:55.123070000 +0800
@@ -757,6 +757,13 @@
         return TRUE;
 }
 
+static void
+_gdm_server_set_command (GdmServer  *server,
+                         const char *command)
+{
+        g_free (server->priv->command);
+        server->priv->command = g_strdup (command);
+}
 
 static void
 _gdm_server_set_display_name (GdmServer  *server,
@@ -800,6 +807,9 @@
         self = GDM_SERVER (object);
 
         switch (prop_id) {
+        case PROP_COMMAND:
+                _gdm_server_set_command (self, g_value_get_string (value));
+                break;
         case PROP_DISPLAY_NAME:
                 _gdm_server_set_display_name (self, g_value_get_string (value));
                 break;
@@ -829,6 +839,9 @@
         self = GDM_SERVER (object);
 
         switch (prop_id) {
+        case PROP_COMMAND:
+                g_value_set_string (value, self->priv->command);
+                break;
         case PROP_DISPLAY_NAME:
                 g_value_set_string (value, self->priv->display_name);
                 break;
@@ -910,6 +923,13 @@
                               G_TYPE_INT);
 
         g_object_class_install_property (object_class,
+                                         PROP_COMMAND,
+                                         g_param_spec_string ("command",
+                                                              "command",
+                                                              "command",
+                                                              NULL,
+                                                              G_PARAM_READWRITE));
+        g_object_class_install_property (object_class,
                                          PROP_DISPLAY_NAME,
                                          g_param_spec_string ("display-name",
                                                               "name",
@@ -977,6 +997,9 @@
 
         gdm_server_stop (server);
 
+        g_free (server->priv->command);
+        g_free (server->priv->log_dir);
+
         G_OBJECT_CLASS (gdm_server_parent_class)->finalize (object);
 }
 
diff -Nur gdm-2.23.92/daemon/gdm-simple-slave.c gdm-2.23.92-new/daemon/gdm-simple-slave.c
--- gdm-2.23.92/daemon/gdm-simple-slave.c	2008-09-04 04:52:53.000000000 +0800
+++ gdm-2.23.92-new/daemon/gdm-simple-slave.c	2008-09-18 10:42:55.131389000 +0800
@@ -73,6 +73,8 @@
         GPid               server_pid;
         guint              connection_attempts;
 
+        char              *xserver_command;
+
         GdmServer         *server;
         GdmGreeterServer  *greeter_server;
         GdmGreeterSession *greeter;
@@ -84,6 +86,7 @@
 
 enum {
         PROP_0,
+        PROP_XSERVER_COMMAND,
 };
 
 static void     gdm_simple_slave_class_init     (GdmSimpleSlaveClass *klass);
@@ -1035,6 +1038,11 @@
                 gboolean disable_tcp;
 
                 slave->priv->server = gdm_server_new (display_name, auth_file);
+                /* pass in custom xserver command */
+                if (slave->priv->xserver_command)
+                        g_object_set (G_OBJECT (slave->priv->server),
+                                            "command", slave->priv->xserver_command,
+                                            NULL);
 
                 disable_tcp = TRUE;
                 if (gdm_settings_client_get_boolean (GDM_KEY_DISALLOW_TCP,
@@ -1125,7 +1133,15 @@
                                const GValue *value,
                                GParamSpec   *pspec)
 {
+        GdmSimpleSlave *self;
+
+        self = GDM_SIMPLE_SLAVE (object);
+
         switch (prop_id) {
+        case PROP_XSERVER_COMMAND:
+                g_free (self->priv->xserver_command);
+                self->priv->xserver_command = g_strdup (g_value_get_string (value));
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -1138,7 +1154,14 @@
                                GValue      *value,
                                GParamSpec *pspec)
 {
+        GdmSimpleSlave *self;
+	
+        self = GDM_SIMPLE_SLAVE (object);
+
         switch (prop_id) {
+        case PROP_XSERVER_COMMAND:
+                g_value_set_string (value, self->priv->xserver_command);
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -1175,6 +1198,15 @@
 
         g_type_class_add_private (klass, sizeof (GdmSimpleSlavePrivate));
 
+        g_object_class_install_property (object_class,
+                                         PROP_XSERVER_COMMAND,
+                                         g_param_spec_string ("xserver-command",
+                                                              "xserver command",
+                                                              "xserver command",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+
         dbus_g_object_type_install_info (GDM_TYPE_SIMPLE_SLAVE, &dbus_glib_gdm_simple_slave_object_info);
 }
 
@@ -1202,6 +1234,7 @@
                 g_source_remove (simple_slave->priv->greeter_reset_id);
                 simple_slave->priv->greeter_reset_id = 0;
         }
+        g_free (simple_slave->priv->xserver_command);
 
         G_OBJECT_CLASS (gdm_simple_slave_parent_class)->finalize (object);
 }
diff -Nur gdm-2.23.92/utils/Makefile.am gdm-2.23.92-new/utils/Makefile.am
--- gdm-2.23.92/utils/Makefile.am	2008-08-27 03:04:00.000000000 +0800
+++ gdm-2.23.92-new/utils/Makefile.am	2008-09-18 10:42:55.139135000 +0800
@@ -3,6 +3,7 @@
 INCLUDES = \
 	-I.						\
 	-I..						\
+	-I$(top_srcdir)/common				\
 	-DLOCALSTATEDIR=\""$(localstatedir)"\" 		\
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\" 	\
 	$(UTILS_CFLAGS)					\
@@ -25,6 +26,7 @@
 
 bin_PROGRAMS = \
 	gdmflexiserver		\
+	gdmdynamic		\
 	gdm-screenshot		\
 	$(NULL)
 
@@ -52,6 +54,16 @@
 	$(COMMON_LIBS)		\
 	$(NULL)
 
+gdmdynamic_SOURCES =        	\
+        gdmdynamic.c        	\
+        $(NULL)
+
+gdmdynamic_LDADD =          	\
+        $(top_builddir)/common/libgdmcommon.la  \
+        $(GTK_LIBS)             \
+        $(COMMON_LIBS)          \
+        $(NULL)
+
 EXTRA_DIST = 			\
 	gdm-stop.in		\
 	gdm-restart.in		\
diff -Nur gdm-2.23.92/utils/gdmdynamic.c gdm-2.23.92-new/utils/gdmdynamic.c
--- gdm-2.23.92/utils/gdmdynamic.c	1970-01-01 08:00:00.000000000 +0800
+++ gdm-2.23.92-new/utils/gdmdynamic.c	2008-09-18 10:42:55.139508000 +0800
@@ -0,0 +1,277 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ *    Authors: simon.zheng@sun.com
+ *    Copyright (C) 2008 Sun Microsystems, 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <strings.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "gdm-log.h"
+
+#define GDM_DBUS_NAME                            "org.gnome.DisplayManager"
+#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH      "/org/gnome/DisplayManager/LocalDisplayFactory"
+#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE "org.gnome.DisplayManager.LocalDisplayFactory"
+
+static void
+run_in_background (gboolean background)
+{
+        /* handle background option by forking and exiting the parent */
+        if (background) {
+                switch(fork ())  {
+                        case -1:
+                                exit (1);
+                        case 0:
+                                break;
+                        default:
+                                exit (0);
+                }
+        }
+}
+
+static gboolean
+add_dynamic_display (const char *key)
+{
+        gint disp_num;
+        char *p;
+        char *xcommand;
+        char *id = NULL;
+        DBusGConnection *connection;
+        DBusGProxy *proxy;
+        GError *error = NULL;
+        gboolean ret;
+
+        if (! g_ascii_isdigit (*key)) {
+                g_warning ("Invalid display number!");
+                return FALSE;
+        }
+        disp_num = atoi (key);
+
+        p = strchr (key, '=');
+        if (p == NULL || *(p + 1) == 0) {
+                g_warning  ("No server string\n");
+                return FALSE;
+        }
+        xcommand = p + 1;
+
+        connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (connection == NULL) {
+                g_warning ("Failed to connect to the D-Bus daemon: %s",
+                       error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+        proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                      GDM_DBUS_NAME,
+                                      GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
+                                      GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE,
+                                      &error);
+        if (proxy == NULL) {
+                g_warning ("Failed to create a new proxy, %s", error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+        ret = dbus_g_proxy_call (proxy, 
+                                "CreateDynamicDisplay", 
+                                &error,
+                                G_TYPE_INT, disp_num,
+                                G_TYPE_STRING, xcommand,
+                                G_TYPE_INVALID,
+                                G_TYPE_STRING, &id,
+                                G_TYPE_INVALID);
+        if (ret == FALSE) {
+                if (error) {
+                         g_warning ("Unable to add dynamic display: %s", error->message);
+                         g_error_free (error);
+                }
+                return FALSE;
+        }
+        g_object_unref (proxy);
+
+        return ret;
+}
+
+static gboolean
+remove_dynamic_display (const char *key)
+{
+        gint disp_num;
+        DBusGConnection *connection;
+        DBusGProxy *proxy;
+        GError *error = NULL;
+        gboolean ret;
+
+        if (!g_ascii_isdigit (*key)) {
+                g_warning ("Invalid display number!");
+                return FALSE;
+        }
+        disp_num = atoi (key);
+
+        connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (connection == NULL) {
+                g_warning ("Failed to connect to the D-Bus daemon: %s",
+                       error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+        proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                      GDM_DBUS_NAME,
+                                      GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
+                                      GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE,
+                                      &error);
+        if (proxy == NULL) {
+                g_warning ("Failed to create a new proxy, %s", error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+        ret = dbus_g_proxy_call (proxy, 
+                                "RemoveDynamicDisplay", 
+                                &error,
+                                G_TYPE_INT, disp_num,
+                                G_TYPE_INVALID,
+                                G_TYPE_INVALID);
+        if (ret == FALSE) {
+                if (error) {
+                         g_warning ("Unable to remove dynamic display: %s", error->message);
+                         g_error_free (error);
+                }
+                return FALSE;
+        }
+        g_object_unref (proxy);
+
+        return ret;
+}
+
+
+static gboolean
+list_attached_displays (const char *pattern)
+{
+        DBusGConnection *connection;
+        DBusGProxy *proxy;
+        char *display_list = NULL;
+        GError *error = NULL;
+        gboolean ret;
+
+        connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (connection == NULL) {
+                g_warning ("Failed to connect to the D-Bus daemon: %s",
+                       error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+        proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                      GDM_DBUS_NAME,
+                                      GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
+                                      GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE,
+                                      &error);
+        if (proxy == NULL) {
+                g_warning ("Failed to create a new proxy, %s", error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+        ret = dbus_g_proxy_call (proxy, 
+                                "ListDisplays", 
+                                &error,
+                                G_TYPE_STRING, pattern,
+                                G_TYPE_INVALID,
+                                G_TYPE_STRING, &display_list,
+                                G_TYPE_INVALID);
+        if (ret == FALSE) {
+                if (error) {
+                         g_warning ("Unable to list attached display: %s", error->message);
+                         g_error_free (error);
+                }
+                return FALSE;
+        } else {
+                g_print ("%s\n", display_list);
+        }
+        
+        g_object_unref (proxy);
+
+        return ret;
+}        
+
+int
+main (int argc, char *argv[])
+{
+        GOptionContext *ctx;
+        gboolean        res;
+        GError         *error;
+
+        char *add_params = NULL;
+        char *delete_params = NULL;
+        char *pattern = NULL;
+        gboolean background = FALSE;
+        gboolean show_version = FALSE;
+
+        /*FIXME: Do we need try sleep and background option? */
+        GOptionEntry options [] = {
+                { "add", 'a', 0, G_OPTION_ARG_STRING, &add_params, N_("Add a new display"), N_("display") },
+                { "delete", 'd', 0, G_OPTION_ARG_STRING, &delete_params, N_("Delete a display"), N_("display") },
+                { "list", 'l', 0, G_OPTION_ARG_STRING, &pattern, N_("List attached dynamic displays that match a pattern"), N_("pattern") },
+                { "background", 'b', 0, G_OPTION_ARG_NONE, &background, N_("Run in background"), NULL },
+                { NULL }
+        };   
+
+        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+        textdomain (GETTEXT_PACKAGE);
+
+        /* Option parsing */
+        ctx = g_option_context_new ("- Manage dynamic displays");
+        g_option_context_add_main_entries (ctx, options, _("Main Options"));
+        g_option_context_parse (ctx, &argc, &argv, NULL);
+        g_option_context_free (ctx);    
+
+        if (show_version) {
+                g_print ("%s %s\n", argv[0], VERSION);
+                exit (1);
+        }
+
+        g_type_init();
+
+        /*
+         * Must contain one of -a, -d, or -l.
+         * In case of "gdmdynamic -l" with NULL pattern, list all displays. 
+         */
+        if (argc == 2 && strncmp (argv[1], "-l", 2) == 0) {
+                pattern = "*";
+        }
+        if (add_params) {
+                run_in_background (background);
+                add_dynamic_display (add_params);
+        } else if (delete_params) {
+                run_in_background (background);
+                remove_dynamic_display (delete_params);
+        } else if (pattern) {
+                run_in_background (background);
+                list_attached_displays (pattern);
+        } else {
+                g_warning ("Invaild parameters!");
+                exit (1);
+        }
+
+        return 0;
+}
--- gdm-2.24.0/daemon/simple-slave-main.c.orig	2008-10-15 20:03:47.113323000 +0800
+++ gdm-2.24.0/daemon/simple-slave-main.c	2008-10-15 20:03:10.269040000 +0800
@@ -170,11 +170,13 @@
         DBusGConnection  *connection;
         GdmSlave         *slave;
         static char      *display_id = NULL;
+	static char      *xserver_command = NULL;
         static gboolean   debug      = FALSE;
         GdmSignalHandler *signal_handler;
         static GOptionEntry entries []   = {
                 { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL },
                 { "display-id", 0, 0, G_OPTION_ARG_STRING, &display_id, N_("Display ID"), N_("id") },
+		{ "xserver-command", 0, 0, G_OPTION_ARG_STRING, &xserver_command, N_("Xserver Command"), N_("xserver") },
                 { NULL }
         };
 
@@ -235,6 +237,12 @@
         if (slave == NULL) {
                 goto out;
         }
+	/* Use custom xserver */
+	if (xserver_command)
+		g_object_set (G_OBJECT (slave),
+			"xserver-command", xserver_command,
+			NULL);
+
         g_signal_connect (slave,
                           "stopped",
                           G_CALLBACK (on_slave_stopped),
