]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
Add session support
authorunknown <robert.ancell@gmail.com>
Mon, 3 May 2010 06:06:06 +0000 (16:06 +1000)
committerunknown <robert.ancell@gmail.com>
Mon, 3 May 2010 06:06:06 +0000 (16:06 +1000)
.bzrignore
data/org.gnome.LightDisplayManager.conf
src/Makefile.am
src/greeter.c
src/greeter.h
src/ldmgreeter.c
src/lightdm.c
src/session-manager.c [new file with mode: 0644]
src/session-manager.h [new file with mode: 0644]
src/session-manager.xml [new file with mode: 0644]

index e11d94211e37ca6e421f97c7ca182f950695892f..1f625aa69ac12266d078e5f69a454cf4f29cd6f9 100644 (file)
@@ -17,7 +17,9 @@ xmldocs.make
 po/stamp-it
 po/POTFILES
 src/lightdm
-src/display-glue.h
 src/ldmgreeter
 src/ldmgreeter
+src/display-glue.h
 src/display-manager-glue.h
+src/user-manager-glue.h
+src/session-manager-glue.h
index 7290f62531c54d85ccd8187536efacfd9246acb9..8790313fd7ae16d9187e7baebcec56a93c2356bf 100644 (file)
@@ -19,6 +19,7 @@
     <allow send_destination="org.gnome.LightDisplayManager" send_interface="org.gnome.LightDisplayManager"/>
     <allow send_destination="org.gnome.LightDisplayManager" send_interface="org.gnome.LightDisplayManager.Display"/>
     <allow send_destination="org.gnome.LightDisplayManager" send_interface="org.gnome.LightDisplayManager.Users"/>
+    <allow send_destination="org.gnome.LightDisplayManager" send_interface="org.gnome.LightDisplayManager.Session"/>
   </policy>
 
 </busconfig>
index 7f5214d06205ad3c6b85f2c96f93c7c9789f4bd9..1838986dd9647f7577ad723f9608a1c91f5fa41b 100644 (file)
@@ -4,6 +4,8 @@ display-glue.h: display.xml
        $(DBUSBINDINGTOOL) --prefix=display --mode=glib-server --output=$@ $^
 display-manager-glue.h: display-manager.xml
        $(DBUSBINDINGTOOL) --prefix=display_manager --mode=glib-server --output=$@ $^
+session-manager-glue.h: session-manager.xml
+       $(DBUSBINDINGTOOL) --prefix=session_manager --mode=glib-server --output=$@ $^
 user-manager-glue.h: user-manager.xml
        $(DBUSBINDINGTOOL) --prefix=user_manager --mode=glib-server --output=$@ $^
 
@@ -15,6 +17,8 @@ lightdm_SOURCES = \
        lightdm.c \
        pam-session.c \
        pam-session.h \
+       session-manager.c \
+       session-manager.h \
        user-manager.c \
        user-manager.h
 
@@ -26,6 +30,7 @@ ldmgreeter_SOURCES = \
 BUILT_SOURCES = \
        display-glue.h \
        display-manager-glue.h \
+       session-manager-glue.h \
        user-manager-glue.h
 
 lightdm_CFLAGS = \
@@ -34,6 +39,7 @@ lightdm_CFLAGS = \
        -DVERSION=\"$(VERSION)\" \
        -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
        -DLOCALE_DIR=\"$(localedir)\" \
+       -DXSESSIONS_DIR=\"$(prefix)/share/xsessions\" \
        -DGREETER_USER=\"gdm\" \
        -DGREETER_BINARY=\"$(prefix)/bin/ldmgreeter\" \
        -DLIGHTDM_BINARY=\"lightdm\"
index 896ed3fc76509e1021038947ca6c7f4845e81c62..fd11d61d7b4f384d5234f128b84b234bf478a236 100644 (file)
@@ -27,11 +27,14 @@ struct GreeterPrivate
 {
     DBusGConnection *bus;
 
-    DBusGProxy *display_proxy, *user_proxy;
+    DBusGProxy *display_proxy, *session_proxy, *user_proxy;
 
     gboolean have_users;
     GList *users;
 
+    gboolean have_sessions;
+    GList *sessions;
+
     gboolean is_authenticated;
 };
 
