1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <string.h>
27
28 #include <glib.h>
29 #include <glib/gi18n.h>
30 #include <glib-object.h>
31
32 #include "gdm-chooser-session.h"
33 #include "gdm-client.h"
34
35 #include "gdm-host-chooser-dialog.h"
36
37 #define GDM_CHOOSER_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CHOOSER_SESSION, GdmChooserSessionPrivate))
38
39 struct GdmChooserSessionPrivate
40 {
41 GdmClient *client;
42 GdmRemoteGreeter *remote_greeter;
43 GdmChooser *chooser;
44 GtkWidget *chooser_dialog;
45 };
46
47 enum {
48 PROP_0,
49 };
50
51 static void gdm_chooser_session_class_init (GdmChooserSessionClass *klass);
52 static void gdm_chooser_session_init (GdmChooserSession *chooser_session);
53 static void gdm_chooser_session_finalize (GObject *object);
54
55 G_DEFINE_TYPE (GdmChooserSession, gdm_chooser_session, G_TYPE_OBJECT)
56
57 static gpointer session_object = NULL;
58
59 static gboolean
launch_compiz(GdmChooserSession * session)60 launch_compiz (GdmChooserSession *session)
61 {
62 GError *error;
63 gboolean ret;
64
65 g_debug ("GdmChooserSession: Launching compiz");
66
67 ret = FALSE;
68
69 error = NULL;
70 g_spawn_command_line_async ("gtk-window-decorator --replace", &error);
71 if (error != NULL) {
72 g_warning ("Error starting WM: %s", error->message);
73 g_error_free (error);
74 goto out;
75 }
76
77 error = NULL;
78 g_spawn_command_line_async ("compiz --replace", &error);
79 if (error != NULL) {
80 g_warning ("Error starting WM: %s", error->message);
81 g_error_free (error);
82 goto out;
83 }
84
85 ret = TRUE;
86
87 /* FIXME: should try to detect if it actually works */
88
89 out:
90 return ret;
91 }
92
93 static gboolean
launch_metacity(GdmChooserSession * session)94 launch_metacity (GdmChooserSession *session)
95 {
96 GError *error;
97 gboolean ret;
98
99 g_debug ("GdmChooserSession: Launching metacity");
100
101 ret = FALSE;
102
103 error = NULL;
104 g_spawn_command_line_async ("metacity --replace", &error);
105 if (error != NULL) {
106 g_warning ("Error starting WM: %s", error->message);
107 g_error_free (error);
108 goto out;
109 }
110
111 ret = TRUE;
112
113 out:
114 return ret;
115 }
116
117 static void
start_window_manager(GdmChooserSession * session)118 start_window_manager (GdmChooserSession *session)
119 {
120 if (! launch_metacity (session)) {
121 launch_compiz (session);
122 }
123 }
124
125 static gboolean
start_settings_daemon(GdmChooserSession * session)126 start_settings_daemon (GdmChooserSession *session)
127 {
128 GError *error;
129 gboolean ret;
130
131 g_debug ("GdmChooserSession: Launching settings daemon");
132
133 ret = FALSE;
134
135 error = NULL;
136 g_spawn_command_line_async (GNOME_SETTINGS_DAEMON_DIR "/gnome-settings-daemon", &error);
137 if (error != NULL) {
138 g_warning ("Error starting settings daemon: %s", error->message);
139 g_error_free (error);
140 goto out;
141 }
142
143 ret = TRUE;
144
145 out:
146 return ret;
147 }
148
149 static void
on_dialog_response(GtkDialog * dialog,int response_id,GdmChooserSession * session)150 on_dialog_response (GtkDialog *dialog,
151 int response_id,
152 GdmChooserSession *session)
153 {
154 GdmChooserHost *host;
155 GError *error = NULL;
156
157 host = NULL;
158 switch (response_id) {
159 case GTK_RESPONSE_OK:
160 host = gdm_host_chooser_dialog_get_host (GDM_HOST_CHOOSER_DIALOG (dialog));
161 case GTK_RESPONSE_NONE:
162 /* delete event */
163 default:
164 break;
165 }
166
167 if (host != NULL) {
168 char *hostname;
169
170 /* only support XDMCP hosts in remote chooser */
171 g_assert (gdm_chooser_host_get_kind (host) == GDM_CHOOSER_HOST_KIND_XDMCP);
172
173 hostname = NULL;
174 gdm_address_get_hostname (gdm_chooser_host_get_address (host), &hostname);
175 /* FIXME: fall back to numerical address? */
176 if (hostname != NULL) {
177 g_debug ("GdmChooserSession: Selected hostname '%s'", hostname);
178 gdm_chooser_call_select_hostname_sync (session->priv->chooser,
179 hostname,
180 NULL,
181 &error);
182
183 if (error != NULL) {
184 g_debug ("GdmChooserSession: %s", error->message);
185 g_clear_error (&error);
186 }
187 g_free (hostname);
188 }
189 }
190
191 gdm_remote_greeter_call_disconnect_sync (session->priv->remote_greeter,
192 NULL,
193 &error);
194 if (error != NULL) {
195 g_debug ("GdmChooserSession: disconnect failed: %s", error->message);
196 }
197 }
198
199 gboolean
gdm_chooser_session_start(GdmChooserSession * session,GError ** error)200 gdm_chooser_session_start (GdmChooserSession *session,
201 GError **error)
202 {
203 g_return_val_if_fail (GDM_IS_CHOOSER_SESSION (session), FALSE);
204
205 session->priv->remote_greeter = gdm_client_get_remote_greeter_sync (session->priv->client,
206 NULL,
207 error);
208 if (session->priv->remote_greeter == NULL) {
209 return FALSE;
210 }
211
212 session->priv->chooser = gdm_client_get_chooser_sync (session->priv->client,
213 NULL,
214 error);
215 if (session->priv->chooser == NULL) {
216 return FALSE;
217 }
218
219 start_settings_daemon (session);
220 start_window_manager (session);
221
222 /* Only support XDMCP on remote choosers */
223 session->priv->chooser_dialog = gdm_host_chooser_dialog_new (GDM_CHOOSER_HOST_KIND_XDMCP);
224 g_signal_connect (session->priv->chooser_dialog,
225 "response",
226 G_CALLBACK (on_dialog_response),
227 session);
228 gtk_widget_show (session->priv->chooser_dialog);
229
230 return TRUE;
231 }
232
233 void
gdm_chooser_session_stop(GdmChooserSession * session)234 gdm_chooser_session_stop (GdmChooserSession *session)
235 {
236 g_return_if_fail (GDM_IS_CHOOSER_SESSION (session));
237
238 }
239
240 static void
gdm_chooser_session_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)241 gdm_chooser_session_set_property (GObject *object,
242 guint prop_id,
243 const GValue *value,
244 GParamSpec *pspec)
245 {
246 switch (prop_id) {
247 default:
248 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
249 break;
250 }
251 }
252
253 static void
gdm_chooser_session_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)254 gdm_chooser_session_get_property (GObject *object,
255 guint prop_id,
256 GValue *value,
257 GParamSpec *pspec)
258 {
259 switch (prop_id) {
260 default:
261 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
262 break;
263 }
264 }
265
266 static GObject *
gdm_chooser_session_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)267 gdm_chooser_session_constructor (GType type,
268 guint n_construct_properties,
269 GObjectConstructParam *construct_properties)
270 {
271 GdmChooserSession *chooser_session;
272
273 chooser_session = GDM_CHOOSER_SESSION (G_OBJECT_CLASS (gdm_chooser_session_parent_class)->constructor (type,
274 n_construct_properties,
275 construct_properties));
276
277 return G_OBJECT (chooser_session);
278 }
279
280 static void
gdm_chooser_session_dispose(GObject * object)281 gdm_chooser_session_dispose (GObject *object)
282 {
283 g_debug ("GdmChooserSession: Disposing chooser_session");
284
285 G_OBJECT_CLASS (gdm_chooser_session_parent_class)->dispose (object);
286 }
287
288 static void
gdm_chooser_session_class_init(GdmChooserSessionClass * klass)289 gdm_chooser_session_class_init (GdmChooserSessionClass *klass)
290 {
291 GObjectClass *object_class = G_OBJECT_CLASS (klass);
292
293 object_class->get_property = gdm_chooser_session_get_property;
294 object_class->set_property = gdm_chooser_session_set_property;
295 object_class->constructor = gdm_chooser_session_constructor;
296 object_class->dispose = gdm_chooser_session_dispose;
297 object_class->finalize = gdm_chooser_session_finalize;
298
299 g_type_class_add_private (klass, sizeof (GdmChooserSessionPrivate));
300 }
301
302 static void
gdm_chooser_session_init(GdmChooserSession * session)303 gdm_chooser_session_init (GdmChooserSession *session)
304 {
305
306 session->priv = GDM_CHOOSER_SESSION_GET_PRIVATE (session);
307
308 session->priv->client = gdm_client_new ();
309 }
310
311 static void
gdm_chooser_session_finalize(GObject * object)312 gdm_chooser_session_finalize (GObject *object)
313 {
314 GdmChooserSession *chooser_session;
315
316 g_return_if_fail (object != NULL);
317 g_return_if_fail (GDM_IS_CHOOSER_SESSION (object));
318
319 chooser_session = GDM_CHOOSER_SESSION (object);
320
321 g_return_if_fail (chooser_session->priv != NULL);
322
323 g_clear_object (&chooser_session->priv->chooser);
324 g_clear_object (&chooser_session->priv->remote_greeter);
325 g_clear_object (&chooser_session->priv->client);
326
327 G_OBJECT_CLASS (gdm_chooser_session_parent_class)->finalize (object);
328 }
329
330 GdmChooserSession *
gdm_chooser_session_new(void)331 gdm_chooser_session_new (void)
332 {
333 if (session_object != NULL) {
334 g_object_ref (session_object);
335 } else {
336 session_object = g_object_new (GDM_TYPE_CHOOSER_SESSION, NULL);
337 g_object_add_weak_pointer (session_object,
338 (gpointer *) &session_object);
339 }
340
341 return GDM_CHOOSER_SESSION (session_object);
342 }
343