source: ldm/trunk/fuentes/gtkgreet/greeter.c @ 855

Last change on this file since 855 was 855, checked in by mabarracus, 5 years ago
  • Updated sources to 2.2.18
  • Ported code from patches to apply in 2.2.18
File size: 31.7 KB
Line 
1/*
2 * LTSP Graphical GTK Greeter
3 * Copyright (2007) Oliver Grawert <ogra@ubuntu.com>, Canonical Ltd.
4
5 * Author: Oliver Grawert <ogra@canonical.com>
6
7 * 2007, Oliver Grawert <ogra@canonical.com>
8 *       Scott Balneaves <sbalneav@ltsp.org>
9 * 2008, Ryan Niebur <RyanRyan52@gmail.com>
10 *       Warren Togami <wtogami@redhat.com>
11 *       Stéphane Graber <stgraber@ubuntu.com>
12 *       Scott Balneaves <sbalneav@ltsp.org>
13 *       Vagrant Cascadian <vagrant@freegeek.org>
14 *       Oliver Grawert <ogra@canonical.com>
15 *       John Ellson <john.ellson@comcast.net>
16 *       Gideon Romm <gadi@ltsp.org>
17 *       Jigish Gohil <cyberorg@opensuse.org>
18 *       Wolfgang Schweer <schweer@cityweb.de>
19 *       Toshio Kuratomi
20 * 2012, Alkis Georgopoulos <alkisg@gmail.com>
21
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License as
24 * published by the Free Software Foundation; version 2.
25
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29 * GNU General Public License for more details.
30
31 * You should have received a copy of the GNU General Public License
32 * along with this program.  If not, you can find it on the World Wide
33 * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
34 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
35 * MA 02110-1301, USA.
36
37 */
38
39#define _GNU_SOURCE
40
41#include <arpa/inet.h>
42#include <cairo.h>
43#include <config.h>
44#include <gdk/gdkkeysyms.h>
45#include <glib.h>
46#include <glib/gprintf.h>
47#include <gtk/gtk.h>
48#include <libintl.h>
49#include <locale.h>
50#include <net/if.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <sys/ioctl.h>
55#include <sys/utsname.h>
56#include <unistd.h>
57
58#include "../src/logging.h"
59#include "greeter.h"
60#include "prefs.h"
61#include "prefwin.h"
62#define _(text) gettext(text)
63
64#define TOP_BAR_HEIGHT 30
65#define BOTTOM_BAR_HEIGHT 30
66
67/*
68 *  Make sure that StatusMessages can accommodate many lines of text - auto scrollbars?
69 */
70GtkWidget *UserPrompt;          /* prompt area before the entry */
71GtkWidget *StatusMessages;      /* Status msg area below entry */
72GtkWidget *entry;               /* entry box */
73GtkWidget *choiceCombo;
74GtkListStore *choiceList;
75
76GtkWidget *GuestButton;
77GtkWidget *timeoutbox;
78gboolean timeout_enabled;
79
80GList *host_list = NULL;
81GIOChannel *g_stdout;           /* stdout io channel */
82gchar *ldm_theme_dir;
83
84int allowguest;
85gint login_timeout;
86gint timeout_left;
87
88gchar *
89ldm_theme_file(char *file)
90{
91    gchar *filename;
92    gchar *filename_default;
93    filename = g_strconcat("/", ldm_theme_dir, "/", file, NULL);
94    filename_default =
95        g_strconcat("/", LDM_THEME_DIR, "ltsp", "/", file, NULL);
96    if (access(g_strconcat(filename, ".png", NULL), F_OK) != -1) {
97        filename = g_strconcat(filename, ".png", NULL);
98    } else if (access(g_strconcat(filename, ".jpg", NULL), F_OK) != -1) {
99        filename = g_strconcat(filename, ".jpg", NULL);
100    } else if (access(g_strconcat(filename_default, ".png", NULL), F_OK) !=
101               -1) {
102        filename = g_strconcat(filename_default, ".png", NULL);
103    } else if (access(g_strconcat(filename_default, ".jpg", NULL), F_OK) !=
104               -1) {
105        filename = g_strconcat(filename_default, ".jpg", NULL);
106    }
107    return filename;
108}
109
110void
111get_default_display_size(gint * width, gint * height)
112{
113    GdkDisplay *display = NULL;
114    GdkScreen *screen = NULL;
115    GdkRectangle my_rect;
116
117    display = gdk_display_get_default();
118    screen = gdk_display_get_default_screen(display);
119    gdk_screen_get_monitor_geometry(screen, 0, &my_rect);
120    *width = my_rect.width;
121    *height = my_rect.height;
122}
123
124GdkPixmap *root_bg = 0;
125void
126load_root_background(const gchar * filename, gboolean scale,
127                     gboolean reload)
128{
129    if (root_bg != 0) {
130        if (reload) {
131            g_object_unref(G_OBJECT(root_bg));
132            root_bg = 0;
133        } else {
134            return;
135        }
136    }
137
138    GtkWidget *image = gtk_image_new_from_file(filename);
139    g_object_ref(G_OBJECT(image));
140    GdkPixbuf *pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image));
141    double img_width = (double) gdk_pixbuf_get_width(pixbuf);
142    double img_height = (double) gdk_pixbuf_get_height(pixbuf);
143
144    GdkWindow *root = gdk_get_default_root_window();
145    gint width, height;
146    get_default_display_size(&width, &height);
147
148    // create pixmap
149    root_bg = gdk_pixmap_new(GDK_DRAWABLE(root), width, height, -1);
150    g_object_ref(G_OBJECT(root_bg));
151
152    // paint pixmap onto bg
153    cairo_t *ctx = gdk_cairo_create(GDK_DRAWABLE(root_bg));
154    if (scale) {
155        cairo_scale(ctx, width / img_width, height / img_height);
156    }
157    gdk_cairo_set_source_pixbuf(ctx, pixbuf, 0, 0);
158    cairo_paint(ctx);
159    cairo_destroy(ctx);
160
161    //g_object_unref(G_OBJECT (bg));
162
163    g_object_unref(G_OBJECT(image));
164}
165
166void
167draw_background(GtkWidget * widget, gpointer data)
168{
169    GdkWindow *window;
170    gint width, height, x, y;
171
172    window = gtk_widget_get_window(widget);
173    if (window == NULL) {
174        return;
175    }
176    gdk_drawable_get_size(GDK_DRAWABLE(window), &width, &height);
177    gdk_window_get_origin(GDK_WINDOW(window), &x, &y);
178    GdkPixmap *new_bg = gdk_pixmap_new(root_bg, width, height, -1);
179    g_object_ref(G_OBJECT(new_bg));
180    gdk_draw_drawable(GDK_DRAWABLE(new_bg),
181                      gdk_gc_new(GDK_DRAWABLE(new_bg)),
182                      GDK_DRAWABLE(root_bg), x, y, 0, 0, width, height);
183    gdk_window_set_back_pixmap(GDK_WINDOW(window), new_bg, 0);
184
185    gtk_widget_queue_draw(GTK_WIDGET(widget));
186}
187
188static void
189destroy(GtkWidget * widget, gpointer data)
190{
191    gtk_main_quit();
192}
193
194static void
195spawn_command(GtkWidget * widget, const gchar * command)
196{
197    GError **error = NULL;
198    g_spawn_command_line_async(command, error);
199}
200
201gboolean
202update_time(GtkWidget * label)
203{
204    time_t timet;
205    struct tm *timePtr;
206    gchar *clock_format;
207    gchar label_markup[100];
208
209    timet = time(NULL);
210    timePtr = localtime(&timet);
211
212    // Allow the users to customize the clock format including the GTK markup,
213    // for example in case they want the date non-bold and the time in bold.
214    clock_format=ldm_getenv_str_default("LDM_CLOCK_FORMAT", "%x, <b>%H:%M</b>");
215    if (strftime(label_markup, sizeof(label_markup), clock_format, timePtr))
216        gtk_label_set_markup((GtkLabel *) label, label_markup);
217
218    return TRUE;
219}
220
221gboolean
222update_timeout(GtkWidget * label)
223{
224    gchar *string;
225    int entry_length;
226    entry_length = strlen(gtk_entry_get_text((GtkEntry *) entry));
227    if (entry_length == 0 && timeout_enabled) {
228        if (timeout_left > 1) {
229            timeout_left--;
230        } else if (timeout_left == 1) {
231            g_io_channel_write_chars(g_stdout, "@GUEST@\n", -1, NULL,
232                                     NULL);
233            g_io_channel_flush(g_stdout, NULL);
234            timeout_left = 0;
235            timeout_enabled = FALSE;
236        } else if (timeout_left == 0) {
237            timeout_left = login_timeout;
238        }
239        string =
240            g_strdup_printf(_("Automatic login in %d seconds"),
241                            timeout_left);
242        gtk_label_set_markup((GtkLabel *) label, string);
243        g_free(string);
244        gtk_widget_show(timeoutbox);
245    } else {
246        timeout_left = 0;
247        gtk_widget_hide(timeoutbox);
248    }
249    return TRUE;
250}
251
252void
253destroy_popup(GtkWidget * widget, GtkWidget * popup)
254{
255    gtk_widget_destroy(popup);
256    return;
257}
258
259gboolean
260xproperty_exists(gchar * property)
261{
262    GdkAtom *actual_property_type = NULL;
263    gint *actual_format = 0;
264    gint *actual_length = 0;
265    guchar **data = NULL;
266    gboolean result;
267
268    result = gdk_property_get(gdk_get_default_root_window(),
269                              gdk_atom_intern(property, TRUE),
270                              GDK_NONE,
271                              0,
272                              512,
273                              FALSE,
274                              actual_property_type,
275                              actual_format, actual_length, data);
276    return result;
277}
278
279gboolean
280handle_command(GIOChannel * io_input)
281{
282    GString *buf;
283
284    buf = g_string_new("");
285
286    g_io_channel_read_line_string(io_input, buf, NULL, NULL);
287    g_strstrip(buf->str);
288
289    log_entry("gtkgreet", 7, "Got command: %s", buf->str);
290
291    if (!g_ascii_strncasecmp(buf->str, "msg", 3)) {
292        gchar **split_buf;
293        split_buf = g_strsplit(buf->str, " ", 2);
294        gtk_label_set_markup((GtkLabel *) StatusMessages, split_buf[1]);
295        g_strfreev(split_buf);
296    } else if (!g_ascii_strncasecmp(buf->str, "quit", 4)) {
297        if (!xproperty_exists("X11VNC_TICKER")) {
298            GdkCursor *cursor;
299            cursor = gdk_cursor_new(GDK_WATCH);
300            gdk_window_set_cursor(gdk_get_default_root_window(), cursor);
301        }
302        gtk_main_quit();
303    } else if (!g_ascii_strncasecmp(buf->str, "prompt", 6)) {
304        gchar **split_buf;
305        split_buf = g_strsplit(buf->str, " ", 2);
306        gtk_label_set_markup((GtkLabel *) UserPrompt, split_buf[1]);
307        g_strfreev(split_buf);
308    } else if (!g_ascii_strncasecmp(buf->str, "userid", 6)) {
309        timeout_enabled = login_timeout > 0;
310        if (timeout_enabled) {
311            gtk_widget_show(timeoutbox);
312        }
313        gtk_widget_show(entry);
314        gtk_widget_hide(choiceCombo);
315        gtk_entry_set_text(GTK_ENTRY(entry), "");
316        gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
317        gtk_widget_set_sensitive(GTK_WIDGET(entry), TRUE);
318        gtk_widget_set_sensitive(GTK_WIDGET(GuestButton), TRUE);
319    } else if (!g_ascii_strncasecmp(buf->str, "passwd", 6)) {
320        timeout_enabled = FALSE;
321        timeout_left = 0;
322        gtk_widget_hide(timeoutbox);
323        gtk_entry_set_text(GTK_ENTRY(entry), "");
324        gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
325        gtk_widget_set_sensitive(GTK_WIDGET(entry), TRUE);
326        gtk_widget_set_sensitive(GTK_WIDGET(GuestButton), FALSE);
327    } else if (!g_ascii_strncasecmp(buf->str, "hostname", 8)) {
328        gchar *hoststr;
329        update_selected_host();
330        hoststr = g_strdup_printf("%s\n", host);
331        g_io_channel_write_chars(g_stdout, hoststr, -1, NULL, NULL);
332        g_io_channel_flush(g_stdout, NULL);
333        g_free(hoststr);
334        gtk_widget_set_sensitive(GTK_WIDGET(entry), FALSE);
335        gtk_widget_set_sensitive(GTK_WIDGET(GuestButton), FALSE);
336    } else if (!g_ascii_strncasecmp(buf->str, "language", 8)) {
337        gchar *langstr;
338        update_selected_lang();
339        langstr = g_strdup_printf("%s\n", language);
340        g_io_channel_write_chars(g_stdout, langstr, -1, NULL, NULL);
341        g_io_channel_flush(g_stdout, NULL);
342        g_free(langstr);
343    } else if (!g_ascii_strncasecmp(buf->str, "session", 7)) {
344        gchar *sessstr;
345        update_selected_sess();
346        sessstr = g_strdup_printf("%s\n", session);
347        g_io_channel_write_chars(g_stdout, sessstr, -1, NULL, NULL);
348        g_io_channel_flush(g_stdout, NULL);
349        g_free(sessstr);
350    } else if (!g_ascii_strncasecmp(buf->str, "choice", 6)) {
351        int i;
352        GtkTreeIter iter;
353
354        // strip newline char
355        buf->len--;
356        buf->str[buf->len] = '\0';
357
358        // choice;choice 1|choice 2|choice 3
359        gchar **choices = g_strsplit(buf->str + 7, "|", -1);
360
361        // drop combo box to drop model
362        gtk_list_store_clear(choiceList);
363
364        for (i = 0; i < g_strv_length(choices); ++i) {
365            gtk_list_store_append(GTK_LIST_STORE(choiceList), &iter);
366            gtk_list_store_set(GTK_LIST_STORE(choiceList), &iter, 0,
367                               choices[i], -1);
368        }
369
370        g_strfreev(choices);
371
372        gtk_widget_hide(entry);
373        gtk_widget_show(choiceCombo);
374    } else if (!g_ascii_strncasecmp(buf->str, "pref choice", 11)) {
375        int i;
376
377        // strip newline char
378        buf->len--;
379        buf->str[buf->len] = '\0';
380
381        // pref choice;key;title;menu;icon;choice 1|choice 2|choice 3
382        gchar **args = g_strsplit(buf->str, ";", 6);
383        gchar **choices = g_strsplit(args[5], "|", -1);
384
385        GreeterPref *pref = greeter_pref_new(g_strdup(args[1]));
386        pref->type = PREF_CHOICE;
387        pref->title = g_strdup(args[2]);
388        pref->menu = g_strdup(args[3]);
389        pref->icon = g_strdup(args[4]);
390
391        for (i = 0; i < g_strv_length(choices); ++i) {
392            pref->choices =
393                g_list_append(pref->choices, g_strdup(choices[i]));
394        }
395
396        g_strfreev(choices);
397        g_strfreev(args);
398    } else if (!g_ascii_strncasecmp(buf->str, "value", 5)) {
399        gchar *name = buf->str + 6;
400        gchar *valstr;
401
402        // strip newline char
403        buf->len--;
404        buf->str[buf->len] = '\0';
405
406        valstr =
407            g_strdup_printf("%s\n", greeter_pref_get_value(name).str_val);
408        g_io_channel_write_chars(g_stdout, valstr, -1, NULL, NULL);
409        g_io_channel_flush(g_stdout, NULL);
410        g_free(valstr);
411    } else if (!g_ascii_strncasecmp(buf->str, "allowguest", 10)) {
412        gchar *valstr = buf->str + 11;
413        allowguest = g_ascii_strncasecmp(valstr, "false", 2);
414        if (!allowguest)
415            gtk_widget_hide(GTK_WIDGET(GuestButton));
416        else
417            gtk_widget_show(GTK_WIDGET(GuestButton));
418    }
419
420    g_string_free(buf, TRUE);
421    return TRUE;
422}
423
424char *
425get_sysname(void)
426{
427    struct utsname name;
428    char *node;
429
430    if (uname(&name) == 0) {
431        node = strdup(name.nodename);
432        return node;
433    }
434    return NULL;
435}
436
437static void
438handle_guestbutton(GtkButton * entry, GdkWindow * window)
439{
440    g_io_channel_write_chars(g_stdout, "@GUEST@\n", -1, NULL, NULL);
441    g_io_channel_flush(g_stdout, NULL);
442}
443
444static void
445handle_choice(GtkComboBox * combo, GdkWindow * window)
446{
447    gchar *selection;
448    gchar *entrystr;
449
450    selection = gtk_combo_box_get_active_text(GTK_COMBO_BOX(choiceCombo));
451    entrystr = g_strdup_printf("%s\n", selection);
452    g_io_channel_write_chars(g_stdout, entrystr, -1, NULL, NULL);
453    g_io_channel_flush(g_stdout, NULL);
454    g_free(entrystr);
455}
456
457static void
458handle_entry(GtkEntry * entry, GdkWindow * window)
459{
460    gchar *entrystr;
461
462    entrystr = g_strdup_printf("%s\n", gtk_entry_get_text(entry));
463    g_io_channel_write_chars(g_stdout, entrystr, -1, NULL, NULL);
464    g_io_channel_flush(g_stdout, NULL);
465    g_free(entrystr);
466    if (gtk_entry_get_visibility(GTK_ENTRY(entry)))
467        gtk_entry_set_text(entry, "");
468}
469
470static gboolean
471menu_append_pref(gpointer akey, gpointer avalue, gpointer adata)
472{
473    char *key = (char *) akey;
474    GreeterPref *pref = (GreeterPref *) avalue;
475    GtkWidget *menu = (GtkWidget *) adata;
476    GtkWidget *pref_item, *prefico;
477
478    pref_item = gtk_image_menu_item_new_with_mnemonic(_(pref->menu));
479    prefico = gtk_image_new_from_file(ldm_theme_file(pref->icon));
480    gtk_image_menu_item_set_image((GtkImageMenuItem *) pref_item, prefico);
481
482    g_signal_connect(G_OBJECT(pref_item), "activate",
483                     G_CALLBACK(prefwin), key);
484    gtk_menu_shell_append(GTK_MENU_SHELL(menu), pref_item);
485
486    return FALSE;
487}
488
489static void
490popup_menu(GtkWidget * widget, GtkWindow * window)
491{
492    GtkWidget *menu, *lang_item, *sess_item, *host_item, *custom_item,
493        *quit_item, *reboot_item;
494    GtkWidget *sep, *langico, *sessico, *hostico, *customico, *rebootico,
495        *haltico;
496    gchar custom_env_var[20], *custom_mnemonic, *custom_command;
497    int i;
498
499    menu = gtk_menu_new();
500
501    if (getenv("LDM_FORCE_LANGUAGE") == NULL) {
502        lang_item =
503            gtk_image_menu_item_new_with_mnemonic(_
504                                                  ("Select _Language ..."));
505        langico = gtk_image_new_from_file(ldm_theme_file("language"));
506        gtk_image_menu_item_set_image((GtkImageMenuItem *) lang_item,
507                                      langico);
508        g_signal_connect_swapped(G_OBJECT(lang_item), "activate",
509                                 G_CALLBACK(langwin), window);
510        gtk_menu_shell_append(GTK_MENU_SHELL(menu), lang_item);
511    }
512
513    if (getenv("LDM_FORCE_SESSION") == NULL) {
514        sess_item =
515            gtk_image_menu_item_new_with_mnemonic(_
516                                                  ("Select _Session ..."));
517        sessico = gtk_image_new_from_file(ldm_theme_file("session"));
518        gtk_image_menu_item_set_image((GtkImageMenuItem *) sess_item,
519                                      sessico);
520        g_signal_connect_swapped(G_OBJECT(sess_item), "activate",
521                                 G_CALLBACK(sesswin), window);
522        gtk_menu_shell_append(GTK_MENU_SHELL(menu), sess_item);
523    }
524
525    if (ldminfo_size() > 1) {
526        host_item =
527            gtk_image_menu_item_new_with_mnemonic(_("Select _Host ..."));
528        hostico = gtk_image_new_from_file(ldm_theme_file("host"));
529        gtk_image_menu_item_set_image((GtkImageMenuItem *) host_item,
530                                      hostico);
531        g_signal_connect_swapped(G_OBJECT(host_item), "activate",
532                                 G_CALLBACK(hostwin), window);
533        gtk_menu_shell_append(GTK_MENU_SHELL(menu), host_item);
534    }
535
536    for (i = 0; i <= 9; i++) {
537        g_sprintf(custom_env_var, "LDM_MENU_ITEM_%d", i);
538        custom_mnemonic = getenv(custom_env_var);
539        if (custom_mnemonic == NULL)
540            continue;
541        custom_item =
542            gtk_image_menu_item_new_with_mnemonic(custom_mnemonic);
543        g_sprintf(custom_env_var, "LDM_MENU_COMMAND_%d", i);
544        custom_command = getenv(custom_env_var);
545        if (custom_command == NULL) {
546            gtk_widget_destroy(custom_item);
547            continue;
548        }
549        customico = gtk_image_new_from_file(ldm_theme_file("backend"));
550        gtk_image_menu_item_set_image((GtkImageMenuItem *) custom_item,
551                                      customico);
552        g_signal_connect(G_OBJECT(custom_item), "activate",
553                         G_CALLBACK(spawn_command),
554                         g_strdup(custom_command));
555        gtk_menu_shell_append(GTK_MENU_SHELL(menu), custom_item);
556    }
557    greeter_pref_foreach(menu_append_pref, menu);
558
559    sep = gtk_separator_menu_item_new();
560    gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
561
562    reboot_item = gtk_image_menu_item_new_with_mnemonic(_("_Reboot"));
563    rebootico = gtk_image_new_from_file(ldm_theme_file("reboot"));
564    gtk_image_menu_item_set_image((GtkImageMenuItem *) reboot_item,
565                                  rebootico);
566    gtk_menu_shell_append(GTK_MENU_SHELL(menu), reboot_item);
567    g_signal_connect(G_OBJECT(reboot_item), "activate",
568                     G_CALLBACK(spawn_command), "/sbin/reboot");
569
570    quit_item = gtk_image_menu_item_new_with_mnemonic(_("Shut_down"));
571    haltico = gtk_image_new_from_file(ldm_theme_file("shutdown"));
572    gtk_image_menu_item_set_image((GtkImageMenuItem *) quit_item, haltico);
573    g_signal_connect(G_OBJECT(quit_item), "activate",
574                     G_CALLBACK(spawn_command), "/sbin/poweroff");
575    gtk_menu_shell_append(GTK_MENU_SHELL(menu), quit_item);
576
577    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
578                   0, gtk_get_current_event_time());
579
580    gtk_widget_show_all(menu);
581    gtk_menu_reposition(GTK_MENU(menu));
582
583    return;
584}
585
586/*
587 * scopy()
588 *
589 * Copy a string.  Used to move data in and out of our ldminfo structure.
590 * Note: if the source string is null, or points to a valid string of '\0',
591 * both result in a dest string length of 0.
592 */
593
594char *
595scopy(char *dest, char *source)
596{
597    if (!source)
598        *dest = '\0';
599    else {
600        strncpy(dest, source, MAXSTRSZ - 1);
601        *(dest + MAXSTRSZ - 1) = '\0';           /* ensure null termination */
602    }
603
604    return dest;
605}
606
607/*
608 * Remap GDK_Tab to behaves as enter
609 * Inspired by gdm/gui/gdmlogin.c
610 */
611static gboolean
612key_press_event(GtkWidget * widget, GdkEventKey * event, gpointer window)
613{
614    if ((event->keyval == GDK_Tab ||
615         event->keyval == GDK_KP_Tab) &&
616        (event->
617         state & (GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SHIFT_MASK)) ==
618        0) {
619        handle_entry(GTK_ENTRY(entry), window);
620        return TRUE;
621    }
622
623    return FALSE;
624}
625
626int
627main(int argc, char *argv[])
628{
629    gint lw, lh;
630
631    GtkWidget *loginWindow, *prefBar;
632    GdkCursor *normcursor, *busycursor;
633    GtkWidget *syslabel, *timelabel;
634    GtkWidget *logo, *EntryBox;
635    GtkWidget *timeoutspacer1, *timeoutspacer2, *timeoutlabel;
636    GtkWidget *entryspacer1, *entryspacer2;
637    GtkWidget *optionico;
638    GtkWidget *optionbutton;
639    GdkWindow *root;
640    GdkPixbuf *pix;
641    gint width, height;
642    GIOChannel *g_stdin;
643    char *ldm_theme;
644
645#ifdef ENABLE_NLS
646    setlocale(LC_ALL, "");
647    bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
648    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
649    textdomain(GETTEXT_PACKAGE);
650#endif
651
652    /* Init log settings */
653    log_init(ldm_getenv_bool("LDM_SYSLOG"),
654             ldm_getenv_int("LDM_LOGLEVEL", -1));
655
656    gtk_init(&argc, &argv);
657    ldm_theme = getenv("LDM_THEME");
658
659    if (ldm_theme) {
660        if (*ldm_theme == '/')
661            ldm_theme_dir = g_strdup(ldm_theme);
662        else
663            ldm_theme_dir = g_strconcat(LDM_THEME_DIR, ldm_theme, NULL);
664    } else {
665        ldm_theme_dir = g_strconcat(LDM_THEME_DIR, "default", NULL);
666    }
667
668    allowguest = ldm_getenv_bool("LDM_GUESTLOGIN");
669    gtk_rc_add_default_file(ldm_theme_file("/greeter-gtkrc"));
670
671    /* Initialize information about hosts */
672    ldminfo_init(&host_list, getenv("LDM_SERVER"));
673
674    normcursor = gdk_cursor_new(GDK_LEFT_PTR);
675    busycursor = gdk_cursor_new(GDK_WATCH);
676
677
678    root = gdk_get_default_root_window();
679    gdk_window_set_cursor(root, busycursor);
680
681    greeter_pref_init();
682
683    /* Set the background */
684    load_root_background(ldm_theme_file("bg"), TRUE, FALSE);
685
686    get_default_display_size(&width, &height);
687
688    /* Setup the time and system labels */
689    {
690        const char *hoststring = 0;
691        syslabel = gtk_label_new("");
692        timelabel = gtk_label_new("");
693#ifdef K12LINUX
694        hoststring =
695            g_strdup_printf("<b>%s</b> (%s)", get_sysname(),
696                            getenv("LDMINFO_IPADDR"));
697#else
698        hoststring =
699            g_strdup_printf("<b>%s</b> (%s) -", get_sysname(),
700                            getenv("LDMINFO_IPADDR"));
701#endif
702        gtk_label_set_markup((GtkLabel *) syslabel, hoststring);
703        update_time(timelabel);
704
705        g_timeout_add(30000, (GSourceFunc) update_time, timelabel);
706    }
707
708    /**** Create the login window ****/
709    loginWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
710
711    /* Create the options button */
712    {
713
714
715        optionbutton = gtk_button_new_with_mnemonic(_("_Preferences"));
716        optionico = gtk_image_new_from_file(ldm_theme_file("preferences"));
717        gtk_button_set_image((GtkButton *) optionbutton, optionico);
718
719        gtk_button_set_relief((GtkButton *) optionbutton, GTK_RELIEF_NONE);
720        gtk_button_set_focus_on_click((GtkButton *) optionbutton, FALSE);
721
722        g_signal_connect(G_OBJECT(optionbutton), "clicked",
723                         G_CALLBACK(popup_menu), loginWindow);
724    }
725
726    /**** Create the login window ****/
727    {
728        GtkWidget *guestbox, *guestspacer1, *guestspacer2, *vbox, *vbox2,
729            *vbox2spacer, *hbox;
730        GtkCellRenderer *renderer;
731
732        g_signal_connect(G_OBJECT(loginWindow), "destroy",
733                         G_CALLBACK(destroy), NULL);
734
735        gtk_widget_set_app_paintable(loginWindow, TRUE);
736        g_signal_connect(loginWindow, "configure-event",
737                         G_CALLBACK(draw_background), NULL);
738        gtk_widget_set_size_request(loginWindow, width, height);
739        gtk_widget_realize(loginWindow);
740        gtk_window_set_decorated(GTK_WINDOW(loginWindow), FALSE);
741
742        logo = gtk_image_new_from_file(ldm_theme_file("logo"));
743#ifdef K12LINUX
744        if (access(ldm_theme_file("bottom_right"), R_OK) == 0) {
745            bottom_right =
746                gtk_image_new_from_file(ldm_theme_file("bottom_right"));
747            has_bottom_right_image = TRUE;
748        } else
749            has_bottom_right_image = FALSE;
750#endif
751
752        pix = gtk_image_get_pixbuf((GtkImage *) logo);
753        lw = gdk_pixbuf_get_width(pix);
754        lh = gdk_pixbuf_get_height(pix);
755
756
757        vbox = gtk_vbox_new(FALSE, 5);
758        vbox2 = gtk_vbox_new(FALSE, ((height / 2) - lh));
759        vbox2spacer = gtk_vbox_new(FALSE, 5);
760        EntryBox = gtk_hbox_new(FALSE, 5);
761        hbox = gtk_hbox_new(FALSE, 0);
762
763        UserPrompt = gtk_label_new("");
764
765        if (lw < 180)
766            lw = 180;
767
768        gtk_misc_set_alignment((GtkMisc *) UserPrompt, 1, 0.5);
769        gtk_widget_set_size_request(UserPrompt, (lw / 2), 0);
770
771        StatusMessages = gtk_label_new("");
772        entry = gtk_entry_new();
773        gtk_entry_set_width_chars(GTK_ENTRY(entry), 20);
774        g_signal_connect(G_OBJECT(entry), "activate",
775                         G_CALLBACK(handle_entry), root);
776        // Remap tab on entry to behave as enter
777        g_signal_connect(G_OBJECT(entry), "key_press_event",
778                         G_CALLBACK(key_press_event), loginWindow);
779
780        choiceList = gtk_list_store_new(1, G_TYPE_STRING);
781        choiceCombo =
782            gtk_combo_box_new_with_model(GTK_TREE_MODEL(choiceList));
783        renderer = gtk_cell_renderer_text_new();
784        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(choiceCombo),
785                                   GTK_CELL_RENDERER(renderer), TRUE);
786        gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(choiceCombo),
787                                      GTK_CELL_RENDERER(renderer),
788                                      "text", 0);
789        g_signal_connect(G_OBJECT(choiceCombo), "changed",
790                         G_CALLBACK(handle_choice), root);
791
792        if (getenv("LDM_LOGIN_TIMEOUT") != NULL) {
793            login_timeout = atoi(getenv("LDM_LOGIN_TIMEOUT"));
794        } else {
795            login_timeout = 0;
796        }
797        timeout_enabled = login_timeout > 0;
798        timeout_left = 0;
799        timeoutspacer1 = gtk_label_new("");
800        timeoutspacer2 = gtk_label_new("");
801        timeoutlabel = gtk_label_new("");
802        timeoutbox = gtk_hbox_new(FALSE, 0);
803        gtk_box_pack_start(GTK_BOX(vbox), timeoutbox, FALSE, FALSE, 0);
804        gtk_box_pack_start(GTK_BOX(timeoutbox), timeoutspacer1, TRUE,
805                           FALSE, 0);
806        gtk_box_pack_start(GTK_BOX(timeoutbox), timeoutlabel, FALSE, FALSE,
807                           0);
808        gtk_box_pack_start(GTK_BOX(timeoutbox), timeoutspacer2, TRUE,
809                           FALSE, 0);
810        g_timeout_add(1000, (GSourceFunc) update_timeout, timeoutlabel);
811
812        guestspacer1 = gtk_label_new("");
813        guestspacer2 = gtk_label_new("");
814        GuestButton = gtk_button_new_with_label(_("Login as Guest"));
815        g_signal_connect(G_OBJECT(GuestButton), "clicked",
816                         G_CALLBACK(handle_guestbutton), root);
817        gtk_button_set_focus_on_click((GtkButton *) GuestButton, FALSE);
818        guestbox = gtk_hbox_new(FALSE, 0);
819        gtk_box_pack_start(GTK_BOX(guestbox), guestspacer1, TRUE, FALSE,
820                           0);
821        gtk_box_pack_start(GTK_BOX(guestbox), GuestButton, FALSE, FALSE,
822                           0);
823        gtk_box_pack_start(GTK_BOX(guestbox), guestspacer2, TRUE, FALSE,
824                           0);
825
826        entryspacer1 = gtk_label_new("");
827        entryspacer2 = gtk_label_new("");
828        gtk_box_pack_start(GTK_BOX(EntryBox), entryspacer1, TRUE, FALSE,
829                           0);
830        gtk_box_pack_start(GTK_BOX(EntryBox), UserPrompt, FALSE, FALSE, 0);
831        gtk_box_pack_start(GTK_BOX(EntryBox), entry, FALSE, FALSE, 0);
832        gtk_box_pack_start(GTK_BOX(EntryBox), choiceCombo, FALSE, FALSE,
833                           0);
834        gtk_box_pack_start(GTK_BOX(EntryBox), entryspacer2, TRUE, FALSE,
835                           0);
836
837        gtk_box_pack_start(GTK_BOX(vbox), logo, FALSE, FALSE, 5);
838        gtk_box_pack_start(GTK_BOX(vbox), EntryBox, TRUE, FALSE, 0);
839        if (allowguest)
840            gtk_box_pack_start(GTK_BOX(vbox), guestbox, FALSE, FALSE, 0);
841        gtk_box_pack_start(GTK_BOX(vbox), timeoutbox, FALSE, FALSE, 0);
842        gtk_box_pack_start(GTK_BOX(vbox), StatusMessages, TRUE, FALSE, 0);
843        gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, FALSE, 0);
844        gtk_box_pack_start(GTK_BOX(vbox2), vbox2spacer, FALSE, FALSE, 0);
845        gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
846
847        gtk_container_add(GTK_CONTAINER(loginWindow), vbox2);
848    }
849
850    /**** Create the preference bar ****/
851    prefBar = gtk_window_new(GTK_WINDOW_TOPLEVEL);
852    {
853        GtkWidget *BottomBarBox;
854
855        gtk_widget_set_app_paintable(GTK_WIDGET(prefBar), TRUE);
856        g_signal_connect(prefBar, "configure-event",
857                         G_CALLBACK(draw_background), NULL);
858        gtk_window_set_decorated(GTK_WINDOW(prefBar), FALSE);
859        gtk_widget_set_size_request(prefBar, width, BOTTOM_BAR_HEIGHT);
860
861        BottomBarBox = gtk_hbox_new(FALSE, 0);
862#ifndef K12LINUX
863        gtk_box_pack_start(GTK_BOX(BottomBarBox),
864                           GTK_WIDGET(optionbutton), FALSE, FALSE, 5);
865
866        gtk_box_pack_end(GTK_BOX(BottomBarBox),
867                         GTK_WIDGET(timelabel), FALSE, FALSE, 5);
868
869        gtk_box_pack_end(GTK_BOX(BottomBarBox),
870                         GTK_WIDGET(syslabel), FALSE, FALSE, 0);
871#else
872        optionbutton_box = gtk_vbox_new(FALSE, 0);
873        optionbutton_spacer = gtk_label_new("");
874        gtk_box_pack_start(GTK_BOX(optionbutton_box),
875                           GTK_WIDGET(optionbutton_spacer), TRUE, FALSE,
876                           0);
877        gtk_box_pack_end(GTK_BOX(optionbutton_box),
878                         GTK_WIDGET(optionbutton), FALSE, FALSE, 5);
879        gtk_box_pack_start(GTK_BOX(BottomBarBox),
880                           GTK_WIDGET(optionbutton_box), FALSE, FALSE, 5);
881
882        if (has_bottom_right_image == TRUE) {
883            bottom_right_box = gtk_vbox_new(FALSE, 0);
884            bottom_right_spacer = gtk_label_new("");
885            gtk_box_pack_start(GTK_BOX(bottom_right_box),
886                               GTK_WIDGET(bottom_right_spacer), TRUE,
887                               FALSE, 0);
888            gtk_box_pack_end(GTK_BOX(bottom_right_box),
889                             GTK_WIDGET(bottom_right), FALSE, FALSE, 0);
890            gtk_box_pack_end(GTK_BOX(BottomBarBox),
891                             GTK_WIDGET(bottom_right_box), FALSE, FALSE,
892                             0);
893        }
894#endif
895        gtk_container_add(GTK_CONTAINER(prefBar), BottomBarBox);
896    }
897
898#ifdef K12LINUX
899    /**** Create the TopBarBox ****/
900    topBar = gtk_window_new(GTK_WINDOW_TOPLEVEL);
901    {
902        GtkWidget *TopBarBox;
903
904        gtk_window_set_decorated(GTK_WINDOW(topBar), FALSE);
905        gtk_widget_set_size_request(topBar, width, TOP_BAR_HEIGHT);
906
907        TopBarBox = gtk_hbox_new(FALSE, 5);
908        gtk_box_pack_start(GTK_BOX(TopBarBox),
909                           GTK_WIDGET(syslabel), FALSE, FALSE, 5);
910        gtk_box_pack_end(GTK_BOX(TopBarBox),
911                         GTK_WIDGET(timelabel), FALSE, FALSE, 5);
912    }
913#endif
914    /* Show everything */
915
916    gtk_widget_show_all(loginWindow);
917    gtk_widget_show_all(prefBar);
918    gtk_window_move(GTK_WINDOW(loginWindow), 0, 0);
919    gtk_window_move(GTK_WINDOW(prefBar), 0, height - BOTTOM_BAR_HEIGHT);
920#ifdef K12LINUX
921    gtk_widget_show_all(topBar);
922    gtk_window_move(GTK_WINDOW(topBar), 0, 0);
923#endif
924
925    // Center the mouse pointer on the default display
926    GdkDisplay *display = gdk_display_get_default();
927    GdkScreen *screen = gdk_display_get_default_screen(display);
928    GdkRectangle bbox;
929    gdk_screen_get_monitor_geometry(screen, 0, &bbox);
930    gdk_display_warp_pointer(display, screen, bbox.width/2, bbox.height/2);
931    gdk_window_set_cursor(root, normcursor);
932
933#ifdef K12LINUX
934    gtk_widget_grab_focus(GTK_WIDGET(entry));
935#endif
936
937    /*
938     * Start listening to stdin
939     */
940
941    g_stdin = g_io_channel_unix_new(STDIN_FILENO);      /* listen to stdin */
942    g_stdout = g_io_channel_unix_new(STDOUT_FILENO);
943    g_io_add_watch(g_stdin, G_IO_IN, (GIOFunc) handle_command, g_stdin);
944
945    gtk_main();
946
947    log_close();
948    return 0;
949}
Note: See TracBrowser for help on using the repository browser.