@@ -130,6 +133,59 @@ greeter_get_users (Greeter *greeter)
     return greeter->priv->users;
 }
 
+#define TYPE_SESSION dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID)
+#define TYPE_SESSION_LIST dbus_g_type_get_collection ("GPtrArray", TYPE_SESSION)
+
+static void
+update_sessions (Greeter *greeter)
+{
+    GPtrArray *sessions;
+    gboolean result;
+    gint i;
+    GError *error = NULL;
+
+    if (greeter->priv->have_sessions)
+        return;
+
+    result = dbus_g_proxy_call (greeter->priv->session_proxy, "GetSessions", &error,
+                                G_TYPE_INVALID,
+                                TYPE_SESSION_LIST, &sessions,
+                                G_TYPE_INVALID);
+    if (!result)
+        g_warning ("Failed to get sessions: %s", error->message);
+    g_clear_error (&error);
+  
+    if (!result)
+        return;
+  
+    for (i = 0; i < sessions->len; i++)
+    {
+        GValue value = { 0 };
+        Session *session;
+      
+        session = g_malloc0 (sizeof (Session));
+      
+        g_value_init (&value, TYPE_SESSION);
+        g_value_set_static_boxed (&value, sessions->pdata[i]);
+        dbus_g_type_struct_get (&value, 0, &session->name, 1, &session->comment, G_MAXUINT);
+
+        g_value_unset (&value);
+
+        greeter->priv->sessions = g_list_append (greeter->priv->sessions, session);
+    }
+
+    g_ptr_array_free (sessions, TRUE);
+
+    greeter->priv->have_sessions = TRUE;
+}
+
+const GList *
+greeter_get_sessions (Greeter *greeter)
+{
+    update_sessions (greeter);
+    return greeter->priv->sessions;
+}
+
 #define TYPE_MESSAGE dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID)
 #define TYPE_MESSAGE_LIST dbus_g_type_get_collection ("GPtrArray", TYPE_MESSAGE)
 
@@ -234,6 +290,10 @@ greeter_init (Greeter *greeter)
                                                               "org.gnome.LightDisplayManager",
                                                               "/org/gnome/LightDisplayManager/Display",
                                                               "org.gnome.LightDisplayManager.Greeter");
+    greeter->priv->session_proxy = dbus_g_proxy_new_for_name (greeter->priv->bus,
+                                                              "org.gnome.LightDisplayManager",
+                                                              "/org/gnome/LightDisplayManager/Session",
+                                                              "org.gnome.LightDisplayManager.Session");
     greeter->priv->user_proxy = dbus_g_proxy_new_for_name (greeter->priv->bus,
                                                            "org.gnome.LightDisplayManager",
                                                            "/org/gnome/LightDisplayManager/Users",
index 88ce550c45ce2a2178ebfcf3a893d7e99ba8e74d..8b1c775bcc03a05f2d7ab175dee34d0b64ce91ea 100644 (file)
@@ -43,6 +43,12 @@ typedef struct
    const char *real_name;
 } UserInfo;
 
+typedef struct
+{
+   const char *name;
+   const char *comment;
+} Session;
+
 GType greeter_get_type (void);
 
 Greeter *greeter_new (void);
@@ -53,6 +59,8 @@ gint greeter_get_num_users (Greeter *greeter);
 
 const GList *greeter_get_users (Greeter *greeter);
 
+const GList *greeter_get_sessions (Greeter *greeter);
+
 void greeter_start_authentication (Greeter *greeter, const char *username);
 
 void greeter_provide_secret (Greeter *greeter, const gchar *secret);
index feb0eed4b894b003b9137a4b601b806f9d826e84..31e0ce98c0b94ab5a99237c248dc39e3f3c6422c 100644 (file)
 #include "greeter.h"
 
 static Greeter *greeter;
-static GtkListStore *user_model;
-static GtkWidget *user_window, *vbox, *label, *user_view, *username_entry, *password_entry;
+static GtkListStore *session_model, *user_model;
+static GtkWidget *user_window, *vbox, *label, *user_view;
+static GtkWidget *username_entry, *password_entry;
+static GtkWidget *session_combo;
 static GtkWidget *panel_window;
 
 static void
