[gdm-list] GDM manages displays on the fly
- From: "simon.zheng" <Simon Zheng Sun COM>
- To: gdm-list gnome org, mccann jhu edu, halfline gmail com
- Cc: Brian Cameron <Brian Cameron Sun COM>
- Subject: [gdm-list] GDM manages displays on the fly
- Date: Sat, 19 Apr 2008 14:35:15 +0800
Hi Joh and Ray,
Before version 2.21, GDM is capable of managing displays dynamically.
It's originally motivated by Sun Ray which works well on various Linux
platform. Sun Ray uses this feature to add/remove Sun Ray clients
when they are added/removed for the network. Beside Sun Ray, there
are other potential use cases, for example, launching GDM with Xvm,
or any terminal server environment might be want to start/stop display
without reconfiguration and restarting GDM daemon.
In order to fit with new GDM 2.21 framework, I try to rewrite
gdmdynamic. Please see attached patch. Could you have a look and give
some idea? Hopefully this functionality will be kept in upstream.
This patch adds a kind of display called dynamic display, which has
below features.
- Can be Added, removed and listed dynamically without
restarting gdm-binary
- Like static display, can be restarted by gdm-binary if it
died exceptionally
- Allow to specify custom Xserver when adding.
- Support adding/removing multiple displays simultaneously,
possibly hundreds of requests at the same time.
As well as static display and product display, currently I put dynamic
display under local display directory. And let gdm-simple-slave manage
it.
Apart from dyanmic management, another big difference from other display
types, we allow to specifiy custom Xserver when starting. Actually this
functionality is also needed for nest transient display, which requires
to run Xnest rather than a standard Xserver. In GDM 2.20, nest transient
display is running by "#gdmflexiserver -n".
Like transient display, property "seat-id" of dynamic displays are set
as "Seat1" in hard-code. Perhaps this needs enhancement. As my
understanding, dynamic display can be regarded as a typical multi-seat
case. But I'm not sure how this can work together with ConsoleKit?
For multi-seat, I'm a little confused. Looking into ConsoleKit code, it
seems to only support 2 seats, local and remote seats. But when I try
gdmdynamic, I find each login screen will add a new seat. Here's a
result of adding 5 displays at the same time.
----------------------------
# ck-list-sessions
Session3:
uid = '50'
realname = 'GDM Reserved UID'
seat = 'Seat4'
session-type = 'LoginWindow'
active = FALSE
x11-display = ':102'
x11-display-device = ''
display-device = ''
remote-host-name = ''
is-local = TRUE
on-since = '2008-04-17T08:24:26Z'
Session4:
uid = '50'
realname = 'GDM Reserved UID'
seat = 'Seat5'
session-type = 'LoginWindow'
active = FALSE
x11-display = ':103'
x11-display-device = ''
display-device = ''
remote-host-name = ''
is-local = TRUE
on-since = '2008-04-17T08:24:26Z'
Session5:
uid = '50'
realname = 'GDM Reserved UID'
seat = 'Seat6'
session-type = 'LoginWindow'
active = FALSE
x11-display = ':100'
x11-display-device = ''
display-device = ''
remote-host-name = ''
is-local = TRUE
on-since = '2008-04-17T08:24:26Z'
Session6:
uid = '50'
realname = 'GDM Reserved UID'
seat = 'Seat7'
session-type = 'LoginWindow'
active = FALSE
x11-display = ':104'
x11-display-device = ''
display-device = ''
remote-host-name = ''
is-local = TRUE
on-since = '2008-04-17T08:24:28Z'
Session1:
uid = '50'
realname = 'GDM Reserved UID'
seat = 'Seat2'
session-type = 'LoginWindow'
active = FALSE
x11-display = ':0'
x11-display-device = ''
display-device = ''
remote-host-name = ''
is-local = TRUE
on-since = '2008-04-17T08:19:53Z'
Session2:
uid = '50'
realname = 'GDM Reserved UID'
seat = 'Seat3'
session-type = 'LoginWindow'
active = FALSE
x11-display = ':101'
x11-display-device = ''
display-device = ''
remote-host-name = ''
------------------------------------------------
Thanks,
-Simon
Index: utils/Makefile.am
===================================================================
--- utils/Makefile.am (revision 6155)
+++ utils/Makefile.am (working copy)
@@ -3,6 +3,7 @@ NULL =
INCLUDES = \
-I. \
-I.. \
+ -I$(top_srcdir)/common \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
$(UTILS_CFLAGS) \
$(GTK_CFLAGS) \
@@ -25,6 +26,7 @@ gdm-safe-restart: gdm-safe-restart.in Ma
bin_PROGRAMS = \
gdmflexiserver \
gdm-screenshot \
+ gdmdynamic \
$(NULL)
sbin_SCRIPTS = \
@@ -51,6 +53,16 @@ gdm_screenshot_LDADD = \
$(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 \
Index: utils/gdmdynamic.c
===================================================================
--- utils/gdmdynamic.c (revision 0)
+++ utils/gdmdynamic.c (revision 0)
@@ -0,0 +1,272 @@
+/* -*- 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_printf ("%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 verbose = FALSE;
+ gboolean background = 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 displays that match a pattern"), N_("pattern") },
+ { "background", 'b', 0, G_OPTION_ARG_NONE, &background, N_("Run in background"), NULL },
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, N_("Show extra debugging information"), 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);
+
+ g_type_init();
+
+ gdm_log_init ();
+ gdm_log_set_debug (verbose);
+
+ /*
+ * Must contain one of -a, -d, or -l.
+ */
+ 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;
+}
Index: daemon/gdm-local-display-factory.c
===================================================================
--- daemon/gdm-local-display-factory.c (revision 6155)
+++ daemon/gdm-local-display-factory.c (working copy)
@@ -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 *f
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,151 @@ gdm_local_display_factory_create_product
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);
+
+ /* FIXME: don't hardcode seat1? */
+ g_object_set (display, "seat-id", CK_SEAT1_PATH, NULL);
+
+ 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);
+ g_object_get (display, "xserver-command", &xserver_cmd, NULL);
+
+ if (xserver_cmd && g_pattern_match_simple (pattern, xserver_cmd)) {
+ /* FIXME: need to show login user name as well as display name */
+ 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,
Index: daemon/gdm-server.c
===================================================================
--- daemon/gdm-server.c (revision 6155)
+++ daemon/gdm-server.c (working copy)
@@ -730,6 +730,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,
@@ -773,6 +780,9 @@ gdm_server_set_property (GObject *o
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;
@@ -802,6 +812,9 @@ gdm_server_get_property (GObject *obj
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;
Index: daemon/gdm-local-display-factory.h
===================================================================
--- daemon/gdm-local-display-factory.h (revision 6155)
+++ daemon/gdm-local-display-factory.h (working copy)
@@ -71,6 +71,21 @@ gboolean gdm_local_dis
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 */
Index: daemon/gdm-local-display-factory.xml
===================================================================
--- daemon/gdm-local-display-factory.xml (revision 6155)
+++ daemon/gdm-local-display-factory.xml (working copy)
@@ -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>
Index: daemon/gdm-dynamic-display.c
===================================================================
--- daemon/gdm-dynamic-display.c (revision 0)
+++ daemon/gdm-dynamic-display.c (revision 0)
@@ -0,0 +1,208 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann redhat com>
+ *
+ * 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);
+}
Index: daemon/gdm-dynamic-display.h
===================================================================
--- daemon/gdm-dynamic-display.h (revision 0)
+++ daemon/gdm-dynamic-display.h (revision 0)
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann redhat com>
+ *
+ * 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 */
Index: daemon/gdm-display.c
===================================================================
--- daemon/gdm-display.c (revision 6155)
+++ daemon/gdm-display.c (working copy)
@@ -58,6 +58,8 @@ struct GdmDisplayPrivate
GTimer *slave_timer;
char *slave_command;
+ char *xserver_command;
+
char *x11_cookie;
gsize x11_cookie_size;
GdmDisplayAccessFile *access_file;
@@ -82,6 +84,7 @@ enum {
PROP_X11_AUTHORITY_FILE,
PROP_IS_LOCAL,
PROP_SLAVE_COMMAND,
+ PROP_XSERVER_COMMAND,
};
static void gdm_display_class_init (GdmDisplayClass *klass);
@@ -483,7 +486,13 @@ gdm_display_real_manage (GdmDisplay *dis
G_CALLBACK (slave_died),
display);
- command = g_strdup_printf ("%s --display-id %s",
+ if (display->priv->xserver_command)
+ 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);
@@ -703,6 +712,14 @@ _gdm_display_set_slave_command (GdmDispl
}
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,
@@ -740,6 +757,9 @@ gdm_display_set_property (GObject
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;
@@ -788,6 +808,9 @@ gdm_display_get_property (GObject
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;
@@ -970,6 +993,14 @@ gdm_display_class_init (GdmDisplayClass
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",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_type_class_add_private (klass, sizeof (GdmDisplayPrivate));
Index: daemon/simple-slave-main.c
===================================================================
--- daemon/simple-slave-main.c (revision 6155)
+++ daemon/simple-slave-main.c (working copy)
@@ -153,9 +153,11 @@ main (int argc,
DBusGConnection *connection;
GdmSlave *slave;
static char *display_id = NULL;
+ static char *xserver_command = NULL;
GdmSignalHandler *signal_handler;
static GOptionEntry entries [] = {
{ "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 }
};
@@ -213,6 +215,11 @@ 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),
Index: daemon/gdm-simple-slave.c
===================================================================
--- daemon/gdm-simple-slave.c (revision 6155)
+++ daemon/gdm-simple-slave.c (working copy)
@@ -73,6 +73,8 @@ struct GdmSimpleSlavePrivate
GPid server_pid;
guint connection_attempts;
+ char *xserver_command;
+
GdmServer *server;
GdmGreeterServer *greeter_server;
GdmGreeterSession *greeter;
@@ -84,6 +86,7 @@ struct GdmSimpleSlavePrivate
enum {
PROP_0,
+ PROP_XSERVER_COMMAND,
};
static void gdm_simple_slave_class_init (GdmSimpleSlaveClass *klass);
@@ -966,6 +969,11 @@ gdm_simple_slave_run (GdmSimpleSlave *sl
gboolean res;
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);
g_signal_connect (slave->priv->server,
"exited",
G_CALLBACK (on_server_exited),
@@ -1047,7 +1055,14 @@ gdm_simple_slave_set_property (GObject
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));
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1060,7 +1075,14 @@ gdm_simple_slave_get_property (GObject
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;
@@ -1097,6 +1119,15 @@ gdm_simple_slave_class_init (GdmSimpleSl
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_ONLY));
+
+
dbus_g_object_type_install_info (GDM_TYPE_SIMPLE_SLAVE, &dbus_glib_gdm_simple_slave_object_info);
}
Index: daemon/Makefile.am
===================================================================
--- daemon/Makefile.am (revision 6155)
+++ daemon/Makefile.am (working copy)
@@ -301,6 +301,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 \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]