source: proiecte/PPPP/gdm/gui/simple-greeter/gdm-greeter-login-window.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 68.8 KB
Line 
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 * Copyright (C) 2008 Red Hat, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include "config.h"
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <fcntl.h>
27#include <unistd.h>
28#include <string.h>
29#include <signal.h>
30#include <sys/stat.h>
31#include <sys/types.h>
32#include <sys/socket.h>
33#include <sys/time.h>
34#include <errno.h>
35#include <pwd.h>
36
37#ifdef ENABLE_RBAC_SHUTDOWN
38#include <auth_attr.h>
39#include <secdb.h>
40#endif
41
42#include <glib.h>
43#include <glib/gi18n.h>
44#include <glib/gstdio.h>
45#include <glib-object.h>
46
47#include <gdk/gdkkeysyms.h>
48#include <gdk/gdkx.h>
49#include <X11/XKBlib.h>
50
51#include <gst/gst.h>
52#include <gtk/gtk.h>
53#include <gst/interfaces/xoverlay.h>
54
55#include <glade/glade-xml.h>
56#include <gconf/gconf-client.h>
57
58#include <dbus/dbus-glib.h>
59#include <dbus/dbus-glib-lowlevel.h>
60
61#ifdef HAVE_DEVICEKIT_POWER
62#include <devkit-power-gobject/devicekit-power.h>
63#endif
64
65#include "gdm-settings-client.h"
66#include "gdm-settings-keys.h"
67#include "gdm-profile.h"
68
69#include "gdm-greeter-login-window.h"
70#include "gdm-user-chooser-widget.h"
71
72#ifdef HAVE_PAM
73#include <security/pam_appl.h>
74#define PW_ENTRY_SIZE PAM_MAX_RESP_SIZE
75#else
76#define PW_ENTRY_SIZE GDM_MAX_PASS
77#endif
78
79#define CK_NAME      "org.freedesktop.ConsoleKit"
80#define CK_PATH      "/org/freedesktop/ConsoleKit"
81#define CK_INTERFACE "org.freedesktop.ConsoleKit"
82
83#define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
84#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
85#define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
86#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
87
88#define GLADE_XML_FILE       "gdm-greeter-login-window.glade"
89
90#define KEY_GREETER_DIR             "/apps/gdm/simple-greeter"
91#define KEY_BANNER_MESSAGE_ENABLED  KEY_GREETER_DIR "/banner_message_enable"
92#define KEY_BANNER_MESSAGE_TEXT     KEY_GREETER_DIR "/banner_message_text"
93#define KEY_BANNER_MESSAGE_TEXT_NOCHOOSER     KEY_GREETER_DIR "/banner_message_text_nochooser"
94#define KEY_LOGO                    KEY_GREETER_DIR "/logo_icon_name"
95#define KEY_DISABLE_RESTART_BUTTONS KEY_GREETER_DIR "/disable_restart_buttons"
96#define GDM_GREETER_LOGIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_LOGIN_WINDOW, GdmGreeterLoginWindowPrivate))
97
98enum {
99        MODE_SELECTION = 0,
100        MODE_AUTHENTICATION
101};
102
103enum {
104        LOGIN_BUTTON_HIDDEN = 0,
105        LOGIN_BUTTON_START_OTHER,
106        LOGIN_BUTTON_ANSWER_QUERY,
107        LOGIN_BUTTON_TIMED_LOGIN
108};
109
110struct GdmGreeterLoginWindowPrivate
111{
112        GladeXML        *xml;
113        GtkWidget       *user_chooser;
114        GtkWidget       *auth_banner_label;
115        guint            display_is_local : 1;
116        guint            is_interactive : 1;
117        guint            user_chooser_loaded : 1;
118        GConfClient     *client;
119
120        gboolean         banner_message_enabled;
121        guint            gconf_cnxn;
122
123        guint            dialog_mode;
124
125        gboolean         timed_login_enabled;
126        guint            timed_login_delay;
127        char            *timed_login_username;
128        guint            timed_login_timeout_id;
129
130        guint            sensitize_power_buttons_timeout_id;
131
132        guint            login_button_handler_id;
133        guint            start_session_handler_id;
134};
135
136enum {
137        PROP_0,
138        PROP_DISPLAY_IS_LOCAL,
139        PROP_IS_INTERACTIVE,
140};
141
142enum {
143        BEGIN_AUTO_LOGIN,
144        BEGIN_VERIFICATION,
145        BEGIN_VERIFICATION_FOR_USER,
146        QUERY_ANSWER,
147        START_SESSION,
148        USER_SELECTED,
149        DISCONNECTED,
150        CANCELLED,
151        LAST_SIGNAL
152};
153
154static guint signals [LAST_SIGNAL] = { 0, };
155static GstElement * pipeline;
156
157static void     gdm_greeter_login_window_class_init   (GdmGreeterLoginWindowClass *klass);
158static void     gdm_greeter_login_window_init         (GdmGreeterLoginWindow      *greeter_login_window);
159static void     gdm_greeter_login_window_finalize     (GObject                    *object);
160
161static void     restart_timed_login_timeout (GdmGreeterLoginWindow *login_window);
162static void     on_user_unchosen            (GdmUserChooserWidget *user_chooser,
163                                             GdmGreeterLoginWindow *login_window);
164
165static void     switch_mode                 (GdmGreeterLoginWindow *login_window,
166                                             int                    number);
167static void     update_banner_message       (GdmGreeterLoginWindow *login_window);
168
169G_DEFINE_TYPE (GdmGreeterLoginWindow, gdm_greeter_login_window, GTK_TYPE_WINDOW)
170
171static void
172set_busy (GdmGreeterLoginWindow *login_window)
173{
174        GdkCursor *cursor;
175
176        cursor = gdk_cursor_new (GDK_WATCH);
177        gdk_window_set_cursor (GTK_WIDGET (login_window)->window, cursor);
178        gdk_cursor_unref (cursor);
179}
180
181static void
182set_ready (GdmGreeterLoginWindow *login_window)
183{
184        gdk_window_set_cursor (GTK_WIDGET (login_window)->window, NULL);
185}
186
187static void
188set_sensitive (GdmGreeterLoginWindow *login_window,
189               gboolean               sensitive)
190{
191        GtkWidget *box;
192
193        box = glade_xml_get_widget (login_window->priv->xml, "auth-input-box");
194        gtk_widget_set_sensitive (box, sensitive);
195
196        box = glade_xml_get_widget (login_window->priv->xml, "buttonbox");
197        gtk_widget_set_sensitive (box, sensitive);
198
199        gtk_widget_set_sensitive (login_window->priv->user_chooser, sensitive);
200}
201
202static void
203set_focus (GdmGreeterLoginWindow *login_window)
204{
205        GtkWidget *entry;
206
207        entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry");
208
209        gdk_window_focus (GTK_WIDGET (login_window)->window, GDK_CURRENT_TIME);
210
211        if (GTK_WIDGET_REALIZED (entry) && ! GTK_WIDGET_HAS_FOCUS (entry)) {
212                gtk_widget_grab_focus (entry);
213        } else if (GTK_WIDGET_REALIZED (login_window->priv->user_chooser) && ! GTK_WIDGET_HAS_FOCUS (login_window->priv->user_chooser)) {
214                gtk_widget_grab_focus (login_window->priv->user_chooser);
215        }
216}
217
218static void
219set_message (GdmGreeterLoginWindow *login_window,
220             const char            *text)
221{
222        GtkWidget *label;
223
224        label = glade_xml_get_widget (login_window->priv->xml, "auth-message-label");
225        gtk_label_set_text (GTK_LABEL (label), text);
226}
227
228static void
229on_user_interaction (GdmGreeterLoginWindow *login_window)
230{
231        g_debug ("GdmGreeterLoginWindow: user is interacting with session!\n");
232        restart_timed_login_timeout (login_window);
233}
234
235static GdkFilterReturn
236on_xevent (XEvent                *xevent,
237           GdkEvent              *event,
238           GdmGreeterLoginWindow *login_window)
239{
240        switch (xevent->xany.type) {
241                case KeyPress:
242                case KeyRelease:
243                case ButtonPress:
244                case ButtonRelease:
245                        on_user_interaction (login_window);
246                        break;
247                case  PropertyNotify:
248                        if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("_NET_WM_USER_TIME")) {
249                                on_user_interaction (login_window);
250                        }
251                        break;
252
253                default:
254                        break;
255        }
256
257        return GDK_FILTER_CONTINUE;
258}
259
260static void
261stop_watching_for_user_interaction (GdmGreeterLoginWindow *login_window)
262{
263        gdk_window_remove_filter (NULL,
264                                  (GdkFilterFunc) on_xevent,
265                                  login_window);
266}
267
268static void
269remove_timed_login_timeout (GdmGreeterLoginWindow *login_window)
270{
271        if (login_window->priv->timed_login_timeout_id > 0) {
272                g_debug ("GdmGreeterLoginWindow: removing timed login timer");
273                g_source_remove (login_window->priv->timed_login_timeout_id);
274                login_window->priv->timed_login_timeout_id = 0;
275        }
276
277        stop_watching_for_user_interaction (login_window);
278}
279
280static void
281_gdm_greeter_login_window_set_interactive (GdmGreeterLoginWindow *login_window,
282                                           gboolean               is_interactive)
283{
284        if (login_window->priv->is_interactive != is_interactive) {
285                login_window->priv->is_interactive = is_interactive;
286                g_object_notify (G_OBJECT (login_window), "is-interactive");
287        }
288}
289
290static gboolean
291timed_login_timer (GdmGreeterLoginWindow *login_window)
292{
293        set_sensitive (login_window, FALSE);
294        set_message (login_window, _("Automatically logging in..."));
295
296        g_debug ("GdmGreeterLoginWindow: timer expired");
297        _gdm_greeter_login_window_set_interactive (login_window, TRUE);
298        login_window->priv->timed_login_timeout_id = 0;
299
300        return FALSE;
301}
302
303static void
304watch_for_user_interaction (GdmGreeterLoginWindow *login_window)
305{
306        gdk_window_add_filter (NULL,
307                               (GdkFilterFunc) on_xevent,
308                               login_window);
309}
310
311static void
312restart_timed_login_timeout (GdmGreeterLoginWindow *login_window)
313{
314        remove_timed_login_timeout (login_window);
315
316        if (login_window->priv->timed_login_enabled) {
317                g_debug ("GdmGreeterLoginWindow: adding timed login timer");
318                watch_for_user_interaction (login_window);
319                login_window->priv->timed_login_timeout_id = g_timeout_add_seconds (login_window->priv->timed_login_delay,
320                                                                                    (GSourceFunc)timed_login_timer,
321                                                                                    login_window);
322
323                gdm_chooser_widget_set_item_timer (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser),
324                                                   GDM_USER_CHOOSER_USER_AUTO,
325                                                   login_window->priv->timed_login_delay * 1000);
326        }
327}
328
329static void
330show_widget (GdmGreeterLoginWindow *login_window,
331             const char            *name,
332             gboolean               visible)
333{
334        GtkWidget *widget;
335
336        widget = glade_xml_get_widget (login_window->priv->xml, name);
337        if (widget != NULL) {
338                if (visible) {
339                        gtk_widget_show (widget);
340                } else {
341                        gtk_widget_hide (widget);
342                }
343        }
344}
345
346static void
347sensitize_widget (GdmGreeterLoginWindow *login_window,
348                  const char            *name,
349                  gboolean               sense)
350{
351        GtkWidget *widget;
352
353        widget = glade_xml_get_widget (login_window->priv->xml, name);
354        if (widget != NULL) {
355                gtk_widget_set_sensitive (widget, sense);
356        }
357}
358
359static gboolean
360get_show_restart_buttons (GdmGreeterLoginWindow *login_window)
361{
362        gboolean     show;
363        GError      *error;
364
365        error = NULL;
366        show = ! gconf_client_get_bool (login_window->priv->client, KEY_DISABLE_RESTART_BUTTONS, &error);
367        if (error != NULL) {
368                g_debug ("GdmGreeterLoginWindow: unable to get disable-restart-buttons configuration: %s", error->message);
369                g_error_free (error);
370        }
371
372#ifdef ENABLE_RBAC_SHUTDOWN
373        {
374                char *username;
375
376                username = g_get_user_name ();
377                if (username == NULL || !chkauthattr (RBAC_SHUTDOWN_KEY, username)) {
378                        show = FALSE;
379                        g_debug ("GdmGreeterLoginWindow: Not showing stop/restart buttons for user %s due to RBAC key %s",
380                                 username, RBAC_SHUTDOWN_KEY);
381                } else {
382                        g_debug ("GdmGreeterLoginWindow: Showing stop/restart buttons for user %s due to RBAC key %s",
383                                 username, RBAC_SHUTDOWN_KEY);
384                }
385        }
386#endif
387        return show;
388}
389
390static void
391on_login_button_clicked_answer_query (GtkButton             *button,
392                                      GdmGreeterLoginWindow *login_window)
393{
394        GtkWidget  *entry;
395        const char *text;
396
397        set_busy (login_window);
398        set_sensitive (login_window, FALSE);
399
400        entry = glade_xml_get_widget (login_window->priv->xml, "auth-prompt-entry");
401        text = gtk_entry_get_text (GTK_ENTRY (entry));
402
403        _gdm_greeter_login_window_set_interactive (login_window, TRUE);
404        g_signal_emit (login_window, signals[QUERY_ANSWER], 0, text);
405}
406
407static void
408on_login_button_clicked_timed_login (GtkButton             *button,
409                                     GdmGreeterLoginWindow *login_window)
410{
411        set_busy (login_window);
412        set_sensitive (login_window, FALSE);
413
414        _gdm_greeter_login_window_set_interactive (login_window, TRUE);
415}
416static void
417on_login_button_clicked_start_other (GtkButton             *button,
418                                     GdmGreeterLoginWindow *login_window)
419{
420        g_debug ("GdmGreeterLoginWindow: starting OTHER login");
421
422        g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED],
423                       0, GDM_USER_CHOOSER_USER_OTHER);
424        g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0);
425        switch_mode (login_window, MODE_AUTHENTICATION);
426}
427
428static void
429set_log_in_button_mode (GdmGreeterLoginWindow *login_window,
430                        int                    mode)
431{
432        GtkWidget *button;
433
434        button = glade_xml_get_widget (login_window->priv->xml, "log-in-button");
435        gtk_widget_grab_default (button);
436
437        /* disconnect any signals */
438        if (login_window->priv->login_button_handler_id > 0) {
439                g_signal_handler_disconnect (button, login_window->priv->login_button_handler_id);
440                login_window->priv->login_button_handler_id = 0;
441       }
442
443        switch (mode) {
444        case LOGIN_BUTTON_HIDDEN:
445                gtk_widget_hide (button);
446                break;
447        case LOGIN_BUTTON_START_OTHER:
448                login_window->priv->login_button_handler_id = g_signal_connect (button, "clicked", G_CALLBACK (on_login_button_clicked_start_other), login_window);
449                gtk_widget_show (button);
450                break;
451        case LOGIN_BUTTON_ANSWER_QUERY:
452                login_window->priv->login_button_handler_id = g_signal_connect (button, "clicked", G_CALLBACK (on_login_button_clicked_answer_query), login_window);
453                gtk_widget_show (button);
454                break;
455        case LOGIN_BUTTON_TIMED_LOGIN:
456                login_window->priv->login_button_handler_id = g_signal_connect (button, "clicked", G_CALLBACK (on_login_button_clicked_timed_login), login_window);
457                gtk_widget_show (button);
458                break;
459        default:
460                g_assert_not_reached ();
461                break;
462        }
463}
464
465static void
466adjust_other_login_visibility(GdmGreeterLoginWindow *login_window)
467{
468        if (! login_window->priv->user_chooser_loaded) {
469                return;
470        }
471
472        if (login_window->priv->dialog_mode != MODE_SELECTION) {
473                return;
474        }
475
476        if (gdm_chooser_widget_get_number_of_items (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser)) == 0) {
477                set_log_in_button_mode (login_window, LOGIN_BUTTON_START_OTHER);
478        } else {
479                set_log_in_button_mode (login_window, LOGIN_BUTTON_HIDDEN);
480        }
481}
482
483#ifdef HAVE_DEVICEKIT_POWER
484static gboolean
485can_suspend (GdmGreeterLoginWindow *login_window)
486{
487        gboolean ret;
488        DkpClient *dkp_client;
489
490        /* use DeviceKit-power to get data */
491        dkp_client = dkp_client_new ();
492        g_object_get (dkp_client,
493                      "can-suspend", &ret,
494                      NULL);
495        g_object_unref (dkp_client);
496        return ret;
497}
498#endif
499
500static void
501remove_sensitize_power_buttons_timeout (GdmGreeterLoginWindow *login_window)
502{
503        if (login_window->priv->sensitize_power_buttons_timeout_id > 0) {
504                g_source_remove (login_window->priv->sensitize_power_buttons_timeout_id);
505                login_window->priv->sensitize_power_buttons_timeout_id = 0;
506        }
507}
508
509static gboolean
510sensitize_power_buttons_timeout (GdmGreeterLoginWindow *login_window)
511{
512        switch (login_window->priv->dialog_mode) {
513        case MODE_SELECTION:
514                sensitize_widget (login_window, "shutdown-button", TRUE);
515                sensitize_widget (login_window, "restart-button", TRUE);
516                sensitize_widget (login_window, "suspend-button", TRUE);
517                sensitize_widget (login_window, "disconnect-button", TRUE);
518                break;
519        case MODE_AUTHENTICATION:
520                break;
521        default:
522                g_assert_not_reached ();
523        }
524
525        login_window->priv->sensitize_power_buttons_timeout_id = 0;
526        return FALSE;
527}
528
529static void
530add_sensitize_power_buttons_timeout (GdmGreeterLoginWindow *login_window)
531{
532        remove_sensitize_power_buttons_timeout (login_window);
533        login_window->priv->sensitize_power_buttons_timeout_id = g_timeout_add_seconds (1,
534                                                                                   (GSourceFunc)sensitize_power_buttons_timeout,
535                                                                                   login_window);
536}
537
538static void
539switch_mode (GdmGreeterLoginWindow *login_window,
540             int                    number)
541{
542        const char *default_name;
543        GtkWidget  *user_chooser;
544        GtkWidget  *box;
545        gboolean    show_restart_buttons;
546        gboolean    show_suspend_button;
547
548        show_restart_buttons = get_show_restart_buttons (login_window);
549
550#ifdef HAVE_DEVICEKIT_POWER
551        show_suspend_button = can_suspend (login_window);
552#else
553        show_suspend_button = FALSE;
554#endif
555
556        /* we want to run this even if we're supposed to
557           be in the mode already so that we reset everything
558           to a known state */
559        login_window->priv->dialog_mode = number;
560
561        default_name = NULL;
562
563        remove_sensitize_power_buttons_timeout (login_window);
564
565        switch (number) {
566        case MODE_SELECTION:
567                set_log_in_button_mode (login_window, LOGIN_BUTTON_HIDDEN);
568
569                show_widget (login_window, "cancel-button", FALSE);
570
571                show_widget (login_window, "shutdown-button",
572                             login_window->priv->display_is_local && show_restart_buttons);
573                show_widget (login_window, "restart-button",
574                             login_window->priv->display_is_local && show_restart_buttons);
575                show_widget (login_window, "suspend-button",
576                             login_window->priv->display_is_local && show_restart_buttons && show_suspend_button);
577                show_widget (login_window, "disconnect-button",
578                             ! login_window->priv->display_is_local);
579
580                show_widget (login_window, "auth-input-box", FALSE);
581
582                add_sensitize_power_buttons_timeout (login_window);
583                sensitize_widget (login_window, "shutdown-button", FALSE);
584                sensitize_widget (login_window, "restart-button", FALSE);
585                sensitize_widget (login_window, "suspend-button", FALSE);
586                sensitize_widget (login_window, "disconnect-button", FALSE);
587
588                default_name = NULL;
589                break;
590        case MODE_AUTHENTICATION:
591                show_widget (login_window, "cancel-button", TRUE);
592                show_widget (login_window, "shutdown-button", FALSE);
593                show_widget (login_window, "restart-button", FALSE);
594                show_widget (login_window, "suspend-button", FALSE);
595                show_widget (login_window, "disconnect-button", FALSE);
596                default_name = "log-in-button";
597                break;
598        default:
599                g_assert_not_reached ();
600        }
601
602        box = glade_xml_get_widget (login_window->priv->xml, "buttonbox");
603        gtk_button_box_set_layout (GTK_BUTTON_BOX (box),
604                                   (number == MODE_SELECTION) ? GTK_BUTTONBOX_SPREAD : GTK_BUTTONBOX_END );
605
606        user_chooser = glade_xml_get_widget (login_window->priv->xml, "user-chooser");
607        box = gtk_widget_get_parent (user_chooser);
608        if (GTK_IS_BOX (box)) {
609                guint       padding;
610                GtkPackType pack_type;
611
612                gtk_box_query_child_packing (GTK_BOX (box),
613                                             user_chooser,
614                                             NULL,
615                                             NULL,
616                                             &padding,
617                                             &pack_type);
618                gtk_box_set_child_packing (GTK_BOX (box),
619                                           user_chooser,
620                                           number == MODE_SELECTION,
621                                           number == MODE_SELECTION,
622                                           padding,
623                                           pack_type);
624        }
625
626        if (default_name != NULL) {
627                GtkWidget *widget;
628
629                widget = glade_xml_get_widget (login_window->priv->xml, default_name);
630                gtk_widget_grab_default (widget);
631        }
632}
633
634static void
635do_disconnect (GdmGreeterLoginWindow *login_window)
636{
637        gtk_main_quit ();
638}
639
640#ifdef HAVE_DEVICEKIT_POWER
641static void
642do_suspend (GdmGreeterLoginWindow *login_window)
643{
644        gboolean ret;
645        DkpClient *dkp_client;
646        GError *error = NULL;
647
648        /* use DeviceKit-power to get data */
649        dkp_client = dkp_client_new ();
650        ret = dkp_client_suspend (dkp_client, &error);
651        if (!ret) {
652                g_warning ("Couldn't suspend: %s", error->message);
653                g_error_free (error);
654                return;
655        }
656        g_object_unref (dkp_client);
657}
658#endif
659
660static void
661delete_entry_text (GtkWidget *entry)
662{
663        const char *typed_text;
664        char       *null_text;
665
666        /* try to scrub out any secret info */
667        typed_text = gtk_entry_get_text (GTK_ENTRY (entry));
668        null_text = g_strnfill (strlen (typed_text) + 1, '\b');
669        gtk_entry_set_text (GTK_ENTRY (entry), null_text);
670        gtk_entry_set_text (GTK_ENTRY (entry), "");
671}
672
673static void
674reset_dialog (GdmGreeterLoginWindow *login_window)
675{
676        GtkWidget  *entry;
677        GtkWidget  *label;
678
679        g_debug ("GdmGreeterLoginWindow: Resetting dialog");
680        set_busy (login_window);
681        set_sensitive (login_window, FALSE);
682
683        if (login_window->priv->timed_login_enabled) {
684                gdm_chooser_widget_set_item_timer (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser),
685                                                   GDM_USER_CHOOSER_USER_AUTO, 0);
686                remove_timed_login_timeout (login_window);
687                login_window->priv->timed_login_enabled = FALSE;
688        }
689        _gdm_greeter_login_window_set_interactive (login_window, FALSE);
690
691        g_signal_handlers_block_by_func (G_OBJECT (login_window->priv->user_chooser),
692                                         G_CALLBACK (on_user_unchosen), login_window);
693        gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), NULL);
694        g_signal_handlers_unblock_by_func (G_OBJECT (login_window->priv->user_chooser),
695                                           G_CALLBACK (on_user_unchosen), login_window);
696
697        if (login_window->priv->start_session_handler_id > 0) {
698                g_signal_handler_disconnect (login_window, login_window->priv->start_session_handler_id);
699                login_window->priv->start_session_handler_id = 0;
700        }
701
702        entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry");
703
704        delete_entry_text (entry);
705
706        gtk_entry_set_visibility (GTK_ENTRY (entry), TRUE);
707        set_message (login_window, "");
708
709        label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label");
710        gtk_label_set_text (GTK_LABEL (label), "");
711
712        switch_mode (login_window, MODE_SELECTION);
713
714        set_sensitive (login_window, TRUE);
715        set_ready (login_window);
716        set_focus (GDM_GREETER_LOGIN_WINDOW (login_window));
717        update_banner_message (login_window);
718        adjust_other_login_visibility (login_window);
719        if (gdm_chooser_widget_get_number_of_items (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser)) >= 1) {
720                gdm_chooser_widget_propagate_pending_key_events (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser));
721        }
722}
723
724static void
725do_cancel (GdmGreeterLoginWindow *login_window)
726{
727        /* need to wait for response from backend */
728        set_message (login_window, _("Cancelling..."));
729        set_busy (login_window);
730        set_sensitive (login_window, FALSE);
731        g_signal_emit (login_window, signals[CANCELLED], 0);
732}
733
734gboolean
735gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window)
736{
737        g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
738
739        reset_dialog (login_window);
740
741        set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE);
742        set_ready (GDM_GREETER_LOGIN_WINDOW (login_window));
743        set_focus (GDM_GREETER_LOGIN_WINDOW (login_window));
744
745        return TRUE;
746}
747
748gboolean
749gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window)
750{
751        g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
752
753        reset_dialog (GDM_GREETER_LOGIN_WINDOW (login_window));
754
755        return TRUE;
756}
757
758gboolean
759gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window,
760                               const char            *text)
761{
762        g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
763
764        g_debug ("GdmGreeterLoginWindow: info: %s", text);
765
766        set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text);
767
768        return TRUE;
769}
770
771gboolean
772gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window,
773                                  const char            *text)
774{
775        g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
776
777        g_debug ("GdmGreeterLoginWindow: problem: %s", text);
778
779        set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text);
780        gdk_window_beep (GTK_WIDGET (login_window)->window);
781
782        return TRUE;
783}
784
785void
786gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window,
787                                              const char            *username,
788                                              int                    delay)
789{
790        static gboolean timed_login_already_enabled;
791
792        g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window));
793
794        g_debug ("GdmGreeterLoginWindow: requested automatic login for user '%s' in %d seconds", username, delay);
795
796        if (login_window->priv->timed_login_username != NULL) {
797                timed_login_already_enabled = TRUE;
798                g_free (login_window->priv->timed_login_username);
799        } else {
800                timed_login_already_enabled = FALSE;
801        }
802        login_window->priv->timed_login_username = g_strdup (username);
803        login_window->priv->timed_login_delay = delay;
804
805        if (login_window->priv->dialog_mode != MODE_SELECTION) {
806                reset_dialog (login_window);
807        }
808        gdm_user_chooser_widget_set_show_user_auto (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), TRUE);
809
810        if (!timed_login_already_enabled) {
811                gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser),
812                                                              GDM_USER_CHOOSER_USER_AUTO);
813        }
814}
815
816static void
817gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_window)
818{
819        if (login_window->priv->is_interactive) {
820                g_debug ("GdmGreeterLoginWindow: starting session");
821                g_signal_emit (login_window, signals[START_SESSION], 0);
822        } else {
823                g_debug ("GdmGreeterLoginWindow: not starting session since "
824                         "user hasn't had an opportunity to pick language "
825                         "and session yet.");
826
827                /* Call back when we're ready to go
828                 */
829                login_window->priv->start_session_handler_id =
830                    g_signal_connect (login_window, "notify::is-interactive",
831                                      G_CALLBACK (gdm_greeter_login_window_start_session_when_ready),
832                                      NULL);
833
834                /* FIXME: If the user wasn't asked any questions by pam but
835                 * pam still authorized them (passwd -d, or the questions got
836                 * asked on an external device) then we need to let them log in.
837                 * Right now we just log them in right away, but we really should
838                 * set a timer up like timed login (but shorter, say ~5 seconds),
839                 * so they can pick language/session.  Will need to refactor things
840                 * a bit so we can share code with timed login.
841                 */
842                if (!login_window->priv->timed_login_enabled) {
843
844                        g_debug ("GdmGreeterLoginWindow: Okay, we'll start the session anyway,"
845                                 "because the user isn't ever going to get an opportunity to"
846                                 "interact with session");
847                        _gdm_greeter_login_window_set_interactive (login_window, TRUE);
848                }
849
850        }
851}
852
853gboolean
854gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window,
855                                     const char            *text)
856{
857        GtkWidget  *entry;
858        GtkWidget  *label;
859
860        g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
861
862        g_debug ("GdmGreeterLoginWindow: info query: %s", text);
863
864        entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry");
865        delete_entry_text (entry);
866        gtk_entry_set_visibility (GTK_ENTRY (entry), TRUE);
867        set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY);
868
869        label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label");
870        gtk_label_set_text (GTK_LABEL (label), text);
871
872        show_widget (login_window, "auth-input-box", TRUE);
873        set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE);
874        set_ready (GDM_GREETER_LOGIN_WINDOW (login_window));
875        set_focus (GDM_GREETER_LOGIN_WINDOW (login_window));
876
877        gdm_chooser_widget_propagate_pending_key_events (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser));
878
879        return TRUE;
880}
881
882gboolean
883gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window,
884                                            const char            *text)
885{
886        GtkWidget  *entry;
887        GtkWidget  *label;
888
889        g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
890
891        entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry");
892        delete_entry_text (entry);
893        gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
894        set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY);
895
896        label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label");
897        gtk_label_set_text (GTK_LABEL (label), text);
898
899        show_widget (login_window, "auth-input-box", TRUE);
900        set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE);
901        set_ready (GDM_GREETER_LOGIN_WINDOW (login_window));
902        set_focus (GDM_GREETER_LOGIN_WINDOW (login_window));
903
904        gdm_chooser_widget_propagate_pending_key_events (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser));
905
906        return TRUE;
907}
908
909void
910gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window)
911{
912        g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window));
913
914        g_debug ("GdmGreeterLoginWindow: user now authorized");
915
916        gdm_greeter_login_window_start_session_when_ready (login_window);
917}
918
919static void
920_gdm_greeter_login_window_set_display_is_local (GdmGreeterLoginWindow *login_window,
921                                                gboolean               is)
922{
923        login_window->priv->display_is_local = is;
924}
925
926static void
927gdm_greeter_login_window_set_property (GObject      *object,
928                                       guint         prop_id,
929                                       const GValue *value,
930                                       GParamSpec   *pspec)
931{
932        GdmGreeterLoginWindow *self;
933
934        self = GDM_GREETER_LOGIN_WINDOW (object);
935
936        switch (prop_id) {
937        case PROP_DISPLAY_IS_LOCAL:
938                _gdm_greeter_login_window_set_display_is_local (self, g_value_get_boolean (value));
939                break;
940        case PROP_IS_INTERACTIVE:
941                _gdm_greeter_login_window_set_interactive (self, g_value_get_boolean (value));
942                break;
943        default:
944                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
945                break;
946        }
947}
948
949static void
950gdm_greeter_login_window_get_property (GObject    *object,
951                                       guint       prop_id,
952                                       GValue     *value,
953                                       GParamSpec *pspec)
954{
955        GdmGreeterLoginWindow *self;
956
957        self = GDM_GREETER_LOGIN_WINDOW (object);
958
959        switch (prop_id) {
960        case PROP_DISPLAY_IS_LOCAL:
961                g_value_set_boolean (value, self->priv->display_is_local);
962                break;
963        case PROP_IS_INTERACTIVE:
964                g_value_set_boolean (value, self->priv->is_interactive);
965                break;
966
967        default:
968                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
969                break;
970        }
971}
972
973static void
974suspend_button_clicked (GtkButton             *button,
975                        GdmGreeterLoginWindow *login_window)
976{
977#ifdef HAVE_DEVICEKIT_POWER
978        do_suspend (login_window);
979#endif
980}
981
982
983static void
984cancel_button_clicked (GtkButton             *button,
985                       GdmGreeterLoginWindow *login_window)
986{
987        do_cancel (login_window);
988}
989
990static void
991disconnect_button_clicked (GtkButton             *button,
992                           GdmGreeterLoginWindow *login_window)
993{
994        do_disconnect (login_window);
995}
996
997static gboolean
998try_system_stop (DBusGConnection *connection,
999                 GError         **error)
1000{
1001        DBusGProxy      *proxy;
1002        gboolean         res;
1003
1004        g_debug ("GdmGreeterLoginWindow: trying to stop system");
1005
1006        proxy = dbus_g_proxy_new_for_name (connection,
1007                                           CK_NAME,
1008                                           CK_MANAGER_PATH,
1009                                           CK_MANAGER_INTERFACE);
1010        res = dbus_g_proxy_call_with_timeout (proxy,
1011                                              "Stop",
1012                                              INT_MAX,
1013                                              error,
1014                                              /* parameters: */
1015                                              G_TYPE_INVALID,
1016                                              /* return values: */
1017                                              G_TYPE_INVALID);
1018        return res;
1019}
1020
1021static gboolean
1022try_system_restart (DBusGConnection *connection,
1023                    GError         **error)
1024{
1025        DBusGProxy      *proxy;
1026        gboolean         res;
1027
1028        g_debug ("GdmGreeterLoginWindow: trying to restart system");
1029
1030        proxy = dbus_g_proxy_new_for_name (connection,
1031                                           CK_NAME,
1032                                           CK_MANAGER_PATH,
1033                                           CK_MANAGER_INTERFACE);
1034        res = dbus_g_proxy_call_with_timeout (proxy,
1035                                              "Restart",
1036                                              INT_MAX,
1037                                              error,
1038                                              /* parameters: */
1039                                              G_TYPE_INVALID,
1040                                              /* return values: */
1041                                              G_TYPE_INVALID);
1042        return res;
1043}
1044
1045static void
1046do_system_restart (GdmGreeterLoginWindow *login_window)
1047{
1048        gboolean         res;
1049        GError          *error;
1050        DBusGConnection *connection;
1051
1052        error = NULL;
1053        connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
1054        if (connection == NULL) {
1055                g_warning ("Unable to get system bus connection: %s", error->message);
1056                g_error_free (error);
1057                return;
1058        }
1059
1060        res = try_system_restart (connection, &error);
1061        if (!res) {
1062                g_debug ("GdmGreeterLoginWindow: unable to restart system: %s: %s",
1063                         dbus_g_error_get_name (error),
1064                         error->message);
1065                g_error_free (error);
1066        }
1067}
1068
1069static void
1070do_system_stop (GdmGreeterLoginWindow *login_window)
1071{
1072        gboolean         res;
1073        GError          *error;
1074        DBusGConnection *connection;
1075
1076        error = NULL;
1077        connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
1078        if (connection == NULL) {
1079                g_warning ("Unable to get system bus connection: %s", error->message);
1080                g_error_free (error);
1081                return;
1082        }
1083
1084        res = try_system_stop (connection, &error);
1085        if (!res) {
1086                g_debug ("GdmGreeterLoginWindow: unable to stop system: %s: %s",
1087                         dbus_g_error_get_name (error),
1088                         error->message);
1089                g_error_free (error);
1090        }
1091}
1092
1093static void
1094restart_button_clicked (GtkButton             *button,
1095                        GdmGreeterLoginWindow *login_window)
1096{
1097        g_debug ("GdmGreeterLoginWindow: restart button clicked");
1098        do_system_restart (login_window);
1099}
1100
1101static void
1102shutdown_button_clicked (GtkButton             *button,
1103                         GdmGreeterLoginWindow *login_window)
1104{
1105        g_debug ("GdmGreeterLoginWindow: stop button clicked");
1106        do_system_stop (login_window);
1107}
1108
1109static void
1110on_user_chooser_visibility_changed (GdmGreeterLoginWindow *login_window)
1111{
1112        update_banner_message (login_window);
1113        adjust_other_login_visibility (login_window);
1114}
1115
1116static void
1117on_users_loaded (GdmUserChooserWidget  *user_chooser,
1118                 GdmGreeterLoginWindow *login_window)
1119{
1120        g_debug ("GdmGreeterLoginWindow: users loaded");
1121        login_window->priv->user_chooser_loaded = TRUE;
1122        update_banner_message (login_window);
1123        adjust_other_login_visibility (login_window);
1124
1125        gdm_chooser_widget_activate_if_one_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser));
1126}
1127
1128static void
1129on_user_chosen (GdmUserChooserWidget  *user_chooser,
1130                GdmGreeterLoginWindow *login_window)
1131{
1132        char *user_name;
1133
1134        user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser));
1135        g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name);
1136
1137        if (user_name == NULL) {
1138                return;
1139        }
1140
1141        g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED],
1142                       0, user_name);
1143
1144        if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) {
1145                g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0);
1146        } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_GUEST) == 0) {
1147                /* FIXME: handle guest account stuff */
1148        } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_AUTO) == 0) {
1149                g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0,
1150                               login_window->priv->timed_login_username);
1151
1152                login_window->priv->timed_login_enabled = TRUE;
1153                restart_timed_login_timeout (login_window);
1154
1155                /* just wait for the user to select language and stuff */
1156                set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN);
1157                set_message (login_window, _("Select language and click Log In"));
1158        } else {
1159                g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, user_name);
1160        }
1161
1162        switch_mode (login_window, MODE_AUTHENTICATION);
1163
1164        g_free (user_name);
1165}
1166
1167static void
1168on_user_unchosen (GdmUserChooserWidget  *user_chooser,
1169                  GdmGreeterLoginWindow *login_window)
1170{
1171        do_cancel (login_window);
1172}
1173
1174static gboolean
1175on_computer_info_label_button_press (GtkWidget             *widget,
1176                                     GdkEventButton        *event,
1177                                     GdmGreeterLoginWindow *login_window)
1178{
1179        GtkWidget *notebook;
1180        int        current_page;
1181        int        n_pages;
1182
1183        /* switch page */
1184        notebook = glade_xml_get_widget (login_window->priv->xml, "computer-info-notebook");
1185        current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
1186        n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
1187
1188        if (current_page + 1 < n_pages) {
1189                gtk_notebook_next_page (GTK_NOTEBOOK (notebook));
1190        } else {
1191                gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0);
1192        }
1193
1194        return FALSE;
1195}
1196
1197static char *
1198file_read_one_line (const char *filename)
1199{
1200        FILE *f;
1201        char *line;
1202        char buf[4096];
1203
1204        line = NULL;
1205
1206        f = fopen (filename, "r");
1207        if (f == NULL) {
1208                g_warning ("Unable to open file %s: %s", filename, g_strerror (errno));
1209                goto out;
1210        }
1211
1212        if (fgets (buf, sizeof (buf), f) == NULL) {
1213                g_warning ("Unable to read from file %s", filename);
1214        }
1215
1216        line = g_strdup (buf);
1217        g_strchomp (line);
1218
1219 out:
1220        fclose (f);
1221
1222        return line;
1223}
1224
1225static const char *known_etc_info_files [] = {
1226        "redhat-release",
1227        "SuSE-release",
1228        "gentoo-release",
1229        "arch-release",
1230        "debian_version",
1231        "mandriva-release",
1232        "slackware-version",
1233        NULL
1234};
1235
1236
1237static char *
1238get_system_version (void)
1239{
1240        char *version;
1241        int i;
1242
1243        version = NULL;
1244
1245        for (i = 0; known_etc_info_files [i]; i++) {
1246                char *path1;
1247                char *path2;
1248
1249                path1 = g_build_filename (SYSCONFDIR, known_etc_info_files [i], NULL);
1250                path2 = g_build_filename ("/etc", known_etc_info_files [i], NULL);
1251                if (g_access (path1, R_OK) == 0) {
1252                        version = file_read_one_line (path1);
1253                } else if (g_access (path2, R_OK) == 0) {
1254                        version = file_read_one_line (path2);
1255                }
1256                g_free (path2);
1257                g_free (path1);
1258                if (version != NULL) {
1259                        break;
1260                }
1261        }
1262
1263        if (version == NULL) {
1264                char *output;
1265                output = NULL;
1266                if (g_spawn_command_line_sync ("uname -sr", &output, NULL, NULL, NULL)) {
1267                        version = g_strchomp (output);
1268                }
1269        }
1270
1271        return version;
1272}
1273
1274static void
1275create_computer_info (GdmGreeterLoginWindow *login_window)
1276{
1277        GtkWidget *label;
1278
1279        gdm_profile_start (NULL);
1280
1281        label = glade_xml_get_widget (login_window->priv->xml, "computer-info-name-label");
1282        if (label != NULL) {
1283                gtk_label_set_text (GTK_LABEL (label), "ana are mere");//g_get_host_name ());
1284        }
1285
1286        label = glade_xml_get_widget (login_window->priv->xml, "computer-info-version-label");
1287        if (label != NULL) {
1288                char *version;
1289                version = get_system_version ();
1290                gtk_label_set_text (GTK_LABEL (label), version);
1291                g_free (version);
1292        }
1293
1294        gdm_profile_end (NULL);
1295}
1296
1297#define INVISIBLE_CHAR_DEFAULT       '*'
1298#define INVISIBLE_CHAR_BLACK_CIRCLE  0x25cf
1299#define INVISIBLE_CHAR_WHITE_BULLET  0x25e6
1300#define INVISIBLE_CHAR_BULLET        0x2022
1301#define INVISIBLE_CHAR_NONE          0
1302
1303static GtkWidget *
1304custom_widget_constructor (GladeXML              *xml,
1305                           char                  *func_name,
1306                           char                  *name,
1307                           char                  *string1,
1308                           char                  *string2,
1309                           int                    int1,
1310                           int                    int2,
1311                           GdmGreeterLoginWindow *login_window)
1312{
1313        GtkWidget *widget;
1314
1315        g_assert (GLADE_IS_XML (xml));
1316        g_assert (name != NULL);
1317        g_assert (GDM_IS_GREETER_LOGIN_WINDOW (login_window));
1318
1319        gdm_profile_start (NULL);
1320
1321        widget = NULL;
1322
1323        if (strcmp (name, "user-chooser") == 0) {
1324               widget = gdm_user_chooser_widget_new ();
1325        }
1326
1327        gdm_profile_end (NULL);
1328
1329        return widget;
1330}
1331
1332static void
1333load_theme (GdmGreeterLoginWindow *login_window)
1334{
1335        GtkWidget *entry;
1336        GtkWidget *button;
1337        GtkWidget *box;
1338        GtkWidget *image;
1339
1340        gdm_profile_start (NULL);
1341
1342        glade_set_custom_handler ((GladeXMLCustomWidgetHandler) custom_widget_constructor,
1343                                  login_window);
1344        login_window->priv->xml = glade_xml_new (GLADEDIR "/" GLADE_XML_FILE,
1345                                                 "window-frame",
1346                                                 PACKAGE);
1347
1348        g_assert (login_window->priv->xml != NULL);
1349
1350        image = glade_xml_get_widget (login_window->priv->xml, "logo-image");
1351        if (image != NULL) {
1352                char        *icon_name;
1353                GError      *error;
1354
1355                error = NULL;
1356                icon_name = gconf_client_get_string (login_window->priv->client, KEY_LOGO, &error);
1357                if (error != NULL) {
1358                        g_debug ("GdmGreeterLoginWindow: unable to get logo icon name: %s", error->message);
1359                        g_error_free (error);
1360                }
1361
1362                g_debug ("GdmGreeterLoginWindow: Got greeter logo '%s'",
1363                          icon_name ? icon_name : "(null)");
1364                if (icon_name != NULL) {
1365                        gtk_image_set_from_icon_name (GTK_IMAGE (image),
1366                                                      icon_name,
1367                                                      GTK_ICON_SIZE_DIALOG);
1368                        g_free (icon_name);
1369                }
1370        }
1371
1372        box = glade_xml_get_widget (login_window->priv->xml, "window-frame");
1373        gtk_container_add (GTK_CONTAINER (login_window), box);
1374
1375        login_window->priv->user_chooser = glade_xml_get_widget (login_window->priv->xml,
1376                                                                 "user-chooser");
1377        if (login_window->priv->user_chooser == NULL) {
1378                g_critical ("Userlist box not found");
1379        }
1380
1381        gdm_user_chooser_widget_set_show_only_chosen (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), TRUE);
1382
1383        g_signal_connect (login_window->priv->user_chooser,
1384                          "loaded",
1385                          G_CALLBACK (on_users_loaded),
1386                          login_window);
1387        g_signal_connect (login_window->priv->user_chooser,
1388                          "activated",
1389                          G_CALLBACK (on_user_chosen),
1390                          login_window);
1391        g_signal_connect (login_window->priv->user_chooser,
1392                          "deactivated",
1393                          G_CALLBACK (on_user_unchosen),
1394                          login_window);
1395
1396        g_signal_connect_swapped (login_window->priv->user_chooser,
1397                                 "notify::list-visible",
1398                                 G_CALLBACK (on_user_chooser_visibility_changed),
1399                                 login_window);
1400
1401        gtk_widget_show (login_window->priv->user_chooser);
1402
1403        login_window->priv->auth_banner_label = glade_xml_get_widget (login_window->priv->xml, "auth-banner-label");
1404        /*make_label_small_italic (login_window->priv->auth_banner_label);*/
1405
1406        button = glade_xml_get_widget (login_window->priv->xml, "suspend-button");
1407        g_signal_connect (button, "clicked", G_CALLBACK (suspend_button_clicked), login_window);
1408
1409        button = glade_xml_get_widget (login_window->priv->xml, "cancel-button");
1410        g_signal_connect (button, "clicked", G_CALLBACK (cancel_button_clicked), login_window);
1411
1412        button = glade_xml_get_widget (login_window->priv->xml, "disconnect-button");
1413        g_signal_connect (button, "clicked", G_CALLBACK (disconnect_button_clicked), login_window);
1414
1415        button = glade_xml_get_widget (login_window->priv->xml, "restart-button");
1416        g_signal_connect (button, "clicked", G_CALLBACK (restart_button_clicked), login_window);
1417        button = glade_xml_get_widget (login_window->priv->xml, "shutdown-button");
1418        g_signal_connect (button, "clicked", G_CALLBACK (shutdown_button_clicked), login_window);
1419
1420        entry = glade_xml_get_widget (login_window->priv->xml, "auth-prompt-entry");
1421        /* Only change the invisible character if it '*' otherwise assume it is OK */
1422        if ('*' == gtk_entry_get_invisible_char (GTK_ENTRY (entry))) {
1423                gunichar invisible_char;
1424                invisible_char = INVISIBLE_CHAR_BLACK_CIRCLE;
1425                gtk_entry_set_invisible_char (GTK_ENTRY (entry), invisible_char);
1426        }
1427
1428        create_computer_info (login_window);
1429
1430        box = glade_xml_get_widget (login_window->priv->xml, "computer-info-event-box");
1431        g_signal_connect (box, "button-press-event", G_CALLBACK (on_computer_info_label_button_press), login_window);
1432
1433        switch_mode (login_window, MODE_SELECTION);
1434
1435        gdm_profile_end (NULL);
1436}
1437
1438static gboolean
1439gdm_greeter_login_window_key_press_event (GtkWidget   *widget,
1440                                          GdkEventKey *event)
1441{
1442        GdmGreeterLoginWindow *login_window;
1443
1444        login_window = GDM_GREETER_LOGIN_WINDOW (widget);
1445
1446        if (event->keyval == GDK_Escape) {
1447                if (login_window->priv->dialog_mode == MODE_AUTHENTICATION) {
1448                        do_cancel (GDM_GREETER_LOGIN_WINDOW (widget));
1449                }
1450        }
1451
1452        return GTK_WIDGET_CLASS (gdm_greeter_login_window_parent_class)->key_press_event (widget, event);
1453}
1454
1455static void
1456gdm_greeter_login_window_size_request (GtkWidget      *widget,
1457                                       GtkRequisition *requisition)
1458{
1459        int             monitor;
1460        GdkScreen      *screen;
1461        GtkRequisition  child_requisition;
1462        GdkRectangle    area;
1463
1464        if (GTK_WIDGET_CLASS (gdm_greeter_login_window_parent_class)->size_request) {
1465                GTK_WIDGET_CLASS (gdm_greeter_login_window_parent_class)->size_request (widget, requisition);
1466        }
1467
1468        if (!GTK_WIDGET_REALIZED (widget)) {
1469                return;
1470        }
1471
1472        screen = gtk_widget_get_screen (widget);
1473        monitor = gdk_screen_get_monitor_at_window (screen, widget->window);
1474        gdk_screen_get_monitor_geometry (screen, monitor, &area);
1475
1476        gtk_widget_get_child_requisition (GTK_BIN (widget)->child, &child_requisition);
1477        *requisition = child_requisition;
1478
1479        requisition->width += 2 * GTK_CONTAINER (widget)->border_width;
1480        requisition->height += 2 * GTK_CONTAINER (widget)->border_width;
1481
1482        /* Make width be at least 33% screen width
1483         * and height be at most 80% of screen height
1484         */
1485        requisition->width = MAX (requisition->width, .33 * area.width);
1486        requisition->height = MIN (requisition->height, .80 * area.height);
1487
1488       /* Don't ever shrink window width
1489        */
1490       requisition->width = MAX (requisition->width, widget->allocation.width);
1491}
1492
1493static void
1494update_banner_message (GdmGreeterLoginWindow *login_window)
1495{
1496        GError      *error;
1497        gboolean     enabled;
1498
1499        if (login_window->priv->auth_banner_label == NULL) {
1500                /* if the theme doesn't have a banner message */
1501                g_debug ("GdmGreeterLoginWindow: theme doesn't support a banner message");
1502                return;
1503        }
1504
1505        error = NULL;
1506        enabled = gconf_client_get_bool (login_window->priv->client, KEY_BANNER_MESSAGE_ENABLED, &error);
1507        if (error != NULL) {
1508                g_debug ("GdmGreeterLoginWindow: unable to get configuration: %s", error->message);
1509                g_error_free (error);
1510        }
1511
1512        login_window->priv->banner_message_enabled = enabled;
1513
1514        if (! enabled) {
1515                g_debug ("GdmGreeterLoginWindow: banner message disabled");
1516                gtk_widget_hide (login_window->priv->auth_banner_label);
1517        } else {
1518                char *message = NULL;
1519                error = NULL;
1520                if (login_window->priv->user_chooser_loaded && gdm_chooser_widget_get_number_of_items (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser)) == 0) {
1521                        message = gconf_client_get_string (login_window->priv->client, KEY_BANNER_MESSAGE_TEXT_NOCHOOSER, &error);
1522                        if (error != NULL) {
1523                                g_debug("GdmGreeterLoginWindow: unable to get nochooser banner text: %s", error->message);
1524                                g_error_free(error);
1525                        }
1526                }
1527                error = NULL;
1528                if (message == NULL) {
1529                        message = gconf_client_get_string (login_window->priv->client, KEY_BANNER_MESSAGE_TEXT, &error);
1530                        if (error != NULL) {
1531                                g_debug("GdmGreeterLoginWindow: unable to get banner text: %s", error->message);
1532                                g_error_free(error);
1533                        }
1534                }
1535                if (message != NULL) {
1536                        char *markup;
1537                        markup = g_markup_printf_escaped ("<small><i>%s</i></small>", message);
1538                        gtk_label_set_markup (GTK_LABEL (login_window->priv->auth_banner_label),
1539                                              markup);
1540                        g_free (markup);
1541                }
1542                g_debug ("GdmGreeterLoginWindow: banner message: %s", message);
1543
1544                gtk_widget_show (login_window->priv->auth_banner_label);
1545        }
1546}
1547
1548gboolean handleBusMsg(GstMessage * message, GtkWidget *window)
1549{
1550        // ignore anything but 'prepare-xwindow-id' element messages
1551        if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
1552                return FALSE;
1553
1554        if (!gst_structure_has_name(message->structure, "prepare-xwindow-id"))
1555                return FALSE;
1556
1557    g_assert(!GTK_WIDGET_NO_WINDOW(window));
1558        g_print("Got prepare-xwindow-id msg\n");
1559        // FIXME: see https://bugzilla.gnome.org/show_bug.cgi?id=599885
1560    //gdk_window_resize(window->window, 100, 100);
1561        gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), GDK_WINDOW_XWINDOW(gtk_widget_get_window(window)));
1562    g_debug("pe nas%s\n",gtk_widget_get_name(window));
1563
1564        return TRUE;
1565}
1566
1567gboolean bus_call(GstBus * bus, GstMessage *msg, gpointer data)
1568{
1569        GtkWidget *window = (GtkWidget*) data;
1570        switch(GST_MESSAGE_TYPE(msg))
1571        {
1572                case GST_MESSAGE_ELEMENT:
1573                        {
1574                                handleBusMsg(msg, window);
1575                                break;
1576                        }
1577
1578                default:
1579                        break;
1580        }
1581
1582        return TRUE;
1583}
1584
1585static void makeWindowBlack(GtkWidget * window)
1586{
1587        GdkColor color;
1588        gdk_color_parse ("black", &color);
1589        gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);    // needed to ensure black background
1590}
1591
1592
1593static GObject *
1594gdm_greeter_login_window_constructor (GType                  type,
1595                                      guint                  n_construct_properties,
1596                                      GObjectConstructParam *construct_properties)
1597{
1598        GdmGreeterLoginWindow      *login_window;
1599        GstElement *src, *sink;
1600        GstStateChangeReturn ret;
1601        GtkWidget * logo;
1602
1603        gdm_profile_start (NULL);
1604
1605        login_window = GDM_GREETER_LOGIN_WINDOW (G_OBJECT_CLASS (gdm_greeter_login_window_parent_class)->constructor (type,
1606                                                                                                                      n_construct_properties,
1607                                                                                                                      construct_properties));
1608
1609
1610        load_theme (login_window);
1611        update_banner_message (login_window);
1612
1613
1614        gst_init(NULL,NULL);
1615
1616       
1617
1618        g_assert(login_window!=NULL);
1619        g_assert(login_window->priv!=NULL);
1620        g_assert(login_window->priv->xml!=NULL);
1621        logo = glade_xml_get_widget (login_window->priv->xml, "webcam");
1622        g_assert(logo!=NULL);
1623        /* create elements */
1624        pipeline = gst_pipeline_new ("my_pipeline");
1625        gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline)), 
1626                (GstBusFunc)bus_call, logo);
1627
1628        src = gst_element_factory_make ("v4l2src", NULL);
1629
1630        sink = gst_element_factory_make("autovideosink", "videosink");
1631        g_object_set(G_OBJECT(sink), "sync", FALSE, NULL);
1632
1633        if (!sink)
1634            g_print ("output could not be found - check your install\n");
1635
1636        gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
1637        g_object_set(G_OBJECT(sink), "force-aspect-ratio", TRUE, NULL);
1638
1639        /* link everything together */
1640        if (!gst_element_link(src, sink)) {
1641            g_print ("Failed to link one or more elements!\n");
1642            return -1;
1643        }
1644
1645
1646        /* run */
1647        makeWindowBlack(logo);
1648        gtk_widget_show_all(logo);
1649
1650        ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
1651
1652        if (ret == GST_STATE_CHANGE_FAILURE) 
1653        {
1654            g_print ("Failed to start up pipeline!\n");
1655            return 1;
1656        }
1657
1658
1659        gdm_profile_end (NULL);
1660
1661        return G_OBJECT (login_window);
1662}
1663
1664    static void
1665gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass)
1666{
1667    GObjectClass   *object_class = G_OBJECT_CLASS (klass);
1668    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
1669
1670    object_class->get_property = gdm_greeter_login_window_get_property;
1671    object_class->set_property = gdm_greeter_login_window_set_property;
1672    object_class->constructor = gdm_greeter_login_window_constructor;
1673    object_class->finalize = gdm_greeter_login_window_finalize;
1674
1675    widget_class->key_press_event = gdm_greeter_login_window_key_press_event;
1676    widget_class->size_request = gdm_greeter_login_window_size_request;
1677
1678    signals [BEGIN_AUTO_LOGIN] =
1679                g_signal_new ("begin-auto-login",
1680                              G_TYPE_FROM_CLASS (object_class),
1681                              G_SIGNAL_RUN_LAST,
1682                              G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, begin_auto_login),
1683                              NULL,
1684                              NULL,
1685                              g_cclosure_marshal_VOID__STRING,
1686                              G_TYPE_NONE, 1, G_TYPE_STRING);
1687        signals [BEGIN_VERIFICATION] =
1688                g_signal_new ("begin-verification",
1689                              G_TYPE_FROM_CLASS (object_class),
1690                              G_SIGNAL_RUN_LAST,
1691                              G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, begin_verification),
1692                              NULL,
1693                              NULL,
1694                              g_cclosure_marshal_VOID__VOID,
1695                              G_TYPE_NONE,
1696                              0);
1697        signals [BEGIN_VERIFICATION_FOR_USER] =
1698                g_signal_new ("begin-verification-for-user",
1699                              G_TYPE_FROM_CLASS (object_class),
1700                              G_SIGNAL_RUN_LAST,
1701                              G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, begin_verification_for_user),
1702                              NULL,
1703                              NULL,
1704                              g_cclosure_marshal_VOID__STRING,
1705                              G_TYPE_NONE,
1706                              1, G_TYPE_STRING);
1707        signals [QUERY_ANSWER] =
1708                g_signal_new ("query-answer",
1709                              G_TYPE_FROM_CLASS (object_class),
1710                              G_SIGNAL_RUN_LAST,
1711                              G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, query_answer),
1712                              NULL,
1713                              NULL,
1714                              g_cclosure_marshal_VOID__STRING,
1715                              G_TYPE_NONE,
1716                              1, G_TYPE_STRING);
1717        signals [USER_SELECTED] =
1718                g_signal_new ("user-selected",
1719                              G_TYPE_FROM_CLASS (object_class),
1720                              G_SIGNAL_RUN_LAST,
1721                              G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, user_selected),
1722                              NULL,
1723                              NULL,
1724                              g_cclosure_marshal_VOID__STRING,
1725                              G_TYPE_NONE,
1726                              1, G_TYPE_STRING);
1727        signals [CANCELLED] =
1728                g_signal_new ("cancelled",
1729                              G_TYPE_FROM_CLASS (object_class),
1730                              G_SIGNAL_RUN_LAST,
1731                              G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, cancelled),
1732                              NULL,
1733                              NULL,
1734                              g_cclosure_marshal_VOID__VOID,
1735                              G_TYPE_NONE,
1736                              0);
1737        signals [DISCONNECTED] =
1738                g_signal_new ("disconnected",
1739                              G_TYPE_FROM_CLASS (object_class),
1740                              G_SIGNAL_RUN_LAST,
1741                              G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, disconnected),
1742                              NULL,
1743                              NULL,
1744                              g_cclosure_marshal_VOID__VOID,
1745                              G_TYPE_NONE,
1746                              0);
1747        signals [START_SESSION] =
1748                g_signal_new ("start-session",
1749                              G_TYPE_FROM_CLASS (object_class),
1750                              G_SIGNAL_RUN_LAST,
1751                              G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, start_session),
1752                              NULL,
1753                              NULL,
1754                              g_cclosure_marshal_VOID__VOID,
1755                              G_TYPE_NONE,
1756                              0);
1757
1758        g_object_class_install_property (object_class,
1759                                         PROP_DISPLAY_IS_LOCAL,
1760                                         g_param_spec_boolean ("display-is-local",
1761                                                               "display is local",
1762                                                               "display is local",
1763                                                               FALSE,
1764                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1765        g_object_class_install_property (object_class,
1766                                         PROP_IS_INTERACTIVE,
1767                                         g_param_spec_boolean ("is-interactive",
1768                                                               "Is Interactive",
1769                                                               "Use has had an oppurtunity to interact with window",
1770                                                               FALSE,
1771                                                               G_PARAM_READABLE));
1772
1773        g_type_class_add_private (klass, sizeof (GdmGreeterLoginWindowPrivate));
1774}
1775
1776static void
1777on_gconf_key_changed (GConfClient           *client,
1778                      guint                  cnxn_id,
1779                      GConfEntry            *entry,
1780                      GdmGreeterLoginWindow *login_window)
1781{
1782        const char *key;
1783        GConfValue *value;
1784
1785        key = gconf_entry_get_key (entry);
1786        value = gconf_entry_get_value (entry);
1787
1788        if (strcmp (key, KEY_BANNER_MESSAGE_ENABLED) == 0) {
1789                if (value->type == GCONF_VALUE_BOOL) {
1790                        gboolean enabled;
1791
1792                        enabled = gconf_value_get_bool (value);
1793                        g_debug ("setting key %s = %d", key, enabled);
1794                        login_window->priv->banner_message_enabled = enabled;
1795                        update_banner_message (login_window);
1796                } else {
1797                        g_warning ("Error retrieving configuration key '%s': Invalid type",
1798                                   key);
1799                }
1800        } else if (strcmp (key, KEY_BANNER_MESSAGE_TEXT) == 0 || strcmp (key, KEY_BANNER_MESSAGE_TEXT_NOCHOOSER) == 0) {
1801                if (login_window->priv->banner_message_enabled) {
1802                        update_banner_message (login_window);
1803                }
1804        } else {
1805                g_debug ("GdmGreeterLoginWindow: Config key not handled: %s", key);
1806        }
1807}
1808
1809static gboolean
1810on_window_state_event (GtkWidget           *widget,
1811                       GdkEventWindowState *event,
1812                       gpointer             data)
1813{
1814        if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) {
1815                g_debug ("GdmGreeterLoginWindow: window iconified");
1816                gtk_window_deiconify (GTK_WINDOW (widget));
1817        }
1818
1819        return FALSE;
1820}
1821
1822static void
1823gdm_greeter_login_window_init (GdmGreeterLoginWindow *login_window)
1824{
1825
1826
1827        gdm_profile_start (NULL);
1828
1829        login_window->priv = GDM_GREETER_LOGIN_WINDOW_GET_PRIVATE (login_window);
1830
1831        login_window->priv->timed_login_enabled = FALSE;
1832
1833        login_window->priv->dialog_mode = MODE_SELECTION;
1834
1835        gtk_window_set_title (GTK_WINDOW (login_window), _("Login Window"));
1836        /*gtk_window_set_opacity (GTK_WINDOW (login_window), 0.85);*/
1837        gtk_window_set_position (GTK_WINDOW (login_window), GTK_WIN_POS_CENTER_ALWAYS);
1838        gtk_window_set_deletable (GTK_WINDOW (login_window), FALSE);
1839        gtk_window_set_decorated (GTK_WINDOW (login_window), FALSE);
1840        gtk_window_set_keep_below (GTK_WINDOW (login_window), TRUE);
1841        gtk_window_set_skip_taskbar_hint (GTK_WINDOW (login_window), TRUE);
1842        gtk_window_set_skip_pager_hint (GTK_WINDOW (login_window), TRUE);
1843        gtk_window_stick (GTK_WINDOW (login_window));
1844        gtk_window_set_type_hint (GTK_WINDOW (login_window), GDK_WINDOW_TYPE_HINT_DOCK);
1845        gtk_container_set_border_width (GTK_CONTAINER (login_window), 0);
1846
1847        g_signal_connect (login_window,
1848                          "window-state-event",
1849                          G_CALLBACK (on_window_state_event),
1850                          NULL);
1851
1852        login_window->priv->client = gconf_client_get_default ();
1853        gconf_client_add_dir (login_window->priv->client,
1854                              KEY_GREETER_DIR,
1855                              GCONF_CLIENT_PRELOAD_ONELEVEL,
1856                              NULL);
1857        login_window->priv->gconf_cnxn = gconf_client_notify_add (login_window->priv->client,
1858                                                                  KEY_GREETER_DIR,
1859                                                                  (GConfClientNotifyFunc)on_gconf_key_changed,
1860                                                                  login_window,
1861                                                                  NULL,
1862                                                                  NULL);
1863
1864
1865
1866        gdm_profile_end (NULL);
1867}
1868
1869static void
1870gdm_greeter_login_window_finalize (GObject *object)
1871{
1872        GdmGreeterLoginWindow *login_window;
1873
1874        g_return_if_fail (object != NULL);
1875        g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (object));
1876
1877        login_window = GDM_GREETER_LOGIN_WINDOW (object);
1878
1879        g_return_if_fail (login_window->priv != NULL);
1880
1881        if (login_window->priv->client != NULL) {
1882                g_object_unref (login_window->priv->client);
1883        }
1884
1885        remove_sensitize_power_buttons_timeout (login_window);
1886        /* clean up */
1887        gst_element_set_state (pipeline, GST_STATE_NULL);
1888        gst_object_unref (pipeline);
1889
1890        G_OBJECT_CLASS (gdm_greeter_login_window_parent_class)->finalize (object);
1891}
1892
1893GtkWidget *
1894gdm_greeter_login_window_new (gboolean is_local)
1895{
1896        GObject *object;
1897
1898        object = g_object_new (GDM_TYPE_GREETER_LOGIN_WINDOW,
1899                               "display-is-local", is_local,
1900                               "resizable", FALSE,
1901                               NULL);
1902
1903        return GTK_WIDGET (object);
1904}
Note: See TracBrowser for help on using the repository browser.