@@ -73,7 +75,7 @@ authentication_complete_cb (Greeter *greeter)
 int
 main(int argc, char **argv)
 {
-    const GList *users, *link;
+    const GList *sessions, *users, *link;
     GtkCellRenderer *renderer;
     GdkDisplay *display;
     GdkScreen *screen;
@@ -143,6 +145,26 @@ main(int argc, char **argv)
     gtk_widget_set_sensitive (password_entry, FALSE);
     gtk_box_pack_start (GTK_BOX (vbox), password_entry, FALSE, FALSE, 0);
     g_signal_connect (password_entry, "activate", G_CALLBACK (password_activate_cb), NULL);
+
+    session_model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    sessions = greeter_get_sessions (greeter);
+    for (link = sessions; link; link = link->next)
+    {
+        Session *session = link->data;
+        GtkTreeIter iter;
+      
+        gtk_list_store_append (GTK_LIST_STORE (session_model), &iter);
+        gtk_list_store_set (GTK_LIST_STORE (session_model), &iter,
+                            0, session->name,
+                            1, session->name,
+                            -1);
+    }
+
+    session_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (session_model));
+    renderer = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (session_combo), renderer, TRUE);
+    gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (session_combo), renderer, "text", 1);
+    gtk_box_pack_start (GTK_BOX (vbox), session_combo, FALSE, FALSE, 0);    
   
     gtk_widget_show_all (user_window);
   
index 7a48633576653e8df47fa7d00c477d88b1ee907f..3f8bc5813e38a7f12dcacdf3394a6685eff9ee2b 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "display-manager.h"
 #include "user-manager.h"
+#include "session-manager.h"
 
 static GMainLoop *loop;
 static gboolean debug = FALSE;
