diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 626afc9..19430f0 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -300,6 +300,8 @@ gdm_binary_SOURCES = 			\
 	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 --git a/daemon/ck-connector.c b/daemon/ck-connector.c
index 0117eb9..d26db01 100644
--- a/daemon/ck-connector.c
+++ b/daemon/ck-connector.c
@@ -79,6 +79,7 @@ static struct {
         { "remote-host-name",   DBUS_TYPE_STRING },
         { "session-type",       DBUS_TYPE_STRING },
         { "is-local",           DBUS_TYPE_BOOLEAN },
+        { "is-dynamic",         DBUS_TYPE_BOOLEAN },
         { "unix-user",          DBUS_TYPE_INT32 },
 };
 
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 323d941..c590dbb 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -61,6 +61,8 @@ struct GdmDisplayPrivate
         GTimer               *slave_timer;
         char                 *slave_command;
 
+        char                 *xserver_command;
+
         char                 *x11_cookie;
         gsize                 x11_cookie_size;
         GdmDisplayAccessFile *access_file;
@@ -85,6 +87,7 @@ enum {
         PROP_X11_AUTHORITY_FILE,
         PROP_IS_LOCAL,
         PROP_SLAVE_COMMAND,
+        PROP_XSERVER_COMMAND,
 };
 
 static void     gdm_display_class_init  (GdmDisplayClass *klass);
@@ -578,7 +581,18 @@ gdm_display_real_prepare (GdmDisplay *display)
         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);
@@ -776,6 +790,24 @@ gdm_display_is_local (GdmDisplay *display,
         return TRUE;
 }
 
+gboolean
+gdm_display_is_dynamic (GdmDisplay *display,
+                        gboolean   *dynamic,
+                        GError    **error)
+{
+        g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE);
+
+        if (dynamic != NULL) {
+                if (display->priv->xserver_command != NULL
+                    && strcmp (display->priv->xserver_command, X_SERVER) != 0)
+                        *dynamic = TRUE;
+                else
+                        *dynamic = FALSE;
+        }
+
+        return TRUE;
+}
+
 static void
 _gdm_display_set_id (GdmDisplay     *display,
                      const char     *id)
@@ -839,6 +871,14 @@ _gdm_display_set_slave_command (GdmDisplay     *display,
 }
 
 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,
@@ -876,6 +916,9 @@ gdm_display_set_property (GObject        *object,
         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;
@@ -924,6 +967,9 @@ gdm_display_get_property (GObject        *object,
         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;
@@ -1108,6 +1154,14 @@ gdm_display_class_init (GdmDisplayClass *klass)
                                                            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));
 
@@ -1143,6 +1197,7 @@ gdm_display_finalize (GObject *object)
         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);
diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h
index 2914c81..81c3906 100644
--- a/daemon/gdm-display.h
+++ b/daemon/gdm-display.h
@@ -117,6 +117,9 @@ gboolean            gdm_display_get_seat_id                    (GdmDisplay *disp
 gboolean            gdm_display_is_local                       (GdmDisplay *display,
                                                                 gboolean   *local,
                                                                 GError    **error);
+gboolean            gdm_display_is_dynamic                     (GdmDisplay *display,
+                                                                gboolean   *dynamic,
+                                                                GError    **error);
 gboolean            gdm_display_get_timed_login_details        (GdmDisplay *display,
                                                                 gboolean   *enabled,
                                                                 char      **username,
diff --git a/daemon/gdm-display.xml b/daemon/gdm-display.xml
index e8a2369..42231db 100644
--- a/daemon/gdm-display.xml
+++ b/daemon/gdm-display.xml
@@ -25,6 +25,9 @@
     <method name="IsLocal">
       <arg name="local" direction="out" type="b"/>
     </method>
+    <method name="IsDynamic">
+      <arg name="dynamic" direction="out" type="b"/>
+    </method>
     <method name="AddUserAuthorization">
       <arg name="username" direction="in" type="s"/>
       <arg name="filename" direction="out" type="s"/>
diff --git a/daemon/gdm-dynamic-display.c b/daemon/gdm-dynamic-display.c
new file mode 100644
index 0000000..00c4fc9
--- /dev/null
+++ b/daemon/gdm-dynamic-display.c
@@ -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 --git a/daemon/gdm-dynamic-display.h b/daemon/gdm-dynamic-display.h
new file mode 100644
index 0000000..509d4d9
--- /dev/null
+++ b/daemon/gdm-dynamic-display.h
@@ -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 --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c
index d09c913..357786a 100644
--- a/daemon/gdm-factory-slave.c
+++ b/daemon/gdm-factory-slave.c
@@ -458,6 +458,7 @@ static void
 run_greeter (GdmFactorySlave *slave)
 {
         gboolean       display_is_local;
+        gboolean       display_is_dynamic;
         char          *display_id;
         char          *display_name;
         char          *display_device;
@@ -468,6 +469,7 @@ run_greeter (GdmFactorySlave *slave)
         g_debug ("GdmFactorySlave: Running greeter");
 
         display_is_local = FALSE;
+        display_is_dynamic = FALSE;
         display_id = NULL;
         display_name = NULL;
         auth_file = NULL;
@@ -476,6 +478,7 @@ run_greeter (GdmFactorySlave *slave)
 
         g_object_get (slave,
                       "display-is-local", &display_is_local,
+                      "display-is-dynamic", &display_is_dynamic,
                       "display-id", &display_id,
                       "display-name", &display_name,
                       "display-hostname", &display_hostname,
@@ -536,7 +539,8 @@ run_greeter (GdmFactorySlave *slave)
         slave->priv->greeter = gdm_greeter_session_new (display_name,
                                                         display_device,
                                                         display_hostname,
-                                                        display_is_local);
+                                                        display_is_local,
+                                                        display_is_dynamic);
         g_signal_connect (slave->priv->greeter,
                           "started",
                           G_CALLBACK (on_greeter_session_start),
diff --git a/daemon/gdm-greeter-session.c b/daemon/gdm-greeter-session.c
index aae1928..c6ab7f4 100644
--- a/daemon/gdm-greeter-session.c
+++ b/daemon/gdm-greeter-session.c
@@ -142,7 +142,8 @@ GdmGreeterSession *
 gdm_greeter_session_new (const char *display_name,
                          const char *display_device,
                          const char *display_hostname,
-                         gboolean    display_is_local)
+                         gboolean    display_is_local,
+                         gboolean    display_is_dynamic)
 {
         GObject *object;
 
@@ -156,6 +157,7 @@ gdm_greeter_session_new (const char *display_name,
                                "x11-display-device", display_device,
                                "x11-display-hostname", display_hostname,
                                "x11-display-is-local", display_is_local,
+                               "x11-display-is-dynamic", display_is_dynamic,
                                NULL);
 
         return GDM_GREETER_SESSION (object);
diff --git a/daemon/gdm-greeter-session.h b/daemon/gdm-greeter-session.h
index 0a171c9..17cc691 100644
--- a/daemon/gdm-greeter-session.h
+++ b/daemon/gdm-greeter-session.h
@@ -52,7 +52,8 @@ GType                 gdm_greeter_session_get_type           (void);
 GdmGreeterSession *   gdm_greeter_session_new                (const char        *display_name,
                                                               const char        *display_device,
                                                               const char        *display_hostname,
-                                                              gboolean           display_is_local);
+                                                              gboolean           display_is_local,
+                                                              gboolean           display_is_dynamic);
 
 G_END_DECLS
 
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 3984ada..523e41b 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -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 @@ sort_nums (gpointer a,
 static guint32
 take_next_display_number (GdmLocalDisplayFactory *factory)
 {
-        GList  *list;
+        GList  *list = NULL;
         GList  *l;
         guint32 ret;
 
@@ -185,6 +186,62 @@ store_display (GdmLocalDisplayFactory *factory,
         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,106 @@ gdm_local_display_factory_create_product_display (GdmLocalDisplayFactory *factor
         return ret;
 }
 
+/*
+  Example:
+  dbus-send --system --dest=org.gnome.DisplayManager \
+  --type=method_call --print-reply --reply-timeout=2000 \
+  /org/gnome/DisplayManager/LocalDisplayFactory \
+  org.gnome.DisplayManager.LocalDisplayFactory.CreateDynamicDisplay \
+  int32:101 string:"/usr/X11/bin/Xvfb"
+*/
+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;
+}
+
+/*
+  Example:
+  dbus-send --system --dest=org.gnome.DisplayManager \
+  --type=method_call --print-reply --reply-timeout=2000 \
+  /org/gnome/DisplayManager/LocalDisplayFactory \
+  org.gnome.DisplayManager.LocalDisplayFactory.RemoveDynamicDisplay \
+  int32:101
+*/
+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;
+}
+
+
 static void
 on_static_display_status_changed (GdmDisplay             *display,
                                   GParamSpec             *arg1,
diff --git a/daemon/gdm-local-display-factory.h b/daemon/gdm-local-display-factory.h
index 2abb053..120e11a 100644
--- a/daemon/gdm-local-display-factory.h
+++ b/daemon/gdm-local-display-factory.h
@@ -71,6 +71,16 @@ gboolean                   gdm_local_display_factory_create_product_display   (G
                                                                                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);
+
 G_END_DECLS
 
 #endif /* __GDM_LOCAL_DISPLAY_FACTORY_H */
diff --git a/daemon/gdm-local-display-factory.xml b/daemon/gdm-local-display-factory.xml
index 51f5153..601227f 100644
--- a/daemon/gdm-local-display-factory.xml
+++ b/daemon/gdm-local-display-factory.xml
@@ -9,5 +9,13 @@
     <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>
   </interface>
 </node>
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
index 26391f5..aee7594 100644
--- a/daemon/gdm-server.c
+++ b/daemon/gdm-server.c
@@ -757,6 +757,13 @@ gdm_server_stop (GdmServer *server)
         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 @@ gdm_server_set_property (GObject      *object,
         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 @@ gdm_server_get_property (GObject    *object,
         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 @@ gdm_server_class_init (GdmServerClass *klass)
                               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_finalize (GObject *object)
 
         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 --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 6a00931..033dd6c 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -73,6 +73,8 @@ struct GdmSimpleSlavePrivate
         GPid               server_pid;
         guint              connection_attempts;
 
+        char              *xserver_command;
+
         GdmServer         *server;
         GdmSessionDirect  *session;
 
@@ -85,6 +87,7 @@ struct GdmSimpleSlavePrivate
 
 enum {
         PROP_0,
+        PROP_XSERVER_COMMAND,
 };
 
 static void     gdm_simple_slave_class_init     (GdmSimpleSlaveClass *klass);
@@ -856,6 +859,7 @@ static void
 start_greeter (GdmSimpleSlave *slave)
 {
         gboolean       display_is_local;
+        gboolean       display_is_dynamic;
         char          *display_id;
         char          *display_name;
         char          *display_device;
@@ -866,6 +870,7 @@ start_greeter (GdmSimpleSlave *slave)
         g_debug ("GdmSimpleSlave: Running greeter");
 
         display_is_local = FALSE;
+        display_is_dynamic = FALSE;
         display_id = NULL;
         display_name = NULL;
         auth_file = NULL;
@@ -875,6 +880,7 @@ start_greeter (GdmSimpleSlave *slave)
         g_object_get (slave,
                       "display-id", &display_id,
                       "display-is-local", &display_is_local,
+                      "display-is-dynamic", &display_is_dynamic,
                       "display-name", &display_name,
                       "display-hostname", &display_hostname,
                       "display-x11-authority-file", &auth_file,
@@ -955,7 +961,8 @@ start_greeter (GdmSimpleSlave *slave)
         slave->priv->greeter = gdm_greeter_session_new (display_name,
                                                         display_device,
                                                         display_hostname,
-                                                        display_is_local);
+                                                        display_is_local,
+                                                        display_is_dynamic);
         g_signal_connect (slave->priv->greeter,
                           "started",
                           G_CALLBACK (on_greeter_session_start),
@@ -1070,6 +1077,12 @@ gdm_simple_slave_run (GdmSimpleSlave *slave)
                 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,
@@ -1158,7 +1171,15 @@ gdm_simple_slave_set_property (GObject      *object,
                                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;
@@ -1171,7 +1192,14 @@ gdm_simple_slave_get_property (GObject    *object,
                                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;
@@ -1208,6 +1236,15 @@ gdm_simple_slave_class_init (GdmSimpleSlaveClass *klass)
 
         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);
 }
 
@@ -1235,6 +1272,7 @@ gdm_simple_slave_finalize (GObject *object)
                 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 --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index 07c63c1..b40e324 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -82,6 +82,7 @@ struct GdmSlavePrivate
         int              display_number;
         char            *display_hostname;
         gboolean         display_is_local;
+        gboolean         display_is_dynamic;
         gboolean         display_is_parented;
         char            *display_seat_id;
         char            *display_x11_authority_file;
@@ -99,6 +100,7 @@ enum {
         PROP_DISPLAY_NUMBER,
         PROP_DISPLAY_HOSTNAME,
         PROP_DISPLAY_IS_LOCAL,
+        PROP_DISPLAY_IS_DYNAMIC,
         PROP_DISPLAY_SEAT_ID,
         PROP_DISPLAY_X11_AUTHORITY_FILE
 };
@@ -513,6 +515,24 @@ gdm_slave_real_start (GdmSlave *slave)
 
         error = NULL;
         res = dbus_g_proxy_call (slave->priv->display_proxy,
+                                 "IsDynamic",
+                                 &error,
+                                 G_TYPE_INVALID,
+                                 G_TYPE_BOOLEAN, &slave->priv->display_is_dynamic,
+                                 G_TYPE_INVALID);
+        if (! res) {
+                if (error != NULL) {
+                        g_warning ("Failed to get value: %s", error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to get value");
+                }
+
+                return FALSE;
+        }
+
+        error = NULL;
+        res = dbus_g_proxy_call (slave->priv->display_proxy,
                                  "GetX11DisplayName",
                                  &error,
                                  G_TYPE_INVALID,
@@ -1164,6 +1184,13 @@ _gdm_slave_set_display_is_local (GdmSlave   *slave,
 }
 
 static void
+_gdm_slave_set_display_is_dynamic (GdmSlave   *slave,
+                                   gboolean    is)
+{
+        slave->priv->display_is_dynamic = is;
+}
+
+static void
 gdm_slave_set_property (GObject      *object,
                         guint         prop_id,
                         const GValue *value,
@@ -1195,6 +1222,9 @@ gdm_slave_set_property (GObject      *object,
         case PROP_DISPLAY_IS_LOCAL:
                 _gdm_slave_set_display_is_local (self, g_value_get_boolean (value));
                 break;
+        case PROP_DISPLAY_IS_DYNAMIC:
+                _gdm_slave_set_display_is_dynamic (self, g_value_get_boolean (value));
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -1233,6 +1263,9 @@ gdm_slave_get_property (GObject    *object,
         case PROP_DISPLAY_IS_LOCAL:
                 g_value_set_boolean (value, self->priv->display_is_local);
                 break;
+        case PROP_DISPLAY_IS_DYNAMIC:
+                g_value_set_boolean (value, self->priv->display_is_dynamic);
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -1357,6 +1390,13 @@ gdm_slave_class_init (GdmSlaveClass *klass)
                                                                "display is local",
                                                                TRUE,
                                                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_IS_DYNAMIC,
+                                         g_param_spec_boolean ("display-is-dynamic",
+                                                               "display is dynamic",
+                                                               "display is dynamic",
+                                                               FALSE,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
         signals [STOPPED] =
                 g_signal_new ("stopped",
diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
index a356cd4..b08188a 100644
--- a/daemon/gdm-welcome-session.c
+++ b/daemon/gdm-welcome-session.c
@@ -69,6 +69,7 @@ struct GdmWelcomeSessionPrivate
         char           *x11_display_hostname;
         char           *x11_authority_file;
         gboolean        x11_display_is_local;
+        gboolean        x11_display_is_dynamic;
 
         guint           child_watch_id;
 
@@ -89,6 +90,7 @@ enum {
         PROP_X11_DISPLAY_HOSTNAME,
         PROP_X11_AUTHORITY_FILE,
         PROP_X11_DISPLAY_IS_LOCAL,
+        PROP_X11_DISPLAY_IS_DYNAMIC,
         PROP_USER_NAME,
         PROP_GROUP_NAME,
         PROP_SERVER_ADDRESS,
@@ -168,12 +170,13 @@ open_welcome_session (GdmWelcomeSession *welcome_session)
                 x11_display_device = "";
         }
 
-        g_debug ("GdmWelcomeSession: Opening ConsoleKit session for user:%d x11-display:'%s' x11-display-device:'%s' remote-host-name:'%s' is-local:%d",
+        g_debug ("GdmWelcomeSession: Opening ConsoleKit session for user:%d x11-display:'%s' x11-display-device:'%s' remote-host-name:'%s' is-local:%d is-dynamic:%d",
                  pwent->pw_uid,
                  welcome_session->priv->x11_display_name,
                  x11_display_device,
                  hostname,
-                 welcome_session->priv->x11_display_is_local);
+                 welcome_session->priv->x11_display_is_local,
+                 welcome_session->priv->x11_display_is_dynamic);
 
         dbus_error_init (&error);
         res = ck_connector_open_session_with_parameters (welcome_session->priv->ckc,
@@ -184,6 +187,7 @@ open_welcome_session (GdmWelcomeSession *welcome_session)
                                                          "x11-display-device", &x11_display_device,
                                                          "remote-host-name", &hostname,
                                                          "is-local", &welcome_session->priv->x11_display_is_local,
+                                                         "is-dynamic", &welcome_session->priv->x11_display_is_dynamic,
                                                          NULL);
         if (! res) {
                 if (dbus_error_is_set (&error)) {
@@ -904,6 +908,12 @@ _gdm_welcome_session_set_x11_display_is_local (GdmWelcomeSession *welcome_sessio
         welcome_session->priv->x11_display_is_local = is_local;
 }
 
+static void
+_gdm_welcome_session_set_x11_display_is_dynamic (GdmWelcomeSession *welcome_session,
+                                                 gboolean           is_dynamic)
+{
+        welcome_session->priv->x11_display_is_dynamic = is_dynamic;
+}
 
 static void
 _gdm_welcome_session_set_x11_authority_file (GdmWelcomeSession *welcome_session,
@@ -991,6 +1001,9 @@ gdm_welcome_session_set_property (GObject      *object,
         case PROP_X11_DISPLAY_IS_LOCAL:
                 _gdm_welcome_session_set_x11_display_is_local (self, g_value_get_boolean (value));
                 break;
+        case PROP_X11_DISPLAY_IS_DYNAMIC:
+                _gdm_welcome_session_set_x11_display_is_dynamic (self, g_value_get_boolean (value));
+                break;
         case PROP_X11_AUTHORITY_FILE:
                 _gdm_welcome_session_set_x11_authority_file (self, g_value_get_string (value));
                 break;
@@ -1047,6 +1060,9 @@ gdm_welcome_session_get_property (GObject    *object,
         case PROP_X11_DISPLAY_IS_LOCAL:
                 g_value_set_boolean (value, self->priv->x11_display_is_local);
                 break;
+        case PROP_X11_DISPLAY_IS_DYNAMIC:
+                g_value_set_boolean (value, self->priv->x11_display_is_dynamic);
+                break;
         case PROP_X11_AUTHORITY_FILE:
                 g_value_set_string (value, self->priv->x11_authority_file);
                 break;
@@ -1135,6 +1151,13 @@ gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass)
                                                                FALSE,
                                                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
         g_object_class_install_property (object_class,
+                                         PROP_X11_DISPLAY_IS_DYNAMIC,
+                                         g_param_spec_boolean ("x11-display-is-dynamic",
+                                                               "is dynamic",
+                                                               "is dynamic",
+                                                               FALSE,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (object_class,
                                          PROP_X11_AUTHORITY_FILE,
                                          g_param_spec_string ("x11-authority-file",
                                                               "authority file",
diff --git a/daemon/simple-slave-main.c b/daemon/simple-slave-main.c
index 9661fa7..3552f9a 100644
--- a/daemon/simple-slave-main.c
+++ b/daemon/simple-slave-main.c
@@ -170,11 +170,13 @@ main (int    argc,
         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,14 @@ main (int    argc,
         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),
diff --git a/m4/intltool.m4 b/m4/intltool.m4
index 122d773..7d8fad7 100644
--- a/m4/intltool.m4
+++ b/m4/intltool.m4
@@ -75,25 +75,25 @@ INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcar
     INTLTOOL_SERVICE_RULE='%.service: %.service.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
    INTLTOOL_POLICY_RULE='%.policy:    %.policy.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
 
-_IT_SUBST(INTLTOOL_DESKTOP_RULE)
-_IT_SUBST(INTLTOOL_DIRECTORY_RULE)
-_IT_SUBST(INTLTOOL_KEYS_RULE)
-_IT_SUBST(INTLTOOL_PROP_RULE)
-_IT_SUBST(INTLTOOL_OAF_RULE)
-_IT_SUBST(INTLTOOL_PONG_RULE)
-_IT_SUBST(INTLTOOL_SERVER_RULE)
-_IT_SUBST(INTLTOOL_SHEET_RULE)
-_IT_SUBST(INTLTOOL_SOUNDLIST_RULE)
-_IT_SUBST(INTLTOOL_UI_RULE)
-_IT_SUBST(INTLTOOL_XAM_RULE)
-_IT_SUBST(INTLTOOL_KBD_RULE)
-_IT_SUBST(INTLTOOL_XML_RULE)
-_IT_SUBST(INTLTOOL_XML_NOMERGE_RULE)
-_IT_SUBST(INTLTOOL_CAVES_RULE)
-_IT_SUBST(INTLTOOL_SCHEMAS_RULE)
-_IT_SUBST(INTLTOOL_THEME_RULE)
-_IT_SUBST(INTLTOOL_SERVICE_RULE)
-_IT_SUBST(INTLTOOL_POLICY_RULE)
+AC_SUBST(INTLTOOL_DESKTOP_RULE)
+AC_SUBST(INTLTOOL_DIRECTORY_RULE)
+AC_SUBST(INTLTOOL_KEYS_RULE)
+AC_SUBST(INTLTOOL_PROP_RULE)
+AC_SUBST(INTLTOOL_OAF_RULE)
+AC_SUBST(INTLTOOL_PONG_RULE)
+AC_SUBST(INTLTOOL_SERVER_RULE)
+AC_SUBST(INTLTOOL_SHEET_RULE)
+AC_SUBST(INTLTOOL_SOUNDLIST_RULE)
+AC_SUBST(INTLTOOL_UI_RULE)
+AC_SUBST(INTLTOOL_XAM_RULE)
+AC_SUBST(INTLTOOL_KBD_RULE)
+AC_SUBST(INTLTOOL_XML_RULE)
+AC_SUBST(INTLTOOL_XML_NOMERGE_RULE)
+AC_SUBST(INTLTOOL_CAVES_RULE)
+AC_SUBST(INTLTOOL_SCHEMAS_RULE)
+AC_SUBST(INTLTOOL_THEME_RULE)
+AC_SUBST(INTLTOOL_SERVICE_RULE)
+AC_SUBST(INTLTOOL_POLICY_RULE)
 
 # Check the gettext tools to make sure they are GNU
 AC_PATH_PROG(XGETTEXT, xgettext)
@@ -105,22 +105,16 @@ if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then
 fi
 xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`"
 mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`"
-mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`"
-if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then
+if test -z "$xgversion" -o -z "$mmversion"; then
     AC_MSG_ERROR([GNU gettext tools not found; required for intltool])
 fi
 
-AC_PATH_PROG(INTLTOOL_PERL, perl)
+AC_PATH_PROG(INTLTOOL_PERL, [perl])
 if test -z "$INTLTOOL_PERL"; then
-   AC_MSG_ERROR([perl not found])
+   AC_MSG_ERROR([perl not found; required for intltool])
 fi
-AC_MSG_CHECKING([for perl >= 5.8.1])
-$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1
-if test $? -ne 0; then
-   AC_MSG_ERROR([perl 5.8.1 is required for intltool])
-else
-   IT_PERL_VERSION="`$INTLTOOL_PERL -e \"printf '%vd', $^V\"`"
-   AC_MSG_RESULT([$IT_PERL_VERSION])
+if test -z "`$INTLTOOL_PERL -v | fgrep '5.' 2> /dev/null`"; then
+   AC_MSG_ERROR([perl 5.x required for intltool])
 fi
 if test "x$2" != "xno-xml"; then
    AC_MSG_CHECKING([for XML::Parser])
@@ -176,7 +170,7 @@ dnl The following CONFIG_COMMANDS should be exetuted at the very end
 dnl of config.status.
 AC_CONFIG_COMMANDS_PRE([
   AC_CONFIG_COMMANDS([$1/stamp-it], [
-    if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" > /dev/null ]; then
+    if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" ]; then
        AC_MSG_ERROR([$1/Makefile.in.in was not created by intltoolize.])
     fi
     rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp"
@@ -198,17 +192,6 @@ AC_CONFIG_COMMANDS_PRE([
 ])dnl
 ])
 
-# _IT_SUBST(VARIABLE)
-# -------------------
-# Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST
-#
-AC_DEFUN([_IT_SUBST],
-[
-AC_SUBST([$1])
-m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])])
-]
-)
-
 # deprecated macros
 AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL])
 # A hint is needed for aclocal from Automake <= 1.9.4:
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 7b90beb..fc4f071 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -22,6 +22,8 @@ gdm-restart: gdm-restart.in Makefile
 	$(edit) $< >$@
 gdm-safe-restart: gdm-safe-restart.in Makefile
 	$(edit) $< >$@
+gdmdynamic: gdmdynamic.in Makefile
+	$(edit) $< >$@
 
 bin_PROGRAMS = \
 	gdmflexiserver		\
@@ -34,6 +36,10 @@ sbin_SCRIPTS = 			\
 	gdm-safe-restart	\
 	$(NULL)
 
+bin_SCRIPTS = 			\
+	gdmdynamic
+	$(NULL)
+
 gdmflexiserver_SOURCES =	\
 	gdmflexiserver.c	\
 	$(NULL)
@@ -56,6 +62,7 @@ EXTRA_DIST = 			\
 	gdm-stop.in		\
 	gdm-restart.in		\
 	gdm-safe-restart.in	\
+	gdmdynamic.in		\
 	$(NULL)
 
 CLEANFILES = 			\
@@ -65,5 +72,6 @@ DISTCLEANFILES = 		\
 	gdm-stop		\
 	gdm-restart		\
 	gdm-safe-restart	\
+	gdmdynamic		\
 	$(NULL)
 
diff --git a/utils/gdmdynamic.in b/utils/gdmdynamic.in
new file mode 100644
index 0000000..eb5e002
--- /dev/null
+++ b/utils/gdmdynamic.in
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+CK_DYNAMIC=`which ck-dynamic`
+
+if test '!' -x $CK_DYNAMIC; then
+	echo "ck-dynamic doesn't exist in your PATH, perhaps ConsoleKit isn't installed"
+	exit 1
+fi
+
+$CK_DYNAMIC "$@"