@@ -90,6 +91,7 @@ main(int argc, char **argv)
 {
     DisplayManager *display_manager;
     UserManager *user_manager;
+    SessionManager *session_manager;
     DBusGConnection *bus;
     struct sigaction action;
     GError *error = NULL;
@@ -129,6 +131,9 @@ main(int argc, char **argv)
     user_manager = user_manager_new ();
     dbus_g_connection_register_g_object (bus, "/org/gnome/LightDisplayManager/Users", G_OBJECT (user_manager));
 
+    session_manager = session_manager_new ();
+    dbus_g_connection_register_g_object (bus, "/org/gnome/LightDisplayManager/Session", G_OBJECT (session_manager));
+
     display_manager = display_manager_new ();
     dbus_g_connection_register_g_object (bus, "/org/gnome/LightDisplayManager", G_OBJECT (display_manager));
 
diff --git a/src/session-manager.c b/src/session-manager.c
new file mode 100644 (file)
index 0000000..4f51721
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2010 Robert Ancell.
+ * Author: Robert Ancell <robert.ancell@canonical.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 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include "session-manager.h"
+#include "session-manager-glue.h"
+
+struct SessionManagerPrivate
+{
+    gboolean sessions_loaded;
+    GList *sessions;
+};
+
+G_DEFINE_TYPE (SessionManager, session_manager, G_TYPE_OBJECT);
+
+SessionManager *
+session_manager_new (void)
+{
+    return g_object_new (SESSION_MANAGER_TYPE, NULL);
+}
+
+static void
+session_free (Session *session)
+{
+    g_free (session->name);
+    g_free (session->comment);
+    g_free (session->exec);
+    g_free (session);
+}
+
+static Session *
+load_session (GKeyFile *key_file, GError **error)
+{
+    Session *session;
+  
+    session = g_malloc0 (sizeof (Session));
+
+    session->name = g_key_file_get_locale_string(key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, NULL, error);
+    if (!session->name)
+    {
+        session_free (session);
+        return NULL;
+    }
+
+    session->comment = g_key_file_get_locale_string(key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, NULL, error);
+    if (!session->comment)
+    {
+        session_free (session);
+        return NULL;
+    }
+
+    session->exec = g_key_file_get_value(key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, error);
+    if (!session->exec)
+    {
+        session_free (session);
+        return NULL;
+    }
+
+    return session;
+}
+
+static void
+load_sessions (SessionManager *manager)
+{
+    GDir *directory;
+    GError *error = NULL;
+    GKeyFile *key_file;
+
+    if (manager->priv->sessions_loaded)
+        return;
+
+    directory = g_dir_open (XSESSIONS_DIR, 0, &error);
+    if (!directory)
+        g_warning ("Failed to open sessions directory: %s", error->message);
+    g_clear_error (&error);
+    if (!directory)
+        return;
+
+    key_file = g_key_file_new ();
+    while (TRUE)
+    {
+        const gchar *filename;
+        gchar *path;
+        gboolean result;
+        Session *session;
+
+        filename = g_dir_read_name (directory);
+        if (filename == NULL)
+            break;
+
+        if (!g_str_has_suffix (filename, ".desktop"))
+            continue;
+
+        path = g_build_filename (XSESSIONS_DIR, filename, NULL);
+        g_debug ("Loading session %s", path);
+
+        result = g_key_file_load_from_file(key_file, path, G_KEY_FILE_NONE, &error);
+        if (!result)
+            g_warning ("Failed to load session file %s: %s:", path, error->message);
+        g_clear_error (&error);
+
+        if (result)
+        {
+            session = load_session (key_file, &error);
+            if (session)
+            {
+                g_debug ("Loaded session %s (%s)", session->name, session->comment);
+                manager->priv->sessions = g_list_append (manager->priv->sessions, session);
+            }
+            else
+                g_warning ("Invalid session %s: %s", path, error->message);
+            g_clear_error (&error);
+        }
+
+        g_free (path);
+    }
+
+    g_dir_close (directory);
+    g_key_file_free (key_file);
+
+    manager->priv->sessions_loaded = TRUE;
+}
+
+#define TYPE_SESSION dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID)
+
+gboolean
+session_manager_get_sessions (SessionManager *manager, GPtrArray **sessions, GError *error)
+{
+    GList *link;
+
+    load_sessions (manager);
+
+    *sessions = g_ptr_array_sized_new (g_list_length (manager->priv->sessions));
+    for (link = manager->priv->sessions; link; link = link->next)
+    {
+        Session *session = link->data;
+        GValue value = { 0 };
+
+        g_value_init (&value, TYPE_SESSION);
+        g_value_take_boxed (&value, dbus_g_type_specialized_construct (TYPE_SESSION));
+        dbus_g_type_struct_set (&value, 0, session->name, 1, session->comment, G_MAXUINT);
+        g_ptr_array_add (*sessions, g_value_get_boxed (&value));
+    }
+
+    return TRUE;
+}
+
+static void
+session_manager_init (SessionManager *manager)
+{
+    manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, SESSION_MANAGER_TYPE, SessionManagerPrivate);
+}
+
+static void
+session_manager_class_init (SessionManagerClass *klass)
+{
+    g_type_class_add_private (klass, sizeof (SessionManagerPrivate));
+
+    dbus_g_object_type_install_info (SESSION_MANAGER_TYPE, &dbus_glib_session_manager_object_info);
+}
diff --git a/src/session-manager.h b/src/session-manager.h
new file mode 100644 (file)
index 0000000..050d3fb
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Robert Ancell.
+ * Author: Robert Ancell <robert.ancell@canonical.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 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#ifndef _SESSION_MANAGER_H_
+#define _SESSION_MANAGER_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define SESSION_MANAGER_TYPE (session_manager_get_type())
+#define SESSION_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SESSION_MANAGER_TYPE, SessionManager));
+
+typedef struct SessionManagerPrivate SessionManagerPrivate;
+
+typedef struct
+{
+    GObject         parent_instance;
+    SessionManagerPrivate *priv;
+} SessionManager;
+
+typedef struct
+{
+    GObjectClass parent_class;
+} SessionManagerClass;
+
+typedef struct
+{
+    char *name;
+    char *comment;
+    char *exec;
+} Session;
+
+GType session_manager_get_type (void);
+
+SessionManager *session_manager_new (void);
+
+gboolean session_manager_get_sessions (SessionManager *manager, GPtrArray **sessions, GError *error);
+
+G_END_DECLS
+
+#endif /* _SESSION_MANAGER_H_ */
diff --git a/src/session-manager.xml b/src/session-manager.xml
new file mode 100644 (file)
index 0000000..be04f6a
--- /dev/null
@@ -0,0 +1,11 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+  <interface name="org.gnome.LightDisplayManager.Session">
+
+    <!-- Method to return the users -->
+    <method name="GetSessions">
+      <arg name="users" direction="out" type="a(ss)"/>
+    </method>
+
+  </interface>
+</node>