/* GDMSetup * Copyright (C) 2002, George Lebl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gdm.h" #include "gdmcommon.h" #include "misc.h" #include "gdmcomm.h" #include "gdmuser.h" /* set the DOING_GDM_DEVELOPMENT env variable if you want to * search for the glade file in the current dir and not the system * install dir, better then something you have to change * in the source and recompile */ static gboolean DOING_GDM_DEVELOPMENT = FALSE; static gboolean RUNNING_UNDER_GDM = FALSE; gint GdmIconMaxHeight; gint GdmIconMaxWidth; gint GdmMinimalUID = 100; gchar *GdmExclude = NULL; gchar *GdmInclude = NULL; gboolean GdmIncludeAll; gboolean GdmAllowRoot; gboolean GdmAllowRemoteRoot; static char *GdmSoundProgram = NULL; static gboolean gdm_running = FALSE; static GladeXML *xml; static GList *timeout_widgets = NULL; static gchar *last_theme_installed = NULL; static int last_remote_login_setting = -1; static gboolean have_sound_ready_file = FALSE; static gboolean have_sound_success_file = FALSE; static gboolean have_sound_failure_file = FALSE; static char *selected_themes = NULL; static char *selected_theme = NULL; static gchar *config_file; enum { XSERVER_COLUMN_VT, XSERVER_COLUMN_SERVER, XSERVER_COLUMN_OPTIONS, XSERVER_NUM_COLUMNS }; enum { THEME_COLUMN_SELECTED, THEME_COLUMN_SELECTED_LIST, THEME_COLUMN_DIR, THEME_COLUMN_FILE, THEME_COLUMN_NAME, THEME_COLUMN_DESCRIPTION, THEME_COLUMN_AUTHOR, THEME_COLUMN_COPYRIGHT, THEME_COLUMN_SCREENSHOT, THEME_NUM_COLUMNS }; enum { USERLIST_NAME, USERLIST_NUM_COLUMNS }; enum { ONE_THEME, RANDOM_THEME }; static void simple_spawn_sync (char **argv) { g_spawn_sync (NULL /* working_directory */, argv, NULL /* envp */, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL /* child_setup */, NULL /* user_data */, NULL /* stdout */, NULL /* stderr */, NULL /* exit status */, NULL /* error */); } static void setup_cursor (GdkCursorType type) { GdkCursor *cursor = gdk_cursor_new (type); gdk_window_set_cursor (gdk_get_default_root_window (), cursor); gdk_cursor_unref (cursor); } static void setup_window_cursor (GdkCursorType type) { GdkCursor *cursor = gdk_cursor_new (type); GtkWidget *setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); if (setup_dialog->window) gdk_window_set_cursor (setup_dialog->window, cursor); gdk_cursor_unref (cursor); } static void unsetup_window_cursor (void) { GtkWidget *setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); if (setup_dialog->window) gdk_window_set_cursor (setup_dialog->window, NULL); } static void update_greeters (void) { char *p, *ret; long pid; static gboolean shown_error = FALSE; gboolean have_error = FALSE; /* recheck for gdm */ gdm_running = gdmcomm_check (config_file, FALSE /* gui_bitching */); if ( ! gdm_running) return; ret = gdmcomm_call_gdm (GDM_SUP_GREETERPIDS, NULL /* auth_cookie */, "2.3.90.2", 5); if (ret == NULL) return; p = strchr (ret, ' '); if (p == NULL) { g_free (ret); return; } p++; for (;;) { if (sscanf (p, "%ld", &pid) != 1) { g_free (ret); goto check_update_error; } /* sanity */ if (pid <= 0) continue; if (kill (pid, SIGHUP) != 0) have_error = TRUE; p = strchr (p, ';'); if (p == NULL) { g_free (ret); goto check_update_error; } p++; } check_update_error: if ( ! shown_error && have_error) { GtkWidget *setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); GtkWidget *dlg = ve_hig_dialog_new (GTK_WINDOW (setup_dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("An error occurred while " "trying to contact the " "login screens. Not all " "updates may have taken " "effect."), ""); gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); shown_error = TRUE; } } static gboolean the_timeout (gpointer data) { GtkWidget *widget = data; gboolean (*func) (GtkWidget *); func = g_object_get_data (G_OBJECT (widget), "timeout_func"); if ( ! (*func) (widget)) { g_object_set_data (G_OBJECT (widget), "change_timeout", NULL); g_object_set_data (G_OBJECT (widget), "timeout_func", NULL); timeout_widgets = g_list_remove (timeout_widgets, widget); return FALSE; } else { return TRUE; } } static void run_timeout (GtkWidget *widget, guint tm, gboolean (*func) (GtkWidget *)) { guint id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), "change_timeout")); if (id != 0) { g_source_remove (id); } else { timeout_widgets = g_list_prepend (timeout_widgets, widget); } id = g_timeout_add (tm, the_timeout, widget); g_object_set_data (G_OBJECT (widget), "timeout_func", func); g_object_set_data (G_OBJECT (widget), "change_timeout", GUINT_TO_POINTER (id)); } static void update_key (const char *notify_key) { if (notify_key == NULL) return; /* recheck for gdm */ gdm_running = gdmcomm_check (config_file, FALSE /* gui_bitching */); if (gdm_running) { char *ret; char *s = g_strdup_printf ("%s %s", GDM_SUP_UPDATE_CONFIG, notify_key); ret = gdmcomm_call_gdm (s, NULL /* auth_cookie */, "2.3.90.2", 5); g_free (s); g_free (ret); } } static gboolean toggle_timeout (GtkWidget *toggle) { const char *key = g_object_get_data (G_OBJECT (toggle), "key"); const char *notify_key = g_object_get_data (G_OBJECT (toggle), "notify_key"); VeConfig *config = ve_config_get (config_file); gboolean val = ve_config_get_bool (config, key); if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) { ve_config_set_bool (config, key, GTK_TOGGLE_BUTTON (toggle)->active); ve_config_save (config, FALSE /* force */); update_key (notify_key); } return FALSE; } static gboolean intspin_timeout (GtkWidget *spin) { const char *key = g_object_get_data (G_OBJECT (spin), "key"); const char *notify_key = g_object_get_data (G_OBJECT (spin), "notify_key"); int val, new_val; VeConfig *config = ve_config_get (config_file); new_val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin)); val = ve_config_get_int (config, key); if (val != new_val) { ve_config_set_int (config, key, new_val); ve_config_save (config, FALSE /* force */); update_key (notify_key); } return FALSE; } static void xservers_get_servers (GtkListStore *store) { /* Find server definitions */ VeConfig *cfg = ve_config_get (config_file); GList *list, *li; gchar *server, *options, *cpy; /* Fill list with all the active servers */ list = ve_config_get_keys (cfg, GDM_KEY_SECTION_SERVERS); for (li = list; li != NULL; li = li->next) { GtkTreeIter iter; char *key = li->data; int vt = atoi(key); key = g_strconcat(GDM_KEY_SECTION_SERVERS, "/", key, NULL); cpy = ve_config_get_string (cfg, key); g_free (key); server = ve_first_word (cpy); options = ve_rest (cpy); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, XSERVER_COLUMN_VT, vt, XSERVER_COLUMN_SERVER, server, XSERVER_COLUMN_OPTIONS, options, -1); g_free(server); } } static GSList * xservers_get_server_definitions() { /* Find server definitions */ GSList *xservers = NULL; GList *list, *li; VeConfig *cfg = ve_config_get (config_file); gchar *StandardXServer = ve_config_get_string (cfg, GDM_KEY_STANDARD_XSERVER); /* Fill list with all server definitions */ list = ve_config_get_sections (cfg); for (li = list; li != NULL; li = li->next) { const char *sec = li->data; if (strncmp (sec, GDM_KEY_SERVER_PREFIX, strlen (GDM_KEY_SERVER_PREFIX)) == 0) { GdmXServer *svr = g_new0 (GdmXServer, 1); char buf[256]; svr->id = g_strdup (sec + strlen (GDM_KEY_SERVER_PREFIX)); g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_NAME, sec); svr->name = ve_config_get_string (cfg, buf); g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_COMMAND, sec); svr->command = ve_config_get_string (cfg, buf); g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_FLEXIBLE, sec); svr->flexible = ve_config_get_bool (cfg, buf); g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_CHOOSABLE, sec); svr->choosable = ve_config_get_bool (cfg, buf); g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_HANDLED, sec); svr->handled = ve_config_get_bool (cfg, buf); g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_CHOOSER, sec); svr->chooser = ve_config_get_bool (cfg, buf); if (ve_string_empty (svr->command)) { g_free (svr->command); svr->command = g_strdup (StandardXServer); } xservers = g_slist_append (xservers, svr); } } return xservers; } static void xserver_update_delete_sensitivity() { GtkWidget *modify_combobox, *delete_button; GtkListStore *store; GtkTreeIter iter; GSList *xservers; GdmXServer *xserver; gchar *text; gchar *selected; gboolean valid; gint i; modify_combobox = glade_helper_get (xml, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); delete_button = glade_helper_get (xml, "xserver_delete_button", GTK_TYPE_BUTTON); /* Get list of servers that are set to start */ store = gtk_list_store_new (XSERVER_NUM_COLUMNS, G_TYPE_INT /* virtual terminal */, G_TYPE_STRING /* server type */, G_TYPE_STRING /* options */); xservers_get_servers(store); /* Get list of servers and determine which one was selected */ xservers = xservers_get_server_definitions(); i = gtk_combo_box_get_active (GTK_COMBO_BOX (modify_combobox)); if (i < 0) { gtk_widget_set_sensitive(delete_button, FALSE); } else { /* Get the xserver selected */ xserver = g_slist_nth_data(xservers, i); /* Sensitivity of delete_button */ if (g_slist_length(xservers) <= 1) { /* Can't delete the laster server */ gtk_widget_set_sensitive(delete_button, FALSE); } else { gtk_widget_set_sensitive(delete_button, TRUE); valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); selected = gtk_combo_box_get_active_text ( GTK_COMBO_BOX (modify_combobox)); /* Can't delete servers currently in use */ while (valid) { gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, XSERVER_COLUMN_SERVER, &text, -1); if (strcmp (text, selected) == 0) { gtk_widget_set_sensitive(delete_button, FALSE); break; } valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); } } } } static gboolean combobox_timeout (GtkWidget *combo_box) { const char *key = g_object_get_data (G_OBJECT (combo_box), "key"); int selected = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box)); VeConfig *config = ve_config_get (config_file); /* Local Greeter and Remote Greeter Comboboxes */ if (strcmp (key, GDM_KEY_REMOTEGREETER) == 0 || strcmp (key, GDM_KEY_GREETER) == 0) { char *new_val = NULL; gchar *val; if (strcmp (key, GDM_KEY_REMOTEGREETER) == 0 && selected == 2) { /* Disable remote login if selected */ GtkWidget *toggle = glade_helper_get (xml, "enable_xdmcp", GTK_TYPE_TOGGLE_BUTTON); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE); return FALSE; } else if (selected == 0) { /* GTK+ Greeter */ new_val = g_strdup (EXPANDED_LIBEXECDIR "/gdmlogin"); last_remote_login_setting = 0; } else if (selected == 1) { /* Themed Greeter */ new_val = g_strdup (EXPANDED_LIBEXECDIR "/gdmgreeter"); last_remote_login_setting = 1; } val = ve_config_get_string (config, key); if (new_val && strcmp (ve_sure_string (val), ve_sure_string (new_val)) != 0) { ve_config_set_string (config, key, new_val); ve_config_save (config, FALSE /* force */); update_key (key); } g_free (new_val); /* Automatic Login Combobox */ } else if (strcmp (key, GDM_KEY_AUTOMATICLOGIN) == 0 || strcmp (key, GDM_KEY_TIMED_LOGIN) == 0) { GtkTreeIter iter; char *new_val = NULL; gchar *val; if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box), &iter)) { gtk_tree_model_get (gtk_combo_box_get_model ( GTK_COMBO_BOX (combo_box)), &iter, 0, &new_val, -1); } val = ve_config_get_string (config, key); if (new_val && strcmp (ve_sure_string (val), ve_sure_string (new_val)) != 0) { ve_config_set_string (config, key, new_val); ve_config_save (config, FALSE /* force */); update_key (key); } g_free (new_val); /* Theme Combobox */ } else if (strcmp (key, GDM_KEY_GRAPHICAL_THEME_RAND) == 0 ) { gboolean GdmGraphicalThemeRand; gboolean new_val; GtkTreeViewColumn *radioColumn = NULL; GtkTreeViewColumn *checkboxColumn = NULL; GtkTreeSelection *selection; GtkTreeIter iter; GValue value = {0, }; gboolean val = ve_config_get_bool (config, key); GtkWidget *theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); GtkWidget *del_button = glade_helper_get (xml, "gg_delete_theme", GTK_TYPE_BUTTON); /* Choose to display radio or checkbox toggle column */ if (selected == RANDOM_THEME) { new_val = TRUE; radioColumn = gtk_tree_view_get_column (GTK_TREE_VIEW (theme_list), THEME_COLUMN_SELECTED); checkboxColumn = gtk_tree_view_get_column (GTK_TREE_VIEW (theme_list), THEME_COLUMN_SELECTED_LIST); gtk_tree_view_column_set_visible (radioColumn, FALSE); gtk_tree_view_column_set_visible (checkboxColumn, TRUE); } else { /* Default to one theme */ new_val = FALSE; radioColumn = gtk_tree_view_get_column (GTK_TREE_VIEW (theme_list), THEME_COLUMN_SELECTED); checkboxColumn = gtk_tree_view_get_column (GTK_TREE_VIEW (theme_list), THEME_COLUMN_SELECTED_LIST); gtk_tree_view_column_set_visible (radioColumn, TRUE); gtk_tree_view_column_set_visible (checkboxColumn, FALSE); } /* Update config */ if (new_val != val) { ve_config_set_bool (config, key, new_val); ve_config_save (config, FALSE /* force */); update_key (key); } /* Update Delete Button's sensitivity */ GdmGraphicalThemeRand = ve_config_get_bool ( ve_config_get (config_file), GDM_KEY_GRAPHICAL_THEME_RAND); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); gtk_widget_set_sensitive (del_button, FALSE); if ( ! gtk_tree_selection_get_selected (selection, NULL, &iter)) { gtk_widget_set_sensitive (del_button, FALSE); } else { GtkTreeModel *model; /* Default to allow deleting of themes */ gtk_widget_set_sensitive (del_button, TRUE); /* Determine if the theme selected is currently active */ model = gtk_tree_view_get_model (GTK_TREE_VIEW (theme_list)); if (GdmGraphicalThemeRand) { gtk_tree_model_get_value (model, &iter, THEME_COLUMN_SELECTED_LIST, &value); } else { gtk_tree_model_get_value (model, &iter, THEME_COLUMN_SELECTED, &value); } /* Do not allow deleting of active themes */ if (g_value_get_boolean (&value)) { gtk_widget_set_sensitive (del_button, FALSE); } } /* Add/Modify Server to Start combobox */ } else if (strcmp (key, GDM_KEY_SECTION_SERVERS) == 0 ) { GtkWidget *add_button = glade_helper_get (xml, "xserver_add_button", GTK_TYPE_BUTTON); gtk_widget_set_sensitive(add_button, TRUE); /* Modify Server Definition combobox */ } else if (strcmp (key, GDM_KEY_SERVER_PREFIX) == 0 ) { /* Init Widgets */ GtkWidget *frame, *modify_combobox; GtkWidget *name_entry, *command_entry; GtkWidget *handled_check, *flexible_check; GtkWidget *greeter_radio, *chooser_radio; GtkWidget *create_button, *delete_button; GtkListStore *store; GSList *xservers; GdmXServer *xserver; gint i; /* Get Widgets from glade */ frame = glade_helper_get (xml, "xserver_modify_frame", GTK_TYPE_FRAME); name_entry = glade_helper_get (xml, "xserver_name_entry", GTK_TYPE_ENTRY); command_entry = glade_helper_get (xml, "xserver_command_entry", GTK_TYPE_ENTRY); handled_check = glade_helper_get (xml, "xserver_handled_checkbutton", GTK_TYPE_CHECK_BUTTON); flexible_check = glade_helper_get (xml, "xserver_flexible_checkbutton", GTK_TYPE_CHECK_BUTTON); greeter_radio = glade_helper_get (xml, "xserver_greeter_radiobutton", GTK_TYPE_RADIO_BUTTON); chooser_radio = glade_helper_get (xml, "xserver_chooser_radiobutton", GTK_TYPE_RADIO_BUTTON); modify_combobox = glade_helper_get (xml, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); create_button = glade_helper_get (xml, "xserver_create_button", GTK_TYPE_BUTTON); delete_button = glade_helper_get (xml, "xserver_delete_button", GTK_TYPE_BUTTON); /* Get list of servers that are set to start */ store = gtk_list_store_new (XSERVER_NUM_COLUMNS, G_TYPE_INT /* virtual terminal */, G_TYPE_STRING /* server type */, G_TYPE_STRING /* options */); xservers_get_servers(store); /* Get list of servers and determine which one was selected */ xservers = xservers_get_server_definitions(); i = gtk_combo_box_get_active (GTK_COMBO_BOX (modify_combobox)); xserver = g_slist_nth_data(xservers, i); /* Set all the corresponding values in the frame */ gtk_entry_set_text (GTK_ENTRY (name_entry), xserver->name); gtk_entry_set_text (GTK_ENTRY (command_entry), xserver->command); /* Update sensitivity of delete button */ xserver_update_delete_sensitivity(); if (xserver->chooser) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser_radio), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (greeter_radio), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (handled_check), xserver->handled); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (flexible_check), xserver->flexible); gtk_widget_set_sensitive(frame, TRUE); } return FALSE; } static void toggle_toggled (GtkWidget *toggle) { run_timeout (toggle, 200, toggle_timeout); } static void remote_toggled (GtkWidget *toggle, gpointer data) { GtkWidget *widget = data; gboolean val; val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)); if (val == TRUE) { if (last_remote_login_setting != -1) gtk_combo_box_set_active (GTK_COMBO_BOX (widget), last_remote_login_setting); gtk_widget_set_sensitive (widget, TRUE); } else { gtk_widget_set_sensitive (widget, FALSE); gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2); } run_timeout (toggle, 200, toggle_timeout); } static void sensitive_entry_toggled (GtkWidget *toggle, gpointer data) { GtkWidget *widget = data; gboolean val; val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)); if (val == FALSE) { gtk_widget_set_sensitive (widget, TRUE); } else { gtk_widget_set_sensitive (widget, FALSE); } run_timeout (toggle, 200, toggle_timeout); } static void intspin_changed (GtkWidget *spin) { run_timeout (spin, 500, intspin_timeout); } static void combobox_changed (GtkWidget *combobox) { run_timeout (combobox, 500, combobox_timeout); } static void timeout_remove (GtkWidget *widget) { gboolean (*func) (GtkWidget *); guint id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), "change_timeout")); if (id != 0) { g_source_remove (id); g_object_set_data (G_OBJECT (widget), "change_timeout", NULL); } func = g_object_get_data (G_OBJECT (widget), "timeout_func"); if (func != NULL) { (*func) (widget); g_object_set_data (G_OBJECT (widget), "timeout_func", NULL); } } static void timeout_remove_all (void) { GList *li, *list; list = timeout_widgets; timeout_widgets = NULL; for (li = list; li != NULL; li = li->next) { timeout_remove (li->data); li->data = NULL; } g_list_free (list); } static void setup_notify_toggle (const char *name, const char *key, const char *notify_key) { GtkWidget *toggle = glade_helper_get (xml, name, GTK_TYPE_TOGGLE_BUTTON); gboolean val; val = ve_config_get_bool (ve_config_get (config_file), key); g_object_set_data_full (G_OBJECT (toggle), "key", g_strdup (key), (GDestroyNotify) g_free); g_object_set_data_full (G_OBJECT (toggle), "notify_key", g_strdup (notify_key), (GDestroyNotify) g_free); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), val); if (strcmp ("enable_xdmcp", name) == 0) { GtkWidget *remote_greeter = glade_helper_get (xml, "remote_greeter", GTK_TYPE_COMBO_BOX); if (val == FALSE) { gtk_widget_set_sensitive (remote_greeter, FALSE); } g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (remote_toggled), remote_greeter); } else { g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled), NULL); } } static void toggle_toggled_sensitivity_positive (GtkWidget *toggle, GtkWidget *depend) { gtk_widget_set_sensitive (depend, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle))); } static void setup_sensitivity_positive_toggle (const char *name, const char *depend_name) { GtkWidget *toggle = glade_helper_get (xml, name, GTK_TYPE_TOGGLE_BUTTON); GtkWidget *depend = glade_helper_get (xml, depend_name, GTK_TYPE_WIDGET); toggle_toggled_sensitivity_positive (toggle, depend); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), depend); } static const char * get_root_user (void) { static char *root_user = NULL; struct passwd *pwent; if (root_user != NULL) return root_user; pwent = getpwuid (0); if (pwent == NULL) /* huh? */ root_user = g_strdup ("root"); else root_user = g_strdup (pwent->pw_name); return root_user; } static void root_not_allowed (GtkWidget *combo_box) { static gboolean warned = FALSE; const char *text = NULL; GtkTreeIter iter; if (warned) return; if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box), &iter)) { gtk_tree_model_get (gtk_combo_box_get_model ( GTK_COMBO_BOX (combo_box)), &iter, 0, &text, -1); } if ( ! ve_string_empty (text) && strcmp (text, get_root_user ()) == 0) { GtkWidget *dlg = ve_hig_dialog_new (NULL /* parent */, GTK_DIALOG_MODAL /* flags */, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Autologin or timed login to the root account is not allowed."), ""); if (RUNNING_UNDER_GDM) setup_cursor (GDK_LEFT_PTR); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); warned = TRUE; } } /* Sets up Automatic Login Username and Timed Login User entry comboboxes * from the general configuration tab. */ static void setup_user_combobox_list (const char *name, const char *key) { GtkListStore *combobox_store = NULL; GtkWidget *combobox_entry = glade_helper_get (xml, name, GTK_TYPE_COMBO_BOX_ENTRY); GtkTreeIter iter; GList *users = NULL; GList *users_string = NULL; GList *li; static gboolean GDM_IS_LOCAL = FALSE; char *selected_user; gint size_of_users = 0; int selected = -1; int cnt; combobox_store = gtk_list_store_new (USERLIST_NUM_COLUMNS, G_TYPE_STRING); selected_user = ve_config_get_string (ve_config_get (config_file), key); /* normally empty */ users_string = g_list_append (users_string, g_strdup ("")); if ( ! ve_string_empty (selected_user)) users_string = g_list_append (users_string, g_strdup (selected_user)); if (ve_string_empty (g_getenv ("GDM_IS_LOCAL"))) GDM_IS_LOCAL = FALSE; else GDM_IS_LOCAL = TRUE; gdm_users_init (&users, &users_string, selected_user, NULL, &size_of_users, GDM_IS_LOCAL, FALSE); users_string = g_list_reverse (users_string); cnt=0; for (li = users_string; li != NULL; li = li->next) { gtk_list_store_append (combobox_store, &iter); if (strcmp (li->data, selected_user) == 0) selected=cnt; gtk_list_store_set(combobox_store, &iter, USERLIST_NAME, li->data, -1); cnt++; } gtk_combo_box_set_model (GTK_COMBO_BOX (combobox_entry), GTK_TREE_MODEL (combobox_store)); if (selected != -1) gtk_combo_box_set_active (GTK_COMBO_BOX (combobox_entry), selected); g_list_foreach (users, (GFunc)g_free, NULL); g_list_free (users); g_list_foreach (users_string, (GFunc)g_free, NULL); g_list_free (users_string); g_free (selected_user); } static void setup_user_combobox (const char *name, const char *key) { GtkWidget *combobox_entry = glade_helper_get (xml, name, GTK_TYPE_COMBO_BOX_ENTRY); setup_user_combobox_list (name, key); g_object_set_data_full (G_OBJECT (combobox_entry), "key", g_strdup (key), (GDestroyNotify) g_free); g_signal_connect (G_OBJECT (combobox_entry), "changed", G_CALLBACK (combobox_changed), NULL); g_signal_connect (G_OBJECT (combobox_entry), "changed", G_CALLBACK (root_not_allowed), NULL); } static void setup_intspin (const char *name, const char *key, const char *notify_key) { GtkWidget *spin = glade_helper_get (xml, name, GTK_TYPE_SPIN_BUTTON); int val; val = ve_config_get_int (ve_config_get (config_file), key); g_object_set_data_full (G_OBJECT (spin), "key", g_strdup (key), (GDestroyNotify) g_free); g_object_set_data_full (G_OBJECT (spin), "notify_key", g_strdup (notify_key), (GDestroyNotify) g_free); gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), val); g_signal_connect (G_OBJECT (spin), "value_changed", G_CALLBACK (intspin_changed), NULL); } static GtkListStore * setup_include_exclude (GtkWidget *treeview, const char *key) { GtkListStore *face_store = gtk_list_store_new (USERLIST_NUM_COLUMNS, G_TYPE_STRING); GtkTreeIter iter; GtkTreeViewColumn *column; GtkCellRenderer *renderer; char **list; int i; column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_set_attributes (column, renderer, "text", USERLIST_NAME, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), (GTK_TREE_MODEL (face_store))); if (strcmp (key, GDM_KEY_INCLUDE) == 0) list = g_strsplit (GdmInclude, ",", 0); else if (strcmp (key, GDM_KEY_EXCLUDE) == 0) list = g_strsplit (GdmExclude, ",", 0); else list = NULL; for (i=0; list != NULL && list[i] != NULL; i++) { gtk_list_store_append (face_store, &iter); gtk_list_store_set(face_store, &iter, USERLIST_NAME, list[i], -1); } g_strfreev (list); return (face_store); } typedef enum { INCLUDE, EXCLUDE } FaceType; typedef struct _FaceCommon { GtkWidget *label; GtkWidget *apply; GtkWidget *include_treeview; GtkWidget *exclude_treeview; GtkListStore *include_store; GtkListStore *exclude_store; GtkTreeModel *include_model; GtkTreeModel *exclude_model; GtkWidget *include_add; GtkWidget *exclude_add; GtkWidget *include_del; GtkWidget *exclude_del; GtkWidget *to_include_button; GtkWidget *to_exclude_button; GtkWidget *include_entry; GtkWidget *exclude_entry; GtkWidget *allusers; } FaceCommon; typedef struct _FaceData { FaceCommon *fc; FaceType type; } FaceData; typedef struct _FaceApply { FaceData *exclude; FaceData *include; } FaceApply; static void face_add (GtkWidget *button, gpointer data) { FaceData *fd = data; const char *text = NULL; const char *model_text; GtkTreeIter iter; gboolean valid; if (fd->type == INCLUDE) text = gtk_entry_get_text (GTK_ENTRY (fd->fc->include_entry)); else if (fd->type == EXCLUDE) text = gtk_entry_get_text (GTK_ENTRY (fd->fc->exclude_entry)); if (gdm_is_user_valid (text)) { valid = gtk_tree_model_get_iter_first (fd->fc->include_model, &iter); while (valid) { gtk_tree_model_get (fd->fc->include_model, &iter, USERLIST_NAME, &model_text, -1); if (strcmp (text, model_text) == 0) { gtk_label_set_text (GTK_LABEL (fd->fc->label), "User already in Include list"); return; } valid = gtk_tree_model_iter_next (fd->fc->include_model, &iter); } valid = gtk_tree_model_get_iter_first (fd->fc->exclude_model, &iter); while (valid) { gtk_tree_model_get (fd->fc->exclude_model, &iter, USERLIST_NAME, &model_text, -1); if (strcmp (text, model_text) == 0) { gtk_label_set_text (GTK_LABEL (fd->fc->label), "User already in Exclude list"); return; } valid = gtk_tree_model_iter_next (fd->fc->exclude_model, &iter); } if (fd->type == INCLUDE) { gtk_list_store_append (fd->fc->include_store, &iter); gtk_list_store_set (fd->fc->include_store, &iter, USERLIST_NAME, text, -1); gtk_entry_set_text (GTK_ENTRY (fd->fc->include_entry), ""); } else if (fd->type == EXCLUDE) { gtk_list_store_append (fd->fc->exclude_store, &iter); gtk_list_store_set (fd->fc->exclude_store, &iter, USERLIST_NAME, text, -1); gtk_entry_set_text (GTK_ENTRY (fd->fc->exclude_entry), ""); } gtk_widget_set_sensitive (fd->fc->apply, TRUE); gtk_label_set_text (GTK_LABEL (fd->fc->label), ""); } else { gtk_label_set_text (GTK_LABEL (fd->fc->label), "Not a valid user"); } } static void face_del (GtkWidget *button, gpointer data) { FaceData *fd = data; GtkTreeSelection *selection; GtkTreeIter iter; if (fd->type == INCLUDE) { selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (fd->fc->include_treeview)); if (gtk_tree_selection_get_selected (selection, &(fd->fc->include_model), &iter)) { gtk_list_store_remove (fd->fc->include_store, &iter); gtk_widget_set_sensitive (fd->fc->apply, TRUE); } } else if (fd->type == EXCLUDE) { selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (fd->fc->exclude_treeview)); if (gtk_tree_selection_get_selected (selection, &(fd->fc->exclude_model), &iter)) { gtk_list_store_remove (fd->fc->exclude_store, &iter); gtk_widget_set_sensitive (fd->fc->apply, TRUE); } } } static void browser_move (GtkWidget *button, gpointer data) { FaceData *fd = data; GtkTreeSelection *selection = NULL; GtkTreeIter iter; GtkTreeModel *model = NULL; char *text; /* The fd->type value passed in corresponds with the list moving to */ if (fd->type == INCLUDE) { model = fd->fc->exclude_model; selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (fd->fc->exclude_treeview)); } else if (fd->type == EXCLUDE) { model = fd->fc->include_model; selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (fd->fc->include_treeview)); } if (gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_tree_model_get (model, &iter, USERLIST_NAME, &text, -1); if (fd->type == INCLUDE) { gtk_list_store_remove (fd->fc->exclude_store, &iter); gtk_list_store_append (fd->fc->include_store, &iter); gtk_list_store_set (fd->fc->include_store, &iter, USERLIST_NAME, text, -1); } else if (fd->type == EXCLUDE) { gtk_list_store_remove (fd->fc->include_store, &iter); gtk_list_store_append (fd->fc->exclude_store, &iter); gtk_list_store_set (fd->fc->exclude_store, &iter, USERLIST_NAME, text, -1); } gtk_widget_set_sensitive (fd->fc->apply, TRUE); } } static void browser_apply (GtkWidget *button, gpointer data) { FaceCommon *fc = data; VeConfig *config = ve_config_get (config_file); GString *userlist = g_string_new (NULL); const char *model_text; char *val; GtkTreeIter iter; gboolean valid; gboolean update_greet = FALSE; char *sep = ""; valid = gtk_tree_model_get_iter_first (fc->include_model, &iter); while (valid) { gtk_tree_model_get (fc->include_model, &iter, USERLIST_NAME, &model_text, -1); g_string_append (userlist, sep); sep = ","; g_string_append (userlist, model_text); valid = gtk_tree_model_iter_next (fc->include_model, &iter); } val = ve_config_get_string (config, GDM_KEY_INCLUDE); if (strcmp (ve_sure_string (val), ve_sure_string (userlist->str)) != 0) { ve_config_set_string (config, GDM_KEY_INCLUDE, userlist->str); ve_config_save (config, FALSE /* force */); update_greet = TRUE; } g_string_free (userlist, TRUE); g_free (val); userlist = g_string_new (NULL); sep = ""; valid = gtk_tree_model_get_iter_first (fc->exclude_model, &iter); while (valid) { gtk_tree_model_get (fc->exclude_model, &iter, USERLIST_NAME, &model_text, -1); g_string_append (userlist, sep); sep = ","; g_string_append (userlist, model_text); valid = gtk_tree_model_iter_next (fc->exclude_model, &iter); } val = ve_config_get_string (config, GDM_KEY_EXCLUDE); if (strcmp (ve_sure_string (val), ve_sure_string (userlist->str)) != 0) { ve_config_set_string (config, GDM_KEY_EXCLUDE, userlist->str); ve_config_save (config, FALSE /* force */); update_greet = TRUE; } if (update_greet) update_greeters (); /* Re-initialize combox with updated userlist. */ GdmInclude = ve_config_get_string (ve_config_get (config_file), GDM_KEY_INCLUDE); GdmExclude = ve_config_get_string (ve_config_get (config_file), GDM_KEY_EXCLUDE); setup_user_combobox_list ("autologin_combo", GDM_KEY_AUTOMATICLOGIN); setup_user_combobox_list ("timedlogin_combo", GDM_KEY_TIMED_LOGIN); g_string_free (userlist, TRUE); g_free (val); } static void face_rowdel (GtkTreeModel *treemodel, GtkTreePath *arg1, gpointer data) { FaceCommon *fc = data; GtkTreeIter iter; GtkTreeSelection *selection; selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (fc->include_treeview)); if (gtk_tree_selection_get_selected (selection, &(fc->include_model), &iter)) { gtk_widget_set_sensitive (fc->to_exclude_button, TRUE); gtk_widget_set_sensitive (fc->include_del, TRUE); } else { gtk_widget_set_sensitive (fc->to_exclude_button, FALSE); gtk_widget_set_sensitive (fc->include_del, FALSE); } selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (fc->exclude_treeview)); if (gtk_tree_selection_get_selected (selection, &(fc->exclude_model), &iter)) { gtk_widget_set_sensitive (fc->to_include_button, TRUE); gtk_widget_set_sensitive (fc->exclude_del, TRUE); } else { gtk_widget_set_sensitive (fc->to_include_button, FALSE); gtk_widget_set_sensitive (fc->exclude_del, FALSE); } } static void face_entry_changed (GtkEditable *editable, gpointer data) { FaceData *fd = data; const char *text; if (fd->type == INCLUDE) { text = gtk_entry_get_text (GTK_ENTRY (fd->fc->include_entry)); if (strlen (text) < 1) gtk_widget_set_sensitive (fd->fc->include_add, FALSE); else gtk_widget_set_sensitive (fd->fc->include_add, TRUE); } else if (fd->type == EXCLUDE) { text = gtk_entry_get_text (GTK_ENTRY (fd->fc->exclude_entry)); if (strlen (text) < 1) gtk_widget_set_sensitive (fd->fc->exclude_add, FALSE); else gtk_widget_set_sensitive (fd->fc->exclude_add, TRUE); } } static void face_selection_changed (GtkTreeSelection *selection, gpointer data) { FaceData *fd = data; GtkTreeIter iter; if (fd->type == INCLUDE) { if (gtk_tree_selection_get_selected (selection, &(fd->fc->include_model), &iter)) { gtk_widget_set_sensitive (fd->fc->to_exclude_button, TRUE); gtk_widget_set_sensitive (fd->fc->include_del, TRUE); } else { gtk_widget_set_sensitive (fd->fc->to_exclude_button, FALSE); gtk_widget_set_sensitive (fd->fc->include_del, FALSE); } } else if (fd->type == EXCLUDE) { if (gtk_tree_selection_get_selected (selection, &(fd->fc->exclude_model), &iter)) { gtk_widget_set_sensitive (fd->fc->to_include_button, TRUE); gtk_widget_set_sensitive (fd->fc->exclude_del, TRUE); } else { gtk_widget_set_sensitive (fd->fc->to_include_button, FALSE); gtk_widget_set_sensitive (fd->fc->exclude_del, FALSE); } } } static void sensitivity_toggled (GtkWidget *toggle, gpointer data) { GtkWidget *widget = data; gtk_widget_set_sensitive (widget, GTK_TOGGLE_BUTTON (toggle)->active); } static void setup_face (void) { GtkWidget *fb_browser = glade_helper_get (xml, "fb_browser", GTK_TYPE_WIDGET); GtkWidget *face_frame = glade_helper_get (xml, "face_frame", GTK_TYPE_WIDGET); static FaceCommon fc; static FaceData fd_include; static FaceData fd_exclude; static FaceApply face_apply; GtkTreeSelection *selection; fc.include_add = glade_helper_get (xml, "fb_includeadd", GTK_TYPE_WIDGET); fc.include_del = glade_helper_get (xml, "fb_includedelete", GTK_TYPE_WIDGET); fc.exclude_add = glade_helper_get (xml, "fb_excludeadd", GTK_TYPE_WIDGET); fc.exclude_del = glade_helper_get (xml, "fb_excludedelete", GTK_TYPE_WIDGET); fc.to_include_button = glade_helper_get (xml, "fb_toinclude", GTK_TYPE_WIDGET); fc.to_exclude_button = glade_helper_get (xml, "fb_toexclude", GTK_TYPE_WIDGET); fc.apply = glade_helper_get (xml, "fb_faceapply", GTK_TYPE_WIDGET); fc.label = glade_helper_get (xml, "fb_message", GTK_TYPE_WIDGET); fc.include_entry = glade_helper_get (xml, "fb_includeentry", GTK_TYPE_WIDGET); fc.exclude_entry = glade_helper_get (xml, "fb_excludeentry", GTK_TYPE_WIDGET); fc.include_treeview = glade_helper_get (xml, "fb_include_treeview", GTK_TYPE_TREE_VIEW); fc.exclude_treeview = glade_helper_get (xml, "fb_exclude_treeview", GTK_TYPE_TREE_VIEW); fc.allusers = glade_helper_get (xml, "fb_allusers", GTK_TYPE_TOGGLE_BUTTON); fc.include_store = setup_include_exclude (fc.include_treeview, GDM_KEY_INCLUDE); fc.exclude_store = setup_include_exclude (fc.exclude_treeview, GDM_KEY_EXCLUDE); fc.include_model = gtk_tree_view_get_model ( GTK_TREE_VIEW (fc.include_treeview)); fc.exclude_model = gtk_tree_view_get_model ( GTK_TREE_VIEW (fc.exclude_treeview)); fd_include.fc = &fc; fd_include.type = INCLUDE; fd_exclude.fc = &fc; fd_exclude.type = EXCLUDE; gtk_widget_set_sensitive (fc.include_add, FALSE); gtk_widget_set_sensitive (fc.exclude_add, FALSE); gtk_widget_set_sensitive (fc.include_del, FALSE); gtk_widget_set_sensitive (fc.exclude_del, FALSE); gtk_widget_set_sensitive (fc.to_include_button, FALSE); gtk_widget_set_sensitive (fc.to_exclude_button, FALSE); gtk_widget_set_sensitive (fc.apply, FALSE); face_apply.include = &fd_include; face_apply.exclude = &fd_exclude; g_signal_connect (fc.include_add, "clicked", G_CALLBACK (face_add), &fd_include); g_signal_connect (fc.exclude_add, "clicked", G_CALLBACK (face_add), &fd_exclude); g_signal_connect (fc.include_del, "clicked", G_CALLBACK (face_del), &fd_include); g_signal_connect (fc.exclude_del, "clicked", G_CALLBACK (face_del), &fd_exclude); g_signal_connect (fc.include_entry, "changed", G_CALLBACK (face_entry_changed), &fd_include); g_signal_connect (fc.exclude_entry, "changed", G_CALLBACK (face_entry_changed), &fd_exclude); g_signal_connect (fc.include_model, "row-deleted", G_CALLBACK (face_rowdel), &fc); g_signal_connect (fc.exclude_model, "row-deleted", G_CALLBACK (face_rowdel), &fc); selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (fc.include_treeview)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); g_signal_connect (selection, "changed", G_CALLBACK (face_selection_changed), &fd_include); selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (fc.exclude_treeview)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); g_signal_connect (selection, "changed", G_CALLBACK (face_selection_changed), &fd_exclude); g_signal_connect (fc.to_include_button, "clicked", G_CALLBACK (browser_move), &fd_include); g_signal_connect (fc.to_exclude_button, "clicked", G_CALLBACK (browser_move), &fd_exclude); g_signal_connect (fc.apply, "clicked", G_CALLBACK (browser_apply), &fc); } static gboolean greeter_toggle_timeout (GtkWidget *toggle) { const char *key = g_object_get_data (G_OBJECT (toggle), "key"); VeConfig *config = ve_config_get (config_file); gboolean val = ve_config_get_bool (config, key); if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) { ve_config_set_bool (config, key, GTK_TOGGLE_BUTTON (toggle)->active); ve_config_save (config, FALSE /* force */); update_greeters (); } return FALSE; } static void greeter_toggle_toggled (GtkWidget *toggle) { run_timeout (toggle, 500, greeter_toggle_timeout); } include_all_toggle (GtkWidget *toggle) { if (GTK_TOGGLE_BUTTON (toggle)->active) GdmIncludeAll = TRUE; else GdmIncludeAll = FALSE; setup_user_combobox_list ("autologin_combo", GDM_KEY_AUTOMATICLOGIN); setup_user_combobox_list ("timedlogin_combo", GDM_KEY_TIMED_LOGIN); } static void setup_greeter_toggle (const char *name, const char *key) { GtkWidget *toggle = glade_helper_get (xml, name, GTK_TYPE_TOGGLE_BUTTON); gboolean val = ve_config_get_bool (ve_config_get (config_file), key); g_object_set_data_full (G_OBJECT (toggle), "key", g_strdup (key), (GDestroyNotify) g_free); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), val); if (strcmp ("sg_defaultwelcome", name) == 0) { GtkWidget *welcome = glade_helper_get (xml, "welcome", GTK_TYPE_ENTRY); if (val == TRUE) gtk_widget_set_sensitive (welcome, FALSE); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), welcome); } else if (strcmp ("sg_defaultremotewelcome", name) == 0) { GtkWidget *remotewelcome = glade_helper_get (xml, "remote_welcome", GTK_TYPE_ENTRY); if (val == TRUE) gtk_widget_set_sensitive (remotewelcome, FALSE); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), remotewelcome); } else if (strcmp ("fb_allusers", name) == 0) { GtkWidget *fb_includebox = glade_helper_get (xml, "fb_includebox", GTK_TYPE_VBOX); GtkWidget *fb_buttonbox = glade_helper_get (xml, "fb_buttonbox", GTK_TYPE_VBOX); if (val == TRUE) { gtk_widget_set_sensitive (fb_includebox, FALSE); gtk_widget_set_sensitive (fb_buttonbox, FALSE); } g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), fb_includebox); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), fb_buttonbox); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (include_all_toggle), NULL); } g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (greeter_toggle_toggled), NULL); } static gboolean greeter_color_timeout (GtkWidget *picker) { const char *key = g_object_get_data (G_OBJECT (picker), "key"); char *val, *color; guint8 r, g, b; VeConfig *config = ve_config_get (config_file); gnome_color_picker_get_i8 (GNOME_COLOR_PICKER (picker), &r, &g, &b, NULL); color = g_strdup_printf ("#%02x%02x%02x", (int)r, (int)g, (int)b); val = ve_config_get_string (config, key); if (strcmp (ve_sure_string (val), ve_sure_string (color)) != 0) { ve_config_set_string (config, key, ve_sure_string (color)); ve_config_save (config, FALSE /* force */); update_greeters (); } g_free (val); g_free (color); return FALSE; } static void greeter_color_changed (GtkWidget *picker, guint r, guint g, guint b, guint a) { run_timeout (picker, 500, greeter_color_timeout); } static void setup_greeter_color (const char *name, const char *key) { GtkWidget *picker = glade_helper_get (xml, name, GNOME_TYPE_COLOR_PICKER); char *val; val = ve_config_get_string (ve_config_get (config_file), key); g_object_set_data_full (G_OBJECT (picker), "key", g_strdup (key), (GDestroyNotify) g_free); if (val != NULL) { GdkColor color; if (gdk_color_parse (val, &color)) gnome_color_picker_set_i16 (GNOME_COLOR_PICKER (picker), color.red, color.green, color.blue, 0); } g_signal_connect (G_OBJECT (picker), "color_set", G_CALLBACK (greeter_color_changed), NULL); g_free (val); } typedef enum { BACKIMAGE, LOGO } ImageType; typedef struct _ImageData { GtkWidget *image; gchar *filename; gchar *key; } ImageData; static void update_preview_cb (GtkFileChooser *file_chooser, gpointer data) { ImageData *image_data = data; char *filename = gtk_file_chooser_get_preview_filename (file_chooser); GdkPixbuf *pixbuf = NULL; if (filename != NULL) pixbuf = gdk_pixbuf_new_from_file (filename, NULL); if (pixbuf) gtk_image_set_from_file (GTK_IMAGE (image_data->image), filename); } static void image_install_response (GtkWidget *file_dialog, gint response, gpointer data) { ImageData *image_data = data; if (response == GTK_RESPONSE_ACCEPT) { char *val; VeConfig *config = ve_config_get (config_file); image_data->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_dialog)); val = ve_config_get_string (config, image_data->key); if (strcmp (ve_sure_string (val), ve_sure_string (image_data->filename)) != 0) { ve_config_set_string (config, image_data->key, ve_sure_string (image_data->filename)); ve_config_save (config, FALSE /* force */); update_greeters (); } g_free (val); } else { gtk_image_set_from_file (GTK_IMAGE (image_data->image), image_data->filename); } gtk_widget_destroy (file_dialog); } static void browse_button_cb (GtkWidget *widget, gpointer data) { ImageData *image_data = data; GtkFileFilter *filter; GtkWidget *setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); GtkWidget *file_dialog = gtk_file_chooser_dialog_new (_("Open File"), GTK_WINDOW (setup_dialog), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if (image_data->filename != NULL && *(image_data->filename) != '\0') gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (file_dialog), image_data->filename); else gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_dialog), EXPANDED_DATADIR "/pixmaps"); gtk_file_chooser_set_show_hidden (file_dialog, TRUE); filter = gtk_file_filter_new (); gtk_file_filter_set_name (filter, _("PNG and JPEG")); gtk_file_filter_add_mime_type (filter, "image/jpeg"); gtk_file_filter_add_mime_type (filter, "image/png"); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_dialog), filter); g_signal_connect (file_dialog, "update-preview", G_CALLBACK (update_preview_cb), image_data); g_signal_connect (G_OBJECT (file_dialog), "destroy", G_CALLBACK (gtk_widget_destroyed), &file_dialog); g_signal_connect (G_OBJECT (file_dialog), "response", G_CALLBACK (image_install_response), image_data); gtk_widget_show (file_dialog); } static void noimage_button_cb (GtkWidget *widget, gpointer data) { ImageData *image_data = data; char *val; VeConfig *config = ve_config_get (config_file); gtk_image_set_from_file (GTK_IMAGE (image_data->image), NULL); image_data->filename = NULL; val = ve_config_get_string (config, image_data->key); if (strcmp (ve_sure_string (val), ve_sure_string (image_data->filename)) != 0) { ve_config_set_string (config, image_data->key, ve_sure_string (image_data->filename)); ve_config_save (config, FALSE /* force */); update_greeters (); } g_free (val); } static void setup_greeter_image (GtkWidget *dialog) { static ImageData logo_data; static ImageData backimage_data; GdkPixbuf *pixbuf; GtkWidget *logo_button = glade_helper_get (xml, "sg_browselogo", GTK_TYPE_WIDGET); GtkWidget *backimage_button = glade_helper_get (xml, "sg_browsebackimage", GTK_TYPE_WIDGET); GtkWidget *nologo_button = glade_helper_get (xml, "sg_nologo", GTK_TYPE_WIDGET); logo_data.image = glade_helper_get (xml, "sg_logo", GTK_TYPE_WIDGET); logo_data.key = GDM_KEY_LOGO; logo_data.filename = ve_config_get_string (ve_config_get (config_file), GDM_KEY_LOGO); backimage_data.image = glade_helper_get (xml, "sg_backimage", GTK_TYPE_WIDGET); backimage_data.filename = ve_config_get_string ( ve_config_get (config_file), GDM_KEY_BACKGROUNDIMAGE); backimage_data.key = GDM_KEY_BACKGROUNDIMAGE; if (logo_data.filename != NULL) { pixbuf = gdk_pixbuf_new_from_file (logo_data.filename, NULL); if (pixbuf != NULL) gtk_image_set_from_file (GTK_IMAGE(logo_data.image), logo_data.filename); else logo_data.filename = NULL; } if (backimage_data.filename != NULL) { pixbuf = gdk_pixbuf_new_from_file (backimage_data.filename, NULL); if (pixbuf != NULL) gtk_image_set_from_file (GTK_IMAGE(backimage_data.image), backimage_data.filename); else backimage_data.filename = NULL; } g_signal_connect (G_OBJECT (logo_button), "clicked", G_CALLBACK (browse_button_cb), &logo_data); g_signal_connect (G_OBJECT (nologo_button), "clicked", G_CALLBACK (noimage_button_cb), &logo_data); g_signal_connect (G_OBJECT (backimage_button), "clicked", G_CALLBACK (browse_button_cb), &backimage_data); } static gboolean greeter_entry_untranslate_timeout (GtkWidget *entry) { const char *key = g_object_get_data (G_OBJECT (entry), "key"); const char *text; VeConfig *config = ve_config_get (config_file); text = gtk_entry_get_text (GTK_ENTRY (entry)); ve_config_delete_translations (config, key); ve_config_set_string (config, key, ve_sure_string (text)); ve_config_save (config, FALSE /* force */); update_greeters (); return FALSE; } static void greeter_entry_untranslate_changed (GtkWidget *entry) { run_timeout (entry, 500, greeter_entry_untranslate_timeout); } static void setup_greeter_untranslate_entry (const char *name, const char *key) { GtkWidget *entry = glade_helper_get (xml, name, GTK_TYPE_ENTRY); char *val; val = ve_config_get_translated_string (ve_config_get (config_file), key); g_object_set_data_full (G_OBJECT (entry), "key", g_strdup (key), (GDestroyNotify) g_free); gtk_entry_set_text (GTK_ENTRY (entry), ve_sure_string (val)); g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (greeter_entry_untranslate_changed), NULL); g_free (val); } static gboolean greeter_backselect_timeout (GtkWidget *toggle) { int val, new_val; GtkWidget *no_bg = glade_helper_get (xml, "sg_no_bg_rb", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *image_bg = glade_helper_get (xml, "sg_image_bg_rb", GTK_TYPE_TOGGLE_BUTTON); VeConfig *config = ve_config_get (config_file); val = ve_config_get_int (config, GDM_KEY_BACKGROUNDTYPE); if (GTK_TOGGLE_BUTTON (no_bg)->active) new_val = 0 /* No background */; else if (GTK_TOGGLE_BUTTON (image_bg)->active) new_val = 1 /* Image */; else new_val = 2 /* Color */; if (val != new_val) { ve_config_set_int (config, GDM_KEY_BACKGROUNDTYPE, new_val); ve_config_save (config, FALSE /* force */); update_greeters (); } return FALSE; } static void greeter_backselect_toggled (GtkWidget *toggle) { /* We set the timeout on the no_bg radiobutton */ GtkWidget *no_bg = glade_helper_get (xml, "sg_no_bg_rb", GTK_TYPE_WIDGET); run_timeout (no_bg, 500, greeter_backselect_timeout); } static void setup_greeter_backselect (void) { int val; GtkWidget *no_bg = glade_helper_get (xml, "sg_no_bg_rb", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *image_bg = glade_helper_get (xml, "sg_image_bg_rb", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *color_bg = glade_helper_get (xml, "sg_color_bg_rb", GTK_TYPE_TOGGLE_BUTTON); val = ve_config_get_int (ve_config_get (config_file), GDM_KEY_BACKGROUNDTYPE); if (val == 0) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (no_bg), TRUE); else if (val == 1) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_bg), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_bg), TRUE); g_signal_connect (G_OBJECT (no_bg), "toggled", G_CALLBACK (greeter_backselect_toggled), NULL); g_signal_connect (G_OBJECT (image_bg), "toggled", G_CALLBACK (greeter_backselect_toggled), NULL); g_signal_connect (G_OBJECT (color_bg), "toggled", G_CALLBACK (greeter_backselect_toggled), NULL); } /* Local and Remote greeter comboboxes from General configuration tab */ static void setup_greeter_combobox (const char *name, const char *key) { GtkWidget *combobox = glade_helper_get (xml, name, GTK_TYPE_COMBO_BOX); GtkWidget *toggle = glade_helper_get (xml, "enable_xdmcp", GTK_TYPE_TOGGLE_BUTTON); char *val; val = ve_config_get_string (ve_config_get (config_file), key); if (val != NULL && strcmp (val, EXPANDED_LIBEXECDIR "/gdmlogin --disable-sound --disable-crash-dialog") == 0) { g_free (val); val = g_strdup (EXPANDED_LIBEXECDIR "/gdmlogin"); } if (strcmp (key, GDM_KEY_REMOTEGREETER) == 0 && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)) == FALSE) gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 2); else if (strcmp (val, EXPANDED_LIBEXECDIR "/gdmlogin") == 0) { gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 0); last_remote_login_setting = 0; } else if (strcmp (val, EXPANDED_LIBEXECDIR "/gdmgreeter") == 0) { gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 1); last_remote_login_setting = 1; } g_free (val); g_object_set_data_full (G_OBJECT (combobox), "key", g_strdup (key), (GDestroyNotify) g_free); g_signal_connect (G_OBJECT (combobox), "changed", G_CALLBACK (combobox_changed), NULL); } static void setup_xdmcp_support (void) { GtkWidget *xdmcp_toggle = glade_helper_get (xml, "enable_xdmcp", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *xdmcp_label = glade_helper_get (xml, "XDMCP_label", GTK_TYPE_WIDGET); GtkWidget *xdmcp_frame = glade_helper_get (xml, "xdmcp_frame", GTK_TYPE_WIDGET); GtkWidget *xdmcp_vbox = glade_helper_get (xml, "xdmcp_vbox", GTK_TYPE_WIDGET); GtkWidget *no_xdmcp_label = glade_helper_get (xml, "no_xdmcp_label", GTK_TYPE_WIDGET); #ifndef HAVE_LIBXDMCP gtk_widget_show (no_xdmcp_label); gtk_widget_hide (xdmcp_vbox); #else /* HAVE_LIBXDMCP */ gtk_widget_hide (no_xdmcp_label); gtk_widget_show (xdmcp_vbox); #endif /* HAVE_LIBXDMCP */ gtk_widget_set_sensitive (xdmcp_label, GTK_TOGGLE_BUTTON (xdmcp_toggle)->active); gtk_widget_set_sensitive (xdmcp_frame, GTK_TOGGLE_BUTTON (xdmcp_toggle)->active); g_signal_connect (G_OBJECT (xdmcp_toggle), "toggled", G_CALLBACK (sensitivity_toggled), xdmcp_frame); g_signal_connect (G_OBJECT (xdmcp_toggle), "toggled", G_CALLBACK (sensitivity_toggled), xdmcp_label); } static gboolean module_compare (const char *mod1, const char *mod2) { char *base1; char *base2; char *p; gboolean ret; /* first cannonify the names */ base1 = g_path_get_basename (mod1); base2 = g_path_get_basename (mod2); if (strncmp (base1, "lib", 3) == 0) strcpy (base1, &base1[3]); if (strncmp (base2, "lib", 3) == 0) strcpy (base2, &base2[3]); p = strstr (base1, ".so"); if (p != NULL) *p = '\0'; p = strstr (base2, ".so"); if (p != NULL) *p = '\0'; ret = (strcmp (base1, base2) == 0); g_free (base1); g_free (base2); return ret; } static gboolean modules_list_contains (const char *modules_list, const char *module) { char **vec; int i; if (ve_string_empty (modules_list)) return FALSE; vec = g_strsplit (modules_list, ":", -1); if (vec == NULL) return FALSE; for (i = 0; vec[i] != NULL; i++) { if (module_compare (vec[i], module)) { g_strfreev (vec); return TRUE; } } g_strfreev (vec); return FALSE; } static gboolean themes_list_contains (const char *themes_list, const char *theme) { char **vec; int i; if (ve_string_empty (themes_list)) return FALSE; vec = g_strsplit (themes_list, GDM_DELIMITER_THEMES, -1); if (vec == NULL) return FALSE; for (i = 0; vec[i] != NULL; i++) { if (strcmp (vec[i], theme) == 0) { g_strfreev (vec); return TRUE; } } g_strfreev (vec); return FALSE; } static char * modules_list_remove (char *modules_list, const char *module) { char **vec; GString *str; char *sep = ""; int i; if (ve_string_empty (modules_list)) return g_strdup (""); vec = g_strsplit (modules_list, ":", -1); if (vec == NULL) return g_strdup (""); str = g_string_new (NULL); for (i = 0; vec[i] != NULL; i++) { if ( ! module_compare (vec[i], module)) { g_string_append (str, sep); sep = ":"; g_string_append (str, vec[i]); } } g_strfreev (vec); return g_string_free (str, FALSE); } /* This function concatenates *string onto *strings_list with the addition of *sep as a deliminator inbetween the strings_list and string, then returns a copy of the new strings_list. */ static char * strings_list_add (char *strings_list, const char *string, const char *sep) { char *n; if (ve_string_empty (strings_list)) n = g_strdup (string); else n = g_strconcat (strings_list, sep, string, NULL); g_free (strings_list); return n; } static void acc_modules_toggled (GtkWidget *toggle, gpointer data) { VeConfig *cfg = ve_config_get (config_file); gboolean add_gtk_modules = ve_config_get_bool (cfg, GDM_KEY_ADD_GTK_MODULES); char *modules_list = ve_config_get_string (cfg, GDM_KEY_GTK_MODULES_LIST); /* first whack the modules from the list */ modules_list = modules_list_remove (modules_list, "gail"); modules_list = modules_list_remove (modules_list, "atk-bridge"); modules_list = modules_list_remove (modules_list, "dwellmouselistener"); modules_list = modules_list_remove (modules_list, "keymouselistener"); if (GTK_TOGGLE_BUTTON (toggle)->active) { if ( ! add_gtk_modules) { g_free (modules_list); modules_list = NULL; } modules_list = strings_list_add (modules_list, "gail", GDM_DELIMITER_MODULES); modules_list = strings_list_add (modules_list, "atk-bridge", GDM_DELIMITER_MODULES); modules_list = strings_list_add (modules_list, EXPANDED_LIBDIR "/gtk-2.0/modules/libkeymouselistener", GDM_DELIMITER_MODULES); modules_list = strings_list_add (modules_list, EXPANDED_LIBDIR "/gtk-2.0/modules/libdwellmouselistener", GDM_DELIMITER_MODULES); add_gtk_modules = TRUE; } if (ve_string_empty (modules_list)) add_gtk_modules = FALSE; ve_config_set_string (cfg, GDM_KEY_GTK_MODULES_LIST, ve_sure_string (modules_list)); ve_config_set_bool (cfg, GDM_KEY_ADD_GTK_MODULES, add_gtk_modules); ve_config_save (cfg, FALSE /* force */); g_free (modules_list); update_key (GDM_KEY_GTK_MODULES_LIST); update_key (GDM_KEY_ADD_GTK_MODULES); } static void test_sound (GtkWidget *button, gpointer data) { GtkWidget *acc_sound_file_label = data; const char *file = gtk_label_get_text (GTK_LABEL (acc_sound_file_label)); const char *argv[3]; if (strcmp (_("None"), file) == 0 || access (file, R_OK) != 0 || ve_string_empty (GdmSoundProgram)) return; argv[0] = GdmSoundProgram; argv[1] = file; argv[2] = NULL; g_spawn_async ("/" /* working directory */, (char **)argv, NULL /* envp */, 0 /* flags */, NULL /* child setup */, NULL /* user data */, NULL /* child pid */, NULL /* error */); } static void no_sound_cb (GtkWidget *widget, gpointer data) { VeConfig *config; GtkWidget *acc_no_sound_file, *acc_sound_test; GtkWidget *acc_sound_file_label = data; const char *key = g_object_get_data (G_OBJECT (acc_sound_file_label), "key"); const char *nosound_button; const char *soundtest_button; char *sound_key, *val, *config_val; nosound_button = g_strconcat ("acc_nosound_", key, "_button", NULL); soundtest_button = g_strconcat ("acc_soundtest_", key, "_button", NULL); acc_no_sound_file = glade_helper_get (xml, nosound_button, GTK_TYPE_BUTTON); acc_sound_test = glade_helper_get (xml, soundtest_button, GTK_TYPE_BUTTON); config = ve_config_get (config_file); gtk_label_set_text (GTK_LABEL (acc_sound_file_label), _("None")); gtk_widget_set_sensitive (acc_no_sound_file, FALSE); gtk_widget_set_sensitive (acc_sound_test, FALSE); if (strcmp (key, "ready") == 0) { sound_key = g_strdup(GDM_KEY_SOUND_ON_LOGIN_READY_FILE); } else if (strcmp (key, "success") == 0) { sound_key = g_strdup(GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE); } else if (strcmp (key, "failure") == 0) { sound_key = g_strdup(GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE); } else { sound_key = NULL; } val = ve_config_get_string (config, sound_key); config_val = ve_sure_string (val); if (config_val != NULL && *config_val != '\0') { ve_config_set_string (config, sound_key, "\0"); ve_config_save (config, FALSE /* force */); update_greeters (); } g_free (sound_key); g_free (val); } static void sound_response (GtkWidget *file_dialog, gint response, gpointer data) { GtkWidget *acc_no_sound_file, *acc_sound_test; GtkWidget *acc_sound_file_label = data; const char *key = g_object_get_data (G_OBJECT (acc_sound_file_label), "key"); const char *nosound_button; const char *soundtest_button; nosound_button = g_strconcat("acc_nosound_",key,"_button",NULL); soundtest_button = g_strconcat("acc_soundtest_",key,"_button",NULL); acc_no_sound_file = glade_helper_get (xml, nosound_button, GTK_TYPE_BUTTON); acc_sound_test = glade_helper_get (xml, soundtest_button, GTK_TYPE_BUTTON); if (response == GTK_RESPONSE_ACCEPT) { VeConfig *config = ve_config_get (config_file); char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_dialog)); char *val, *sound_key; gtk_label_set_text (GTK_LABEL (acc_sound_file_label), filename); gtk_widget_set_sensitive (acc_no_sound_file, TRUE); gtk_widget_set_sensitive (acc_sound_test, TRUE); if (strcmp (key, "ready") == 0 ) { have_sound_ready_file = TRUE; sound_key = g_strdup(GDM_KEY_SOUND_ON_LOGIN_READY_FILE); } else if (strcmp (key, "success") == 0 ) { have_sound_success_file = TRUE; sound_key = g_strdup(GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE); } else if (strcmp (key, "failure") == 0 ) { have_sound_failure_file = TRUE; sound_key = g_strdup(GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE); } else { sound_key = NULL; } val = ve_config_get_string (config, sound_key); if (strcmp (ve_sure_string (val), ve_sure_string (filename)) != 0) { ve_config_set_string (config, sound_key, ve_sure_string (filename)); ve_config_save (config, FALSE /* force */); update_greeters (); } g_free (val); } else { if (strcmp (key,"ready") == 0) { if (have_sound_ready_file) { gtk_widget_set_sensitive (acc_no_sound_file, TRUE); gtk_widget_set_sensitive (acc_sound_test, TRUE); } else { gtk_widget_set_sensitive (acc_no_sound_file, FALSE); gtk_widget_set_sensitive (acc_sound_test, FALSE); } } else if (strcmp (key,"success") == 0) { if (have_sound_success_file) { gtk_widget_set_sensitive (acc_no_sound_file, TRUE); gtk_widget_set_sensitive (acc_sound_test, TRUE); } else { gtk_widget_set_sensitive (acc_no_sound_file, FALSE); gtk_widget_set_sensitive (acc_sound_test, FALSE); } } else if (strcmp (key,"failure") == 0) { if (have_sound_failure_file) { gtk_widget_set_sensitive (acc_no_sound_file, TRUE); gtk_widget_set_sensitive (acc_sound_test, TRUE); } else { gtk_widget_set_sensitive (acc_no_sound_file, FALSE); gtk_widget_set_sensitive (acc_sound_test, FALSE); } } } gtk_widget_destroy (file_dialog); } static void browse_sound_cb (GtkWidget *widget, gpointer data) { GtkWidget *setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); GtkWidget *label = data; GtkFileFilter *filter; GtkWidget *file_dialog = gtk_file_chooser_dialog_new (_("Open File"), GTK_WINDOW (setup_dialog), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_show_hidden (file_dialog, TRUE); filter = gtk_file_filter_new (); gtk_file_filter_set_name (filter, _("All files")); gtk_file_filter_add_pattern(filter, "*"); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_dialog), filter); gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_dialog), EXPANDED_DATADIR "/sounds"); g_signal_connect (G_OBJECT (file_dialog), "destroy", G_CALLBACK (gtk_widget_destroyed), &file_dialog); g_signal_connect (G_OBJECT (file_dialog), "response", G_CALLBACK (sound_response), label); gtk_widget_show (file_dialog); } static void setup_accessibility_support (void) { GtkWidget *acc_modules = glade_helper_get (xml, "acc_modules", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *acc_sound_ready_file_label = glade_helper_get (xml, "acc_sound_ready_file", GTK_TYPE_LABEL); GtkWidget *acc_sound_ready_file = glade_helper_get (xml, "acc_sound_ready_button", GTK_TYPE_BUTTON); GtkWidget *acc_no_sound_ready_file = glade_helper_get (xml, "acc_nosound_ready_button", GTK_TYPE_BUTTON); GtkWidget *acc_sound_test_ready = glade_helper_get (xml, "acc_soundtest_ready_button", GTK_TYPE_BUTTON); GtkWidget *acc_sound_success_file_label = glade_helper_get (xml, "acc_sound_success_file", GTK_TYPE_LABEL); GtkWidget *acc_sound_success_file = glade_helper_get (xml, "acc_sound_success_button", GTK_TYPE_BUTTON); GtkWidget *acc_no_sound_success_file = glade_helper_get (xml, "acc_nosound_success_button", GTK_TYPE_BUTTON); GtkWidget *acc_sound_test_success = glade_helper_get (xml, "acc_soundtest_success_button", GTK_TYPE_BUTTON); GtkWidget *acc_sound_failure_file_label = glade_helper_get (xml, "acc_sound_failure_file", GTK_TYPE_LABEL); GtkWidget *acc_sound_failure_file = glade_helper_get (xml, "acc_sound_failure_button", GTK_TYPE_BUTTON); GtkWidget *acc_no_sound_failure_file = glade_helper_get (xml, "acc_nosound_failure_button", GTK_TYPE_BUTTON); GtkWidget *acc_sound_test_failure = glade_helper_get (xml, "acc_soundtest_failure_button", GTK_TYPE_BUTTON); gchar *ready_key = g_strdup("ready"); gchar *success_key = g_strdup("success"); gchar *failure_key = g_strdup("failure"); VeConfig *config = ve_config_get (config_file); gboolean add_gtk_modules = ve_config_get_bool (config, GDM_KEY_ADD_GTK_MODULES); char *modules_list = ve_config_get_string (config, GDM_KEY_GTK_MODULES_LIST); char *val; g_object_set_data (G_OBJECT (acc_sound_ready_file_label), "key", ready_key); g_object_set_data (G_OBJECT (acc_sound_success_file_label), "key", success_key); g_object_set_data (G_OBJECT (acc_sound_failure_file_label), "key", failure_key); if (add_gtk_modules && modules_list_contains (modules_list, "gail") && modules_list_contains (modules_list, "atk-bridge") && modules_list_contains (modules_list, "dwellmouselistener") && modules_list_contains (modules_list, "keymouselistener")) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (acc_modules), TRUE); } else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (acc_modules), FALSE); } val = ve_config_get_string (config, GDM_KEY_SOUND_ON_LOGIN_READY_FILE); if (val != NULL && *val != '\0') { gtk_label_set_text (GTK_LABEL (acc_sound_ready_file_label), val); } else { gtk_label_set_text (GTK_LABEL (acc_sound_ready_file_label), _("None")); gtk_widget_set_sensitive (acc_no_sound_ready_file, FALSE); gtk_widget_set_sensitive (acc_sound_test_ready, FALSE); } val = ve_config_get_string (config, GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE); if (val != NULL && *val != '\0') { gtk_label_set_text (GTK_LABEL (acc_sound_success_file_label), val); } else { gtk_label_set_text (GTK_LABEL (acc_sound_success_file_label), _("None")); gtk_widget_set_sensitive (acc_no_sound_success_file, FALSE); gtk_widget_set_sensitive (acc_sound_test_success, FALSE); } val = ve_config_get_string (config, GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE); if (val != NULL && *val != '\0') { gtk_label_set_text (GTK_LABEL (acc_sound_failure_file_label), val); } else { gtk_label_set_text (GTK_LABEL (acc_sound_failure_file_label), _("None")); gtk_widget_set_sensitive (acc_no_sound_failure_file, FALSE); gtk_widget_set_sensitive (acc_sound_test_failure, FALSE); } g_signal_connect (G_OBJECT (acc_modules), "toggled", G_CALLBACK (acc_modules_toggled), NULL); g_signal_connect (G_OBJECT (acc_sound_ready_file), "clicked", G_CALLBACK (browse_sound_cb), acc_sound_ready_file_label); g_signal_connect (G_OBJECT (acc_no_sound_ready_file), "clicked", G_CALLBACK (no_sound_cb), acc_sound_ready_file_label); g_signal_connect (G_OBJECT (acc_sound_test_ready), "clicked", G_CALLBACK (test_sound), acc_sound_ready_file_label); g_signal_connect (G_OBJECT (acc_sound_success_file), "clicked", G_CALLBACK (browse_sound_cb), acc_sound_success_file_label); g_signal_connect (G_OBJECT (acc_no_sound_success_file), "clicked", G_CALLBACK (no_sound_cb), acc_sound_success_file_label); g_signal_connect (G_OBJECT (acc_sound_test_success), "clicked", G_CALLBACK (test_sound), acc_sound_success_file_label); g_signal_connect (G_OBJECT (acc_sound_failure_file), "clicked", G_CALLBACK (browse_sound_cb), acc_sound_failure_file_label); g_signal_connect (G_OBJECT (acc_no_sound_failure_file), "clicked", G_CALLBACK (no_sound_cb), acc_sound_failure_file_label); g_signal_connect (G_OBJECT (acc_sound_test_failure), "clicked", G_CALLBACK (test_sound), acc_sound_failure_file_label); } static void background_toggled (void) { GtkWidget *no_bg = glade_helper_get (xml, "sg_no_bg_rb", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *image_bg = glade_helper_get (xml, "sg_image_bg_rb", GTK_TYPE_TOGGLE_BUTTON); /*GtkWidget *color_bg = glade_helper_get (xml, "sg_color_bg_rb", GTK_TYPE_TOGGLE_BUTTON);*/ GtkWidget *scale = glade_helper_get (xml, "sg_scale_background", GTK_TYPE_WIDGET); GtkWidget *image = glade_helper_get (xml, "sg_backimage", GTK_TYPE_WIDGET); GtkWidget *onlycolor = glade_helper_get (xml, "sg_remote_color_only", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *color_label = glade_helper_get (xml, "sg_backcolor_label", GTK_TYPE_WIDGET); GtkWidget *color = glade_helper_get (xml, "sg_backcolor", GTK_TYPE_WIDGET); GtkWidget *browse_button = glade_helper_get (xml, "sg_browsebackimage", GTK_TYPE_WIDGET); if (GTK_TOGGLE_BUTTON (no_bg)->active) { gtk_widget_set_sensitive (scale, FALSE); gtk_widget_set_sensitive (image, FALSE); gtk_widget_set_sensitive (onlycolor, FALSE); gtk_widget_set_sensitive (color_label, FALSE); gtk_widget_set_sensitive (color, FALSE); gtk_widget_set_sensitive (browse_button, FALSE); } else if (GTK_TOGGLE_BUTTON (image_bg)->active) { gtk_widget_set_sensitive (scale, TRUE); gtk_widget_set_sensitive (image, TRUE); gtk_widget_set_sensitive (onlycolor, TRUE); gtk_widget_set_sensitive (browse_button, TRUE); if (GTK_TOGGLE_BUTTON (onlycolor)->active) { gtk_widget_set_sensitive (color_label, TRUE); gtk_widget_set_sensitive (color, TRUE); } else { gtk_widget_set_sensitive (color_label, FALSE); gtk_widget_set_sensitive (color, FALSE); } } else /* if (GTK_TOGGLE_BUTTON (color_bg)->active) */ { gtk_widget_set_sensitive (scale, FALSE); gtk_widget_set_sensitive (image, FALSE); gtk_widget_set_sensitive (onlycolor, FALSE); gtk_widget_set_sensitive (color_label, TRUE); gtk_widget_set_sensitive (color, TRUE); gtk_widget_set_sensitive (browse_button, FALSE); } } static void setup_background_support (void) { GtkWidget *no_bg = glade_helper_get (xml, "sg_no_bg_rb", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *image_bg = glade_helper_get (xml, "sg_image_bg_rb", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *color_bg = glade_helper_get (xml, "sg_color_bg_rb", GTK_TYPE_TOGGLE_BUTTON); GtkWidget *onlycolor = glade_helper_get (xml, "sg_remote_color_only", GTK_TYPE_TOGGLE_BUTTON); g_signal_connect (G_OBJECT (no_bg), "toggled", G_CALLBACK (background_toggled), NULL); g_signal_connect (G_OBJECT (image_bg), "toggled", G_CALLBACK (background_toggled), NULL); g_signal_connect (G_OBJECT (color_bg), "toggled", G_CALLBACK (background_toggled), NULL); g_signal_connect (G_OBJECT (onlycolor), "toggled", G_CALLBACK (background_toggled), NULL); background_toggled (); } static char * get_theme_dir (void) { char *theme_dir; theme_dir = ve_config_get_string (ve_config_get (config_file), GDM_KEY_GRAPHICAL_THEME_DIR); if (theme_dir == NULL || theme_dir[0] == '\0' || access (theme_dir, R_OK) != 0) { g_free (theme_dir); theme_dir = g_strdup (EXPANDED_DATADIR "/gdm/themes/"); } return theme_dir; } static void textview_set_buffer (GtkTextView *view, const char *text) { GtkTextBuffer *buffer = gtk_text_view_get_buffer (view); gtk_text_buffer_set_text (buffer, text, -1); } /* Sets up the preview section of Themed Greeter page after a theme has been selected */ static void gg_selection_changed (GtkTreeSelection *selection, gpointer data) { GtkWidget *label; GtkWidget *preview = glade_helper_get (xml, "gg_theme_preview", GTK_TYPE_IMAGE); GtkWidget *no_preview = glade_helper_get (xml, "gg_theme_no_preview", GTK_TYPE_WIDGET); GtkWidget *del_button = glade_helper_get (xml, "gg_delete_theme", GTK_TYPE_BUTTON); char *screenshot; GtkTreeModel *model; GtkTreeIter iter; GValue value = {0, }; gboolean GdmGraphicalThemeRand = ve_config_get_bool ( ve_config_get (config_file), GDM_KEY_GRAPHICAL_THEME_RAND); if ( ! gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_widget_set_sensitive (del_button, FALSE); return; } /* Default to allow deleting of themes */ gtk_widget_set_sensitive (del_button, TRUE); /* Determine if the theme selected is currently active */ if (GdmGraphicalThemeRand) { gtk_tree_model_get_value (model, &iter, THEME_COLUMN_SELECTED_LIST, &value); } else { gtk_tree_model_get_value (model, &iter, THEME_COLUMN_SELECTED, &value); } /* Do not allow deleting of active themes */ if (g_value_get_boolean (&value)) { gtk_widget_set_sensitive (del_button, FALSE); } g_value_unset (&value); gtk_tree_model_get_value (model, &iter, THEME_COLUMN_AUTHOR, &value); label = glade_helper_get (xml, "gg_author_text_view", GTK_TYPE_TEXT_VIEW); textview_set_buffer (GTK_TEXT_VIEW (label), ve_sure_string (g_value_get_string (&value))); g_value_unset (&value); gtk_tree_model_get_value (model, &iter, THEME_COLUMN_COPYRIGHT, &value); label = glade_helper_get (xml, "gg_copyright_text_view", GTK_TYPE_TEXT_VIEW); textview_set_buffer (GTK_TEXT_VIEW (label), ve_sure_string (g_value_get_string (&value))); g_value_unset (&value); gtk_tree_model_get_value (model, &iter, THEME_COLUMN_DESCRIPTION, &value); label = glade_helper_get (xml, "gg_desc_text_view", GTK_TYPE_TEXT_VIEW); textview_set_buffer (GTK_TEXT_VIEW (label), ve_sure_string (g_value_get_string (&value))); g_value_unset (&value); gtk_tree_model_get_value (model, &iter, THEME_COLUMN_SCREENSHOT, &value); screenshot = g_strdup (g_value_get_string (&value)); g_value_unset (&value); gtk_widget_hide (preview); gtk_widget_show (no_preview); if ( ! ve_string_empty (screenshot) && access (screenshot, R_OK) == 0) { GdkPixbuf *pb; pb = gdk_pixbuf_new_from_file (screenshot, NULL); if (pb != NULL) { if (gdk_pixbuf_get_width (pb) > 200 || gdk_pixbuf_get_height (pb) > 150) { GdkPixbuf *pb2; pb2 = gdk_pixbuf_scale_simple (pb, 200, 150, GDK_INTERP_BILINEAR); g_object_unref (G_OBJECT (pb)); pb = pb2; } gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pb); g_object_unref (G_OBJECT (pb)); gtk_widget_show (preview); gtk_widget_hide (no_preview); } } g_free (screenshot); } static GtkTreeIter * read_themes (GtkListStore *store, const char *theme_dir, DIR *dir, const char *select_item) { struct dirent *dent; GtkTreeIter *select_iter = NULL; while ((dent = readdir (dir)) != NULL) { char *n, *file, *name, *desc, *author, *copyright, *ss; char *full; GtkTreeIter iter; gboolean sel_theme; gboolean sel_themes; VeConfig *theme_file; if (dent->d_name[0] == '.') continue; n = g_strconcat (theme_dir, "/", dent->d_name, "/GdmGreeterTheme.desktop", NULL); if (access (n, R_OK) != 0) { g_free (n); n = g_strconcat (theme_dir, "/", dent->d_name, "/GdmGreeterTheme.info", NULL); } if (access (n, R_OK) != 0) { g_free (n); continue; } theme_file = ve_config_new (n); file = ve_config_get_translated_string (theme_file, "GdmGreeterTheme/Greeter"); if (ve_string_empty (file)) { g_free (file); file = g_strconcat (dent->d_name, ".xml", NULL); } full = g_strconcat (theme_dir, "/", dent->d_name, "/", file, NULL); if (access (full, R_OK) != 0) { g_free (file); g_free (full); g_free (n); continue; } g_free (full); if (selected_theme != NULL && strcmp (dent->d_name, selected_theme) == 0) sel_theme = TRUE; else sel_theme = FALSE; if (selected_themes != NULL && themes_list_contains (selected_themes, dent->d_name)) sel_themes = TRUE; else sel_themes = FALSE; name = ve_config_get_translated_string (theme_file, "GdmGreeterTheme/Name"); if (ve_string_empty (name)) { g_free (name); name = g_strdup (dent->d_name); } desc = ve_config_get_translated_string (theme_file, "GdmGreeterTheme/Description"); author = ve_config_get_translated_string (theme_file, "GdmGreeterTheme/Author"); copyright = ve_config_get_translated_string (theme_file, "GdmGreeterTheme/Copyright"); ss = ve_config_get_translated_string (theme_file, "GdmGreeterTheme/Screenshot"); ve_config_destroy (theme_file); if (ss != NULL) full = g_strconcat (theme_dir, "/", dent->d_name, "/", ss, NULL); else full = NULL; gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, THEME_COLUMN_SELECTED, sel_theme, THEME_COLUMN_SELECTED_LIST, sel_themes, THEME_COLUMN_DIR, dent->d_name, THEME_COLUMN_FILE, file, THEME_COLUMN_NAME, name, THEME_COLUMN_DESCRIPTION, desc, THEME_COLUMN_AUTHOR, author, THEME_COLUMN_COPYRIGHT, copyright, THEME_COLUMN_SCREENSHOT, full, -1); if (select_item != NULL && strcmp (dent->d_name, select_item) == 0) { /* anality */ g_free (select_iter); select_iter = g_new0 (GtkTreeIter, 1); *select_iter = iter; } g_free (file); g_free (name); g_free (desc); g_free (author); g_free (copyright); g_free (ss); g_free (full); g_free (n); } return select_iter; } static gboolean greeter_theme_timeout (GtkWidget *toggle) { char *theme; char *themes; VeConfig *config = ve_config_get (config_file); theme = ve_config_get_string (config, GDM_KEY_GRAPHICAL_THEME); themes = ve_config_get_string (config, GDM_KEY_GRAPHICAL_THEMES); /* If no checkbox themes selected */ if (selected_themes == NULL) selected_themes = ""; /* If themes have changed from the config file, update it. */ if ((strcmp (ve_sure_string (theme), ve_sure_string (selected_theme)) != 0) || (strcmp (ve_sure_string (themes), ve_sure_string (selected_themes)) != 0)) { ve_config_set_string (config, GDM_KEY_GRAPHICAL_THEME, selected_theme); ve_config_set_string (config, GDM_KEY_GRAPHICAL_THEMES, selected_themes); ve_config_save (config, FALSE /* force */); update_greeters (); } g_free (theme); g_free (themes); return FALSE; } static void selected_toggled (GtkCellRendererToggle *cell, char *path_str, gpointer data) { gchar *theme_name = NULL; GtkTreeModel *model = GTK_TREE_MODEL (data); GtkTreeIter selected_iter; GtkTreeIter iter; GtkTreePath *path; GtkTreePath *sel_path = gtk_tree_path_new_from_string (path_str); GtkWidget *theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); GtkWidget *del_button = glade_helper_get (xml, "gg_delete_theme", GTK_TYPE_BUTTON); gboolean is_radio; gtk_tree_model_get_iter (model, &selected_iter, sel_path); path = gtk_tree_path_new_first (); is_radio = gtk_cell_renderer_toggle_get_radio (cell); if (is_radio) { /* Radiobuttons */ /* Clear list of all selected themes */ g_free (selected_theme); /* Get the new selected theme */ gtk_tree_model_get (model, &selected_iter, THEME_COLUMN_DIR, &selected_theme, -1); /* Loop through all themes in list */ while (gtk_tree_model_get_iter (model, &iter, path)) { /* If this toggle was just toggled */ if (gtk_tree_path_compare (path, sel_path) == 0) { gtk_list_store_set (GTK_LIST_STORE (model), &iter, THEME_COLUMN_SELECTED, TRUE, -1); /* Toggle ON */ gtk_widget_set_sensitive (del_button, FALSE); } else { gtk_list_store_set (GTK_LIST_STORE (model), &iter, THEME_COLUMN_SELECTED, FALSE, -1); /* Toggle OFF */ } gtk_tree_path_next (path); } } else { /* Checkboxes */ /* Clear list of all selected themes */ g_free(selected_themes); selected_themes = NULL; /* Loop through all checkboxes */ while (gtk_tree_model_get_iter (model, &iter, path)) { gboolean selected = FALSE; /* If this checkbox was just toggled */ if (gtk_tree_path_compare (path, sel_path) == 0) { gtk_tree_model_get (model, &selected_iter, THEME_COLUMN_DIR, &theme_name, -1); if (gtk_cell_renderer_toggle_get_active (cell)) { gtk_list_store_set (GTK_LIST_STORE (model), &iter, THEME_COLUMN_SELECTED_LIST, FALSE, -1); /* Toggle OFF */ gtk_widget_set_sensitive (del_button, TRUE); } else { gtk_list_store_set (GTK_LIST_STORE (model), &iter, THEME_COLUMN_SELECTED_LIST, TRUE, -1); /* Toggle ON */ gtk_widget_set_sensitive (del_button, FALSE); } } gtk_tree_model_get (model, &iter, THEME_COLUMN_SELECTED_LIST, &selected, THEME_COLUMN_DIR, &theme_name, -1); if (selected) selected_themes = strings_list_add (selected_themes, theme_name, GDM_DELIMITER_THEMES); g_free(theme_name); gtk_tree_path_next (path); } if (selected_themes == NULL) selected_themes = g_strdup(""); } gtk_tree_path_free (path); gtk_tree_path_free (sel_path); run_timeout (theme_list, 500, greeter_theme_timeout); } static gboolean is_ext (const char *filename, const char *ext) { const char *dot; dot = strrchr (filename, '.'); if (dot == NULL) return FALSE; if (strcmp (dot, ext) == 0) return TRUE; else return FALSE; } /* sense the right unzip program */ static char * find_unzip (const char *filename) { char *prog; char *tryg[] = { "/bin/gunzip", "/usr/bin/gunzip", NULL }; char *tryb[] = { "/bin/bunzip2", "/usr/bin/bunzip2", NULL }; int i; if (is_ext (filename, ".bz2")) { prog = g_find_program_in_path ("bunzip2"); if (prog != NULL) return prog; for (i = 0; tryb[i] != NULL; i++) { if (access (tryb[i], X_OK) == 0) return g_strdup (tryb[i]); } } prog = g_find_program_in_path ("gunzip"); if (prog != NULL) return prog; for (i = 0; tryg[i] != NULL; i++) { if (access (tryg[i], X_OK) == 0) return g_strdup (tryg[i]); } /* Hmmm, fallback */ return g_strdup ("/bin/gunzip"); } static char * find_tar (void) { char *tar_prog; char *try[] = { "/bin/gtar", "/bin/tar", "/usr/bin/gtar", "/usr/bin/tar", NULL }; int i; tar_prog = g_find_program_in_path ("gtar"); if (tar_prog != NULL) return tar_prog; tar_prog = g_find_program_in_path ("tar"); if (tar_prog != NULL) return tar_prog; for (i = 0; try[i] != NULL; i++) { if (access (try[i], X_OK) == 0) return g_strdup (try[i]); } /* Hmmm, fallback */ return g_strdup ("/bin/tar"); } static char * find_chmod (void) { char *chmod_prog; char *try[] = { "/bin/chmod", "/sbin/chmod", "/usr/bin/chmod", "/usr/sbin/chmod", NULL }; int i; chmod_prog = g_find_program_in_path ("chmod"); if (chmod_prog != NULL) return chmod_prog; for (i = 0; try[i] != NULL; i++) { if (access (try[i], X_OK) == 0) return g_strdup (try[i]); } /* Hmmm, fallback */ return g_strdup ("/bin/chmod"); } static char * find_chown (void) { char *chown_prog; char *try[] = { "/bin/chown", "/sbin/chown", "/usr/bin/chown", "/usr/sbin/chown", NULL }; int i; chown_prog = g_find_program_in_path ("chown"); if (chown_prog != NULL) return chown_prog; for (i = 0; try[i] != NULL; i++) { if (access (try[i], X_OK) == 0) return g_strdup (try[i]); } /* Hmmm, fallback */ return g_strdup ("/bin/chown"); } static char * get_the_dir (FILE *fp, char **error) { char buf[2048]; char *dir = NULL; int dirlen = 0; gboolean got_info = FALSE; gboolean read_a_line = FALSE; while (fgets (buf, sizeof (buf), fp) != NULL) { char *p, *s; read_a_line = TRUE; p = strchr (buf, '\n'); if (p != NULL) *p = '\0'; if (dir == NULL) { p = strchr (buf, '/'); if (p != NULL) *p = '\0'; dir = g_strdup (buf); if (p != NULL) *p = '/'; dirlen = strlen (dir); if (dirlen < 1) { *error = _("Archive is not of a subdirectory"); g_free (dir); return NULL; } } if (strncmp (buf, dir, dirlen) != 0) { *error = _("Archive is not of a single subdirectory"); g_free (dir); return NULL; } if ( ! got_info) { s = g_strconcat (dir, "/GdmGreeterTheme.info", NULL); if (strcmp (buf, s) == 0) got_info = TRUE; g_free (s); } if ( ! got_info) { s = g_strconcat (dir, "/GdmGreeterTheme.desktop", NULL); if (strcmp (buf, s) == 0) got_info = TRUE; g_free (s); } } if (got_info) return dir; if ( ! read_a_line) *error = _("File not a tar.gz or tar archive"); else *error = _("Archive does not include a " "GdmGreeterTheme.info file"); g_free (dir); return NULL; } static char * get_archive_dir (const char *filename, char **untar_cmd, char **error) { char *quoted; char *tar; char *unzip; char *cmd; char *dir; FILE *fp; *untar_cmd = NULL; *error = NULL; if (access (filename, F_OK) != 0) { *error = _("File does not exist"); return NULL; } /* Note that this adds './' In front to avoid troubles */ quoted = ve_shell_quote_filename (filename); tar = find_tar (); unzip = find_unzip (filename); cmd = g_strdup_printf ("%s -c %s | %s -tf -", unzip, quoted, tar); fp = popen (cmd, "r"); g_free (cmd); if (fp != NULL) { int ret; dir = get_the_dir (fp, error); ret = pclose (fp); if (ret == 0 && dir != NULL) { *untar_cmd = g_strdup_printf ("%s -c %s | %s -xf -", unzip, quoted, tar); g_free (tar); g_free (unzip); g_free (quoted); return dir; } else { *error = NULL; } g_free (dir); } /* error due to command failing */ if (*error == NULL) { /* Try uncompressed? */ cmd = g_strdup_printf ("%s -tf %s", tar, quoted); fp = popen (cmd, "r"); g_free (cmd); if (fp != NULL) { int ret; dir = get_the_dir (fp, error); ret = pclose (fp); if (ret == 0 && dir != NULL) { *untar_cmd = g_strdup_printf ("%s -xf %s", tar, quoted); g_free (tar); g_free (unzip); g_free (quoted); return dir; } else { *error = NULL; } g_free (dir); } } if (*error == NULL) *error = _("File not a tar.gz or tar archive"); g_free (tar); g_free (unzip); g_free (quoted); return NULL; } static gboolean dir_exists (const char *parent, const char *dir) { DIR *dp = opendir (parent); struct dirent *dent; if (dp == NULL) return FALSE; while ((dent = readdir (dp)) != NULL) { if (strcmp (dent->d_name, dir) == 0) { closedir (dp); return TRUE; } } closedir (dp); return FALSE; } static void theme_install_response (GtkWidget *chooser, gint response, gpointer data) { GtkListStore *store = data; GtkWidget *theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); char *filename, *dir, *untar_cmd, *theme_dir, *cwd; GtkTreeIter *select_iter = NULL; GtkTreeSelection *selection; char *error; DIR *dp; gboolean success = FALSE; if (response != GTK_RESPONSE_OK) { gtk_widget_destroy (chooser); return; } cwd = g_get_current_dir (); theme_dir = get_theme_dir (); filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)); if (last_theme_installed != NULL) g_free (last_theme_installed); last_theme_installed = g_strdup (filename); if (filename == NULL) { GtkWidget *dlg = ve_hig_dialog_new (GTK_WINDOW (chooser), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("No file selected"), ""); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); g_free (cwd); g_free (theme_dir); return; } if ( ! g_path_is_absolute (filename)) { char *f = g_build_filename (cwd, filename, NULL); g_free (filename); filename = f; } dir = get_archive_dir (filename, &untar_cmd, &error); /* FIXME: perhaps do a little bit more sanity checking of * the archive */ if (dir == NULL) { GtkWidget *dlg; gchar *msg; msg = g_strdup_printf (_("Details: %s"), error); dlg = ve_hig_dialog_new (GTK_WINDOW (chooser), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Not a theme archive"), msg); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); g_free (filename); g_free (cwd); g_free (theme_dir); g_free (msg); return; } if (dir_exists (theme_dir, dir)) { char *fname = ve_filename_to_utf8 (dir); char *s; GtkWidget *button; GtkWidget *dlg; /* FIXME: if exists already perhaps we could also have an * option to change the dir name */ s = g_strdup_printf (_("Theme directory '%s' seems to be already " "installed. Install again anyway?"), fname); dlg = ve_hig_dialog_new (GTK_WINDOW (chooser), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, s, ""); g_free (fname); g_free (s); button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); gtk_dialog_add_action_widget (GTK_DIALOG (dlg), button, GTK_RESPONSE_NO); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_show (button); button = gtk_button_new_from_stock ("_Install Anyway"); gtk_dialog_add_action_widget (GTK_DIALOG (dlg), button, GTK_RESPONSE_YES); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_show (button); gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_YES); gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); if (gtk_dialog_run (GTK_DIALOG (dlg)) != GTK_RESPONSE_YES) { gtk_widget_destroy (dlg); g_free (filename); g_free (cwd); g_free (dir); g_free (theme_dir); return; } gtk_widget_destroy (dlg); } g_assert (untar_cmd != NULL); if (chdir (theme_dir) == 0 && /* this is a security sanity check */ strchr (dir, '/') == NULL && system (untar_cmd) == 0) { char *argv[5]; char *quoted = g_strconcat ("./", dir, NULL); char *chown = find_chown (); char *chmod = find_chmod (); success = TRUE; /* HACK! */ argv[0] = chown; argv[1] = "-R"; argv[2] = "root:root"; argv[3] = quoted; argv[4] = NULL; simple_spawn_sync (argv); argv[0] = chmod; argv[1] = "-R"; argv[2] = "a+r"; argv[3] = quoted; argv[4] = NULL; simple_spawn_sync (argv); argv[0] = chmod; argv[1] = "a+x"; argv[2] = quoted; argv[3] = NULL; simple_spawn_sync (argv); g_free (quoted); g_free (chown); g_free (chmod); } if ( ! success) { GtkWidget *dlg = ve_hig_dialog_new (GTK_WINDOW (chooser), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Some error occurred when " "installing the theme"), ""); gtk_dialog_run (GTK_DIALOG (dlg)); gtk_widget_destroy (dlg); } gtk_list_store_clear (store); dp = opendir (theme_dir); if (dp != NULL) { select_iter = read_themes (store, theme_dir, dp, dir); closedir (dp); } selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list)); if (select_iter != NULL) { gtk_tree_selection_select_iter (selection, select_iter); g_free (select_iter); } g_free (untar_cmd); g_free (dir); g_free (filename); g_free (cwd); g_free (theme_dir); gtk_widget_destroy (GTK_WIDGET (chooser)); } static void install_new_theme (GtkWidget *button, gpointer data) { GtkListStore *store = data; static GtkWidget *chooser = NULL; GtkWidget *setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); chooser = gtk_file_chooser_dialog_new (_("Select new theme archive to install"), GTK_WINDOW (setup_dialog), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Install"), GTK_RESPONSE_OK, NULL); gtk_file_chooser_set_show_hidden (chooser, TRUE); g_signal_connect (G_OBJECT (chooser), "destroy", G_CALLBACK (gtk_widget_destroyed), &chooser); g_signal_connect (G_OBJECT (chooser), "response", G_CALLBACK (theme_install_response), store); if (last_theme_installed != NULL) gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), last_theme_installed); gtk_widget_show (chooser); } static void delete_theme (GtkWidget *button, gpointer data) { GtkListStore *store = data; GtkWidget *theme_list; GtkWidget *setup_dialog; GtkWidget *del_button; GtkTreeSelection *selection; char *dir, *name; GtkTreeModel *model; GtkTreeIter iter; GValue value = {0, }; GtkWidget *dlg; char *s; setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); del_button = glade_helper_get (xml, "gg_delete_theme", GTK_TYPE_BUTTON); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list)); if ( ! gtk_tree_selection_get_selected (selection, &model, &iter)) { /* should never get here since the button shuld not be * enabled */ return; } gtk_tree_model_get_value (model, &iter, THEME_COLUMN_SELECTED, &value); /* Do not allow deleting of selected theme */ if (g_value_get_boolean (&value)) { /* should never get here since the button shuld not be * enabled */ g_value_unset (&value); return; } g_value_unset (&value); gtk_tree_model_get_value (model, &iter, THEME_COLUMN_NAME, &value); name = g_strdup (g_value_get_string (&value)); g_value_unset (&value); gtk_tree_model_get_value (model, &iter, THEME_COLUMN_DIR, &value); dir = g_strdup (g_value_get_string (&value)); g_value_unset (&value); s = g_strdup_printf (_("Do you really wish to remove theme '%s' from the system?"), name); dlg = ve_hig_dialog_new (GTK_WINDOW (setup_dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, s, ""); g_free (s); button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); gtk_dialog_add_action_widget (GTK_DIALOG (dlg), button, GTK_RESPONSE_NO); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_show (button); button = gtk_button_new_from_stock (_("_Remove Theme")); gtk_dialog_add_action_widget (GTK_DIALOG (dlg), button, GTK_RESPONSE_YES); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_show (button); gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_YES); if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_YES) { char *theme_dir = get_theme_dir (); char *cwd = g_get_current_dir (); if (chdir (theme_dir) == 0 && /* this is a security sanity check, since we're doing rm -fR */ strchr (dir, '/') == NULL) { /* HACK! */ DIR *dp; char *argv[4]; GtkTreeIter *select_iter = NULL; argv[0] = "/bin/rm"; argv[1] = "-fR"; argv[2] = g_strconcat ("./", dir, NULL); argv[3] = NULL; simple_spawn_sync (argv); g_free (argv[2]); /* Update the list */ gtk_list_store_clear (store); dp = opendir (theme_dir); if (dp != NULL) { select_iter = read_themes (store, theme_dir, dp, selected_theme); closedir (dp); } if (select_iter != NULL) { gtk_tree_selection_select_iter (selection, select_iter); g_free (select_iter); } } chdir (cwd); g_free (cwd); g_free (theme_dir); } gtk_widget_destroy (dlg); g_free (name); g_free (dir); } static gboolean xserver_entry_timeout (GtkWidget *entry) { VeConfig *cfg; const char *key = g_object_get_data (G_OBJECT (entry), "key"); const char *text = gtk_entry_get_text (GTK_ENTRY (entry)); /* Get xserver section to update */ GtkWidget *combobox = glade_helper_get (xml, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); gchar *section = gtk_combo_box_get_active_text (GTK_COMBO_BOX (combobox)); section = g_strconcat(GDM_KEY_SERVER_PREFIX, section, "/", NULL); if (strcmp (key, GDM_KEY_SERVER_NAME) == 0) section = g_strconcat(section, GDM_KEY_SERVER_NAME, NULL); else if (strcmp (key, GDM_KEY_SERVER_COMMAND) == 0) section = g_strconcat(section, GDM_KEY_SERVER_COMMAND, NULL); /* Locate this server's section */ cfg = ve_config_get (config_file); /* Update this servers configuration */ ve_config_set_string (cfg, section, ve_sure_string (text)); ve_config_save (cfg, FALSE /* force */); g_free(section); return FALSE; } static gboolean xserver_toggle_timeout (GtkWidget *toggle) { const char *key = g_object_get_data (G_OBJECT (toggle), "key"); VeConfig *cfg; gboolean val; /* Get xserver section to update */ GtkWidget *combobox = glade_helper_get (xml, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); gchar *section = gtk_combo_box_get_active_text (GTK_COMBO_BOX (combobox)); section = g_strconcat(GDM_KEY_SERVER_PREFIX, section, "/", NULL); if (strcmp (key, GDM_KEY_SERVER_HANDLED) == 0) section = g_strconcat(section, GDM_KEY_SERVER_HANDLED, NULL); else if (strcmp (key, GDM_KEY_SERVER_FLEXIBLE) == 0) section = g_strconcat(section, GDM_KEY_SERVER_FLEXIBLE, NULL); else if (strcmp (key, GDM_KEY_SERVER_CHOOSER) == 0) section = g_strconcat(section, GDM_KEY_SERVER_CHOOSER, NULL); /* Locate this server's section */ cfg = ve_config_get (config_file); val = ve_config_get_bool (cfg, section); /* Update this servers configuration */ if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) { ve_config_set_bool (cfg, section, GTK_TOGGLE_BUTTON (toggle)->active); ve_config_save (cfg, FALSE /* force */); } g_free(section); return FALSE; } static void xserver_toggle_toggled (GtkWidget *toggle) { run_timeout (toggle, 500, xserver_toggle_timeout); } static void xserver_entry_changed (GtkWidget *entry) { run_timeout (entry, 500, xserver_entry_timeout); } static void xserver_append_combobox(GdmXServer *xserver, GtkComboBox *combobox) { gtk_combo_box_append_text (combobox, xserver->id); } static void xserver_populate_combobox(GtkComboBox* combobox) { gint i,j; GSList *xservers; /* Get number of items in combobox */ i = gtk_tree_model_iter_n_children( gtk_combo_box_get_model (GTK_COMBO_BOX (combobox)), NULL); /* Delete all items from combobox */ for (j = 0; j < i; j++) { gtk_combo_box_remove_text(combobox,0); } /* Populate combobox with list of current servers */ xservers = xservers_get_server_definitions(); g_slist_foreach(xservers, (GFunc) xserver_append_combobox, combobox); } static void xserver_init_server_list() { /* Get Widgets from glade */ GtkWidget *treeview = glade_helper_get (xml, "xserver_tree_view", GTK_TYPE_TREE_VIEW); GtkWidget *remove_button = glade_helper_get (xml, "xserver_remove_button", GTK_TYPE_BUTTON); /* create list store */ GtkListStore *store = gtk_list_store_new (XSERVER_NUM_COLUMNS, G_TYPE_INT /* virtual terminal */, G_TYPE_STRING /* server type */, G_TYPE_STRING /* options */); /* Read all xservers to start from configuration */ xservers_get_servers(store); gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store)); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE); gtk_widget_set_sensitive (remove_button, FALSE); } static void xserver_init_servers() { GtkWidget *spinner, *combo, *entry, *add_button, *remove_button; /* Get Widgets from glade */ spinner = glade_helper_get (xml, "xserver_spin_button", GTK_TYPE_SPIN_BUTTON); combo = glade_helper_get (xml, "xserver_server_combobox", GTK_TYPE_COMBO_BOX); entry = glade_helper_get (xml, "xserver_options_entry", GTK_TYPE_ENTRY); add_button = glade_helper_get (xml, "xserver_add_button", GTK_TYPE_BUTTON); remove_button = glade_helper_get (xml, "xserver_remove_button", GTK_TYPE_BUTTON); /* Init widget states */ xserver_init_server_list(); gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), 1); xserver_populate_combobox (GTK_COMBO_BOX (combo)); gtk_entry_set_text (GTK_ENTRY (entry), ""); gtk_widget_set_sensitive (add_button, FALSE); gtk_widget_set_sensitive (remove_button, FALSE); } static void xserver_row_selected(GtkTreeSelection *selection, gpointer data) { GtkWidget *remove_button = glade_helper_get (xml, "xserver_remove_button", GTK_TYPE_BUTTON); gtk_widget_set_sensitive (remove_button, TRUE); } /* Remove a server from the list of servers to start (not the same as * deleting a server definition) */ static void xserver_remove(gpointer data) { GtkWidget *treeview, *combo; GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; VeConfig *cfg; gint vt; char vt_value[3]; treeview = glade_helper_get (xml, "xserver_tree_view", GTK_TYPE_TREE_VIEW); combo = glade_helper_get (xml, "xserver_server_combobox", GTK_TYPE_COMBO_BOX); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { char *key; /* Update config */ cfg = ve_config_get (config_file); gtk_tree_model_get (model, &iter, XSERVER_COLUMN_VT, &vt, -1); g_snprintf (vt_value, sizeof (vt_value), "%d", vt); key = g_object_get_data (G_OBJECT (combo), "key"); key = g_strconcat (key, "/", vt_value, "=", NULL); ve_config_delete_key (cfg, key); ve_config_save (cfg, FALSE /* force */); /* Update gdmsetup */ xserver_init_server_list(); xserver_update_delete_sensitivity(); } } /* Add a server to the list of servers to start (not the same as * creating a server definition) */ static void xserver_add(gpointer data) { VeConfig *cfg; GtkWidget *spinner, *combo, *entry, *button; gchar *string; char spinner_value[3], *key; /* Get Widgets from glade */ spinner = glade_helper_get (xml, "xserver_spin_button", GTK_TYPE_SPIN_BUTTON); entry = glade_helper_get (xml, "xserver_options_entry", GTK_TYPE_ENTRY); combo = glade_helper_get (xml, "xserver_server_combobox", GTK_TYPE_COMBO_BOX); button = glade_helper_get (xml, "xserver_add_button", GTK_TYPE_BUTTON); /* Section in config to modify */ key = g_object_get_data (G_OBJECT (combo), "key"); /* String to add to config */ g_snprintf (spinner_value, sizeof (spinner_value), "%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner))); key = g_strconcat (key, "/", spinner_value, "=", NULL); string = g_strconcat (gtk_combo_box_get_active_text (GTK_COMBO_BOX (combo)), " ", gtk_entry_get_text (GTK_ENTRY (entry)), NULL); /* Add to config */ cfg = ve_config_get (config_file); ve_config_set_string (cfg, key, ve_sure_string(string)); ve_config_save (cfg, FALSE /* force */); /* Reinitialize gdmsetup */ xserver_init_servers(); xserver_update_delete_sensitivity(); /* Free memory */ g_free(string); g_free(key); } /* TODO: This section needs a little work until it is ready (mainly config section modifications) */ /* Create a server definition (not the same as removing a server * from the list of servers to start) */ static void xserver_create(gpointer data) { VeConfig *cfg; gboolean success; /* Init Widgets */ GtkWidget *frame, *modify_combobox; GtkWidget *name_entry, *command_entry; GtkWidget *handled_check, *flexible_check; GtkWidget *greeter_radio, *chooser_radio; GtkWidget *create_button, *delete_button; /* Get Widgets from glade */ frame = glade_helper_get (xml, "xserver_modify_frame", GTK_TYPE_FRAME); name_entry = glade_helper_get (xml, "xserver_name_entry", GTK_TYPE_ENTRY); command_entry = glade_helper_get (xml, "xserver_command_entry", GTK_TYPE_ENTRY); handled_check = glade_helper_get (xml, "xserver_handled_checkbutton", GTK_TYPE_CHECK_BUTTON); flexible_check = glade_helper_get (xml, "xserver_flexible_checkbutton", GTK_TYPE_CHECK_BUTTON); greeter_radio = glade_helper_get (xml, "xserver_greeter_radiobutton", GTK_TYPE_RADIO_BUTTON); chooser_radio = glade_helper_get (xml, "xserver_chooser_radiobutton", GTK_TYPE_RADIO_BUTTON); modify_combobox = glade_helper_get (xml, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); create_button = glade_helper_get (xml, "xserver_create_button", GTK_TYPE_BUTTON); delete_button = glade_helper_get (xml, "xserver_delete_button", GTK_TYPE_BUTTON); gtk_combo_box_append_text (GTK_COMBO_BOX (modify_combobox), "New Server"); /* TODO: Create a new section for this server */ /* TODO: Write this value to the config and update xservers list */ cfg = ve_config_get (config_file); success = FALSE; /* success = ve_config_add_section (cfg, SECTION_NAME); */ if (success) { gint i; /* Update settings for new server */ gtk_widget_set_sensitive (frame, TRUE); gtk_widget_set_sensitive (delete_button, TRUE); gtk_widget_grab_focus (name_entry); gtk_entry_set_text (GTK_ENTRY (name_entry), "New Server"); gtk_editable_select_region (GTK_EDITABLE (name_entry), 0, -1); gtk_entry_set_text (GTK_ENTRY (command_entry), X_SERVER); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (greeter_radio), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser_radio), FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (handled_check), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (flexible_check), FALSE); /* Select the new server in the combobox */ i = gtk_tree_model_iter_n_children ( gtk_combo_box_get_model (GTK_COMBO_BOX (modify_combobox)), NULL) - 1; gtk_combo_box_set_active (GTK_COMBO_BOX (modify_combobox), i); } } static void xserver_init_definitions() { /* Init Widgets */ GtkWidget *frame, *modify_combobox, *server_combobox; GtkWidget *name_entry, *command_entry; GtkWidget *handled_check, *flexible_check; GtkWidget *greeter_radio, *chooser_radio; GtkWidget *create_button, *delete_button; /* Get Widgets from glade */ frame = glade_helper_get (xml, "xserver_modify_frame", GTK_TYPE_FRAME); name_entry = glade_helper_get (xml, "xserver_name_entry", GTK_TYPE_ENTRY); command_entry = glade_helper_get (xml, "xserver_command_entry", GTK_TYPE_ENTRY); handled_check = glade_helper_get (xml, "xserver_handled_checkbutton", GTK_TYPE_CHECK_BUTTON); flexible_check = glade_helper_get (xml, "xserver_flexible_checkbutton", GTK_TYPE_CHECK_BUTTON); greeter_radio = glade_helper_get (xml, "xserver_greeter_radiobutton", GTK_TYPE_RADIO_BUTTON); chooser_radio = glade_helper_get (xml, "xserver_chooser_radiobutton", GTK_TYPE_RADIO_BUTTON); modify_combobox = glade_helper_get (xml, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); server_combobox = glade_helper_get (xml, "xserver_server_combobox", GTK_TYPE_COMBO_BOX); create_button = glade_helper_get (xml, "xserver_create_button", GTK_TYPE_BUTTON); delete_button = glade_helper_get (xml, "xserver_delete_button", GTK_TYPE_BUTTON); /* Populate comboboxes with servers*/ xserver_populate_combobox (GTK_COMBO_BOX (server_combobox)); xserver_populate_combobox (GTK_COMBO_BOX (modify_combobox)); /* Default sensitivity and settings */ gtk_widget_set_sensitive (frame, FALSE); gtk_widget_set_sensitive (delete_button, FALSE); gtk_widget_set_sensitive (create_button, FALSE); gtk_widget_grab_focus (modify_combobox); gtk_entry_set_text (GTK_ENTRY (name_entry), ""); gtk_entry_set_text (GTK_ENTRY (command_entry), ""); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (greeter_radio),TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser_radio),FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (handled_check),TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (flexible_check),FALSE); } /* Deletes a server definition (not the same as removing a server * from the list of servers to start) */ static void xserver_delete(gpointer data) { /* Get xserver section to delete */ GtkWidget *combobox = glade_helper_get (xml, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); gchar *section = gtk_combo_box_get_active_text ( GTK_COMBO_BOX (combobox)); /* Delete xserver section */ VeConfig *cfg = ve_config_get (config_file); ve_config_delete_section (cfg, g_strconcat (GDM_KEY_SERVER_PREFIX, section, NULL)); /* Reinitialize definitions */ xserver_init_definitions(); } static void setup_xserver_support (void) { GtkWidget *frame, *treeview; GtkWidget *modify_combobox, *server_combobox; GtkWidget *name_entry, *command_entry; GtkWidget *handled_check, *flexible_check; GtkWidget *greeter_radio, *chooser_radio; GtkWidget *create_button, *delete_button, *add_button, *remove_button; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; /* Initialize the xserver settings */ xserver_init_definitions(); xserver_init_servers(); /* TODO: In the future, resolution/refresh rate configuration */ /* setup_xrandr_support (); */ /* Get Widgets from glade */ frame = glade_helper_get (xml, "xserver_modify_frame", GTK_TYPE_FRAME); treeview = glade_helper_get (xml, "xserver_tree_view", GTK_TYPE_TREE_VIEW); name_entry = glade_helper_get (xml, "xserver_name_entry", GTK_TYPE_ENTRY); command_entry = glade_helper_get (xml, "xserver_command_entry", GTK_TYPE_ENTRY); handled_check = glade_helper_get (xml, "xserver_handled_checkbutton", GTK_TYPE_CHECK_BUTTON); flexible_check = glade_helper_get (xml, "xserver_flexible_checkbutton", GTK_TYPE_CHECK_BUTTON); greeter_radio = glade_helper_get (xml, "xserver_greeter_radiobutton", GTK_TYPE_RADIO_BUTTON); chooser_radio = glade_helper_get (xml, "xserver_chooser_radiobutton", GTK_TYPE_RADIO_BUTTON); modify_combobox = glade_helper_get (xml, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); server_combobox = glade_helper_get (xml, "xserver_server_combobox", GTK_TYPE_COMBO_BOX); create_button = glade_helper_get (xml, "xserver_create_button", GTK_TYPE_BUTTON); delete_button = glade_helper_get (xml, "xserver_delete_button", GTK_TYPE_BUTTON); remove_button = glade_helper_get (xml, "xserver_remove_button", GTK_TYPE_BUTTON); add_button = glade_helper_get (xml, "xserver_add_button", GTK_TYPE_BUTTON); /* Setup Virtual terminal column in servers to start frame */ column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_set_title (column, "VT"); gtk_tree_view_column_set_attributes (column, renderer, "text", XSERVER_COLUMN_VT, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); /* Setup Server column in servers to start frame */ column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_set_title (column, "Server"); gtk_tree_view_column_set_attributes (column, renderer, "text", XSERVER_COLUMN_SERVER, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); /* Setup Options column in servers to start frame*/ column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_set_title (column, "Options"); gtk_tree_view_column_set_attributes (column, renderer, "text",XSERVER_COLUMN_OPTIONS, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); /* Setup tree selections */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); /* Register these items with keys */ g_object_set_data_full (G_OBJECT (modify_combobox), "key", g_strdup (GDM_KEY_SERVER_PREFIX), (GDestroyNotify) g_free); g_object_set_data_full (G_OBJECT (server_combobox), "key", g_strdup (GDM_KEY_SECTION_SERVERS), (GDestroyNotify) g_free); g_object_set_data_full (G_OBJECT (name_entry), "key", g_strdup (GDM_KEY_SERVER_NAME), (GDestroyNotify) g_free); g_object_set_data_full (G_OBJECT (command_entry), "key", g_strdup (GDM_KEY_SERVER_COMMAND), (GDestroyNotify) g_free); g_object_set_data_full (G_OBJECT (handled_check), "key", g_strdup (GDM_KEY_SERVER_HANDLED), (GDestroyNotify) g_free); g_object_set_data_full (G_OBJECT (flexible_check), "key", g_strdup (GDM_KEY_SERVER_FLEXIBLE), (GDestroyNotify) g_free); g_object_set_data_full (G_OBJECT (chooser_radio), "key", g_strdup (GDM_KEY_SERVER_CHOOSER), (GDestroyNotify) g_free); /* Signals Handlers */ g_signal_connect (G_OBJECT (name_entry), "changed", G_CALLBACK (xserver_entry_changed),NULL); g_signal_connect (G_OBJECT (command_entry), "changed", G_CALLBACK (xserver_entry_changed), NULL); g_signal_connect (modify_combobox, "changed", G_CALLBACK (combobox_changed), NULL); g_signal_connect (server_combobox, "changed", G_CALLBACK (combobox_changed), NULL); g_signal_connect (G_OBJECT (handled_check), "toggled", G_CALLBACK (xserver_toggle_toggled), NULL); g_signal_connect (G_OBJECT (flexible_check), "toggled", G_CALLBACK (xserver_toggle_toggled), NULL); g_signal_connect (G_OBJECT (chooser_radio), "toggled", G_CALLBACK (xserver_toggle_toggled), NULL); /* TODO: In the future, allow creation of servers g_signal_connect (create_button, "clicked", G_CALLBACK (xserver_create), NULL); */ g_signal_connect (delete_button, "clicked", G_CALLBACK (xserver_delete), NULL); g_signal_connect (add_button, "clicked", G_CALLBACK (xserver_add), NULL); g_signal_connect (remove_button, "clicked", G_CALLBACK (xserver_remove), NULL); g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (xserver_row_selected), NULL); } static void setup_graphical_themes (void) { gboolean GdmGraphicalThemeRand; DIR *dir; GtkListStore *store; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; GtkTreeIter *select_iter = NULL; GtkWidget *theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); GtkWidget *button = glade_helper_get (xml, "gg_install_new_theme", GTK_TYPE_BUTTON); GtkWidget *del_button = glade_helper_get (xml, "gg_delete_theme", GTK_TYPE_BUTTON); GtkWidget *mode_combobox = glade_helper_get (xml, "gg_mode_combobox", GTK_TYPE_COMBO_BOX); char *theme_dir = get_theme_dir (); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (theme_list), TRUE); selected_theme = ve_config_get_string (ve_config_get (config_file), GDM_KEY_GRAPHICAL_THEME); selected_themes = ve_config_get_string (ve_config_get (config_file), GDM_KEY_GRAPHICAL_THEMES); /* FIXME: If a theme directory contains the string GDM_DELIMITER_THEMES in the name, then this theme won't work when trying to load as it will be perceived as two different themes seperated by GDM_DELIMITER_THEMES. This can be fixed by setting up an escape character for it, but I'm not sure if directories can have the slash (/) character in them, so I just made GDM_DELIMITER_THEMES equal to "/:" instead. */ GdmGraphicalThemeRand = ve_config_get_bool ( ve_config_get (config_file), GDM_KEY_GRAPHICAL_THEME_RAND); /* create list store */ store = gtk_list_store_new (THEME_NUM_COLUMNS, G_TYPE_BOOLEAN /* selected theme */, G_TYPE_BOOLEAN /* selected themes */, G_TYPE_STRING /* dir */, G_TYPE_STRING /* file */, G_TYPE_STRING /* name */, G_TYPE_STRING /* desc */, G_TYPE_STRING /* author */, G_TYPE_STRING /* copyright */, G_TYPE_STRING /* screenshot */); /* Register theme mode combobox */ g_object_set_data_full (G_OBJECT (mode_combobox), "key", g_strdup (GDM_KEY_GRAPHICAL_THEME_RAND), (GDestroyNotify) g_free); /* Signals */ g_signal_connect (mode_combobox, "changed", G_CALLBACK (combobox_changed), NULL); g_signal_connect (button, "clicked", G_CALLBACK (install_new_theme), store); g_signal_connect (del_button, "clicked", G_CALLBACK (delete_theme), store); /* Init controls */ gtk_widget_set_sensitive (del_button, FALSE); gtk_combo_box_set_active (GTK_COMBO_BOX (mode_combobox), GdmGraphicalThemeRand); /* Read all Themes from directory and store in tree */ dir = opendir (theme_dir); if (dir != NULL) { select_iter = read_themes (store, theme_dir, dir, selected_theme); closedir (dir); } g_free (theme_dir); gtk_tree_view_set_model (GTK_TREE_VIEW (theme_list), GTK_TREE_MODEL (store)); /* The radio toggle column */ column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_toggle_new (); gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE); g_signal_connect (G_OBJECT (renderer), "toggled", G_CALLBACK (selected_toggled), store); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "active", THEME_COLUMN_SELECTED, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (theme_list), column); gtk_tree_view_column_set_visible(column, !GdmGraphicalThemeRand); /* The checkbox toggle column */ column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_toggle_new (); gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), FALSE); g_signal_connect (G_OBJECT (renderer), "toggled", G_CALLBACK (selected_toggled), store); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "active", THEME_COLUMN_SELECTED_LIST, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (theme_list), column); gtk_tree_view_column_set_visible(column, GdmGraphicalThemeRand); /* The text column */ column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_set_attributes (column, renderer, "text", THEME_COLUMN_NAME, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (theme_list), column); /* Selection setup */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); g_signal_connect (selection, "changed", G_CALLBACK (gg_selection_changed), NULL); if (select_iter != NULL) { gtk_tree_selection_select_iter (selection, select_iter); g_free (select_iter); } } static gboolean delete_event (GtkWidget *w) { timeout_remove_all (); gtk_main_quit (); return FALSE; } static void dialog_response (GtkWidget *dlg, int response, gpointer data) { if (response == GTK_RESPONSE_CLOSE) { timeout_remove_all (); gtk_main_quit (); } else if (response == GTK_RESPONSE_HELP) { GError *error = NULL; GtkWidget *setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); static GtkWidget *dlg = NULL; if (dlg != NULL) { gtk_window_present (GTK_WINDOW (dlg)); return; } if ( ! RUNNING_UNDER_GDM) { gnome_help_display_uri ("ghelp:gdm", &error); /* FIXME: handle errors nicer */ if (error == NULL) return; g_error_free (error); } /* fallback help dialogue */ /* HIG compliance? */ dlg = gtk_message_dialog_new (GTK_WINDOW (setup_dialog), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, /* This is the temporary help dialog */ _("This configuration window changes settings " "for the GDM daemon, which is the graphical " "login screen for GNOME. Changes that you make " "will take effect immediately.\n\n" "Note that not all configuration options " "are listed here. You may want to edit %s " "if you cannot find what you are looking for.\n\n" "For complete documentation see the GNOME help browser " "under the \"Desktop\" category."), config_file); gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); g_signal_connect (G_OBJECT (dlg), "destroy", G_CALLBACK (gtk_widget_destroyed), &dlg); g_signal_connect_swapped (G_OBJECT (dlg), "response", G_CALLBACK (gtk_widget_destroy), dlg); gtk_widget_show (dlg); } } static void add_to_size_group (GtkSizeGroup *sg, const char *wid) { GtkWidget *w = glade_helper_get (xml, wid, GTK_TYPE_WIDGET); gtk_size_group_add_widget (sg, w); } static void setup_gui (void) { GtkWidget *dialog; GtkSizeGroup *sg; GtkWidget *label_welcome; GtkWidget *label_remote_welcome; gchar *GdmDefaultWelcome; gchar *GdmDefaultRemoteWelcome; xml = glade_helper_load ("gdmsetup.glade", "setup_dialog", GTK_TYPE_DIALOG, TRUE /* dump_on_destroy */); dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_DIALOG); label_welcome = glade_helper_get (xml, "sg_defaultwelcomelabel", GTK_TYPE_WIDGET); label_remote_welcome = glade_helper_get (xml, "sg_defaultremotewelcomelabel", GTK_TYPE_WIDGET); g_signal_connect (G_OBJECT (dialog), "delete_event", G_CALLBACK (delete_event), NULL); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (dialog_response), NULL); /* setup bold thingies */ glade_helper_tagify_label (xml, "greeter_cat_label", "b"); glade_helper_tagify_label (xml, "autologin_cat_label", "b"); glade_helper_tagify_label (xml, "timedlogin_cat_label", "b"); glade_helper_tagify_label (xml, "sg_logo_cat_label", "b"); glade_helper_tagify_label (xml, "sg_background_cat_label", "b"); glade_helper_tagify_label (xml, "options_cat_label", "b"); glade_helper_tagify_label (xml, "gg_preview_cat_label", "b"); glade_helper_tagify_label (xml, "gg_author_label", "b"); glade_helper_tagify_label (xml, "gg_desc_label", "b"); glade_helper_tagify_label (xml, "gg_copyright_label", "b"); glade_helper_tagify_label (xml, "acc_options_cat_label", "b"); glade_helper_tagify_label (xml, "xserver_cat_label", "b"); setup_accessibility_support (); setup_xdmcp_support (); setup_background_support (); setup_greeter_backselect (); setup_graphical_themes (); setup_xserver_support (); sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); add_to_size_group (sg, "local_greeter"); add_to_size_group (sg, "remote_greeter"); add_to_size_group (sg, "welcome"); add_to_size_group (sg, "remote_welcome"); add_to_size_group (sg, "autologin_combo"); add_to_size_group (sg, "timedlogin_combo"); add_to_size_group (sg, "timedlogin_seconds"); g_object_unref (G_OBJECT (sg)); sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); add_to_size_group (sg, "local_greeter_label"); add_to_size_group (sg, "remote_greeter_label"); add_to_size_group (sg, "welcome_label"); add_to_size_group (sg, "remote_welcome_label"); add_to_size_group (sg, "autologin_label"); add_to_size_group (sg, "timed_login_label"); add_to_size_group (sg, "timedlogin_seconds_label"); g_object_unref (G_OBJECT (sg)); sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); add_to_size_group (sg, "greeter_table"); add_to_size_group (sg, "autologin_table"); add_to_size_group (sg, "timed_login_table"); g_object_unref (G_OBJECT (sg)); sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); add_to_size_group (sg, "autologin"); add_to_size_group (sg, "timedlogin"); g_object_unref (G_OBJECT (sg)); /* Note: Just setting up a notify here doesn't mean things will get updated. You must also wire in the logic for update in the daemon and/or greeters (or chooser) or whereever this is actually being updated. */ /* General */ setup_user_combobox ("autologin_combo", GDM_KEY_AUTOMATICLOGIN); setup_user_combobox ("timedlogin_combo", GDM_KEY_TIMED_LOGIN); setup_notify_toggle ("autologin", GDM_KEY_AUTOMATICLOGIN_ENABLE, NULL /* notify_key */); setup_notify_toggle ("timedlogin", GDM_KEY_TIMED_LOGIN_ENABLE, GDM_KEY_TIMED_LOGIN_ENABLE /* notify_key */); /* Security */ setup_notify_toggle ("allowroot", GDM_KEY_ALLOWROOT, GDM_KEY_ALLOWROOT /* notify_key */); setup_notify_toggle ("allowremoteroot", GDM_KEY_ALLOWREMOTEROOT, GDM_KEY_ALLOWREMOTEROOT /* notify_key */); setup_notify_toggle ("allowremoteauto", GDM_KEY_ALLOWREMOTEAUTOLOGIN, GDM_KEY_ALLOWREMOTEAUTOLOGIN /* notify_key */); setup_notify_toggle ("sysmenu", GDM_KEY_SYSMENU, GDM_KEY_SYSMENU /* notify_key */); setup_notify_toggle ("config_available", GDM_KEY_CONFIG_AVAILABLE, GDM_KEY_CONFIG_AVAILABLE /* notify_key */); setup_notify_toggle ("chooser_button", GDM_KEY_CHOOSER_BUTTON, GDM_KEY_CHOOSER_BUTTON /* notify_key */); setup_notify_toggle ("disallow_tcp", GDM_KEY_DISALLOWTCP, GDM_KEY_DISALLOWTCP /* notify_key */); /* General */ GdmDefaultWelcome = g_strdup (_(GDM_DEFAULT_WELCOME_MSG)); GdmDefaultRemoteWelcome = g_strdup (_(GDM_DEFAULT_REMOTEWELCOME_MSG)); gtk_label_set_text (GTK_LABEL (label_welcome), GdmDefaultWelcome); gtk_label_set_text (GTK_LABEL (label_remote_welcome), GdmDefaultRemoteWelcome); /* Security */ setup_sensitivity_positive_toggle ("sysmenu", "config_available"); setup_sensitivity_positive_toggle ("sysmenu", "chooser_button"); setup_notify_toggle ("enable_debug", GDM_KEY_DEBUG, GDM_KEY_DEBUG /* notify_key */); setup_notify_toggle ("enable_xdmcp", GDM_KEY_XDMCP, GDM_KEY_XDMCP /* notify_key */); setup_notify_toggle ("honour_indirect", GDM_KEY_INDIRECT, "xdmcp/PARAMETERS" /* notify_key */); setup_intspin ("timedlogin_seconds", GDM_KEY_TIMED_LOGIN_DELAY, GDM_KEY_TIMED_LOGIN_DELAY /* notify_key */); setup_intspin ("retry_delay", GDM_KEY_RETRYDELAY, GDM_KEY_RETRYDELAY /* notify_key */); setup_intspin ("udpport", GDM_KEY_UDPPORT, GDM_KEY_UDPPORT /* notify_key */); setup_intspin ("maxpending", GDM_KEY_MAXPEND, "xdmcp/PARAMETERS" /* notify_key */); setup_intspin ("maxpendingindirect", GDM_KEY_MAXINDIR, "xdmcp/PARAMETERS" /* notify_key */); setup_intspin ("maxremotesessions", GDM_KEY_MAXSESS, "xdmcp/PARAMETERS" /* notify_key */); setup_intspin ("maxwait", GDM_KEY_MAXWAIT, "xdmcp/PARAMETERS" /* notify_key */); setup_intspin ("maxwaitindirect", GDM_KEY_MAXINDWAIT, "xdmcp/PARAMETERS" /* notify_key */); setup_intspin ("displaysperhost", GDM_KEY_DISPERHOST, "xdmcp/PARAMETERS" /* notify_key */); setup_intspin ("pinginterval", GDM_KEY_PINGINTERVAL, "xdmcp/PARAMETERS" /* notify_key */); setup_greeter_toggle ("fb_browser", GDM_KEY_BROWSER); /* General */ setup_greeter_combobox ("local_greeter", GDM_KEY_GREETER); setup_greeter_combobox ("remote_greeter", GDM_KEY_REMOTEGREETER); /* Greeter */ setup_greeter_toggle ("sg_scale_background", GDM_KEY_BACKGROUNDSCALETOFIT); setup_greeter_toggle ("sg_remote_color_only", GDM_KEY_BACKGROUNDREMOTEONLYCOLOR); setup_greeter_image (dialog); setup_greeter_color ("sg_backcolor", GDM_KEY_BACKGROUNDCOLOR); setup_greeter_toggle ("sg_defaultwelcome", GDM_KEY_DEFAULT_WELCOME); setup_greeter_toggle ("sg_defaultremotewelcome", GDM_KEY_DEFAULT_REMOTEWELCOME); setup_greeter_untranslate_entry ("welcome", GDM_KEY_WELCOME); setup_greeter_untranslate_entry ("remote_welcome", GDM_KEY_REMOTEWELCOME); /* Accesibility */ setup_greeter_toggle ("acc_theme", GDM_KEY_ALLOW_GTK_THEME_CHANGE); setup_greeter_toggle ("acc_sound_ready", GDM_KEY_SOUND_ON_LOGIN_READY); setup_greeter_toggle ("acc_sound_success", GDM_KEY_SOUND_ON_LOGIN_SUCCESS); setup_greeter_toggle ("acc_sound_failure", GDM_KEY_SOUND_ON_LOGIN_FAILURE); /* Face browser */ setup_greeter_toggle ("fb_allusers", GDM_KEY_INCLUDEALL); setup_face (); } static gboolean get_sensitivity (void) { static Atom atom = 0; Display *disp = gdk_x11_get_default_xdisplay (); Window root = gdk_x11_get_default_root_xwindow (); unsigned char *datac; gulong *data; gulong nitems_return; gulong bytes_after_return; Atom type_returned; int format_returned; if (atom == 0) atom = XInternAtom (disp, "_GDM_SETUP_INSENSITIVE", False); if (XGetWindowProperty (disp, root, atom, 0, 1, False, XA_CARDINAL, &type_returned, &format_returned, &nitems_return, &bytes_after_return, &datac) != Success) return TRUE; data = (gulong *)datac; if (format_returned != 32 || data[0] == 0) { XFree (data); return TRUE; } else { XFree (data); return FALSE; } } static void update_sensitivity (void) { gboolean sensitive = get_sensitivity (); GtkWidget *setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); gtk_widget_set_sensitive (setup_dialog, sensitive); if (sensitive) unsetup_window_cursor (); else setup_window_cursor (GDK_WATCH); } static GdkFilterReturn root_window_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) { XEvent *xevent = (XEvent *)gdk_xevent; if (xevent->type == PropertyNotify) update_sensitivity (); return GDK_FILTER_CONTINUE; } static void setup_disable_handler (void) { XWindowAttributes attribs = { 0, }; Display *disp = gdk_x11_get_default_xdisplay (); Window root = gdk_x11_get_default_root_xwindow (); update_sensitivity (); /* set event mask for events on root window */ XGetWindowAttributes (disp, root, &attribs); XSelectInput (disp, root, attribs.your_event_mask | PropertyChangeMask); gdk_window_add_filter (gdk_get_default_root_window (), root_window_filter, NULL); } static gboolean gdm_event (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer data) { GdkEvent *event; /* HAAAAAAAAAAAAAAAAACK */ /* Since the user has not logged in yet and may have left/right * mouse buttons switched, we just translate every right mouse click * to a left mouse click */ if (n_param_values != 2 || !G_VALUE_HOLDS (¶m_values[1], GDK_TYPE_EVENT)) return FALSE; event = g_value_get_boxed (¶m_values[1]); if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) && event->button.button == 3) event->button.button = 1; return TRUE; } struct poptOption options [] = { { "config", 'c', POPT_ARG_STRING, &config_file, 0, N_("Alternative configuration file"), N_("CONFIGFILE") }, { NULL, 0, 0, NULL, 0} }; int main (int argc, char *argv[]) { GnomeProgram *program; poptContext ctx; if (g_getenv ("DOING_GDM_DEVELOPMENT") != NULL) DOING_GDM_DEVELOPMENT = TRUE; if (g_getenv ("RUNNING_UNDER_GDM") != NULL) RUNNING_UNDER_GDM = TRUE; bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); program = gnome_program_init ("gdmsetup", VERSION, LIBGNOMEUI_MODULE /* module_info */, argc, argv, GNOME_PROGRAM_STANDARD_PROPERTIES, GNOME_PARAM_POPT_TABLE, options, GNOME_PARAM_CREATE_DIRECTORIES, ! RUNNING_UNDER_GDM, NULL); g_object_get (G_OBJECT (program), GNOME_PARAM_POPT_CONTEXT, &ctx, NULL); glade_gnome_init(); /* It is not null if config file location is passed in via command line */ if (config_file == NULL) { config_file = gdm_common_get_config_file (); if (config_file == NULL) { g_print (_("Could not access GDM configuration file.\n")); exit (EXIT_FAILURE); } } gdm_running = gdmcomm_check (config_file, FALSE /* gui_bitching */); if (RUNNING_UNDER_GDM) { char *gtkrc; char *theme_name; /* Set busy cursor */ setup_cursor (GDK_WATCH); /* parse the given gtk rc first */ gtkrc = ve_config_get_string (ve_config_get (config_file), GDM_KEY_GTKRC); if ( ! ve_string_empty (gtkrc)) gtk_rc_parse (gtkrc); g_free (gtkrc); theme_name = g_strdup (g_getenv ("GDM_GTK_THEME")); if (ve_string_empty (theme_name)) { g_free (theme_name); theme_name = ve_config_get_string (ve_config_get (config_file), GDM_KEY_GTK_THEME); } if ( ! ve_string_empty (theme_name)) { gdm_set_theme (theme_name); } /* evil, but oh well */ g_type_class_ref (GTK_TYPE_WIDGET); } glade_helper_add_glade_directory (GDM_GLADE_DIR); /* Make sure the user is root. If not, they shouldn't be messing with * GDM's configuration. */ if ( ! DOING_GDM_DEVELOPMENT && geteuid() != 0) { GtkWidget *fatal_error = ve_hig_dialog_new (NULL /* parent */, GTK_DIALOG_MODAL /* flags */, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("You must be the root user to configure GDM."), ""); if (RUNNING_UNDER_GDM) setup_cursor (GDK_LEFT_PTR); gtk_dialog_run (GTK_DIALOG (fatal_error)); exit (EXIT_FAILURE); } /* XXX: the setup proggie using a greeter config var for it's * ui? Say it ain't so. Our config sections are SUCH A MESS */ GdmIconMaxHeight = ve_config_get_int (ve_config_get (config_file), GDM_KEY_ICONHEIGHT); GdmIconMaxWidth = ve_config_get_int (ve_config_get (config_file), GDM_KEY_ICONWIDTH); GdmMinimalUID = ve_config_get_int (ve_config_get (config_file), GDM_KEY_MINIMALUID); GdmIncludeAll = ve_config_get_bool (ve_config_get (config_file), GDM_KEY_INCLUDEALL); GdmInclude = ve_config_get_string (ve_config_get (config_file), GDM_KEY_INCLUDE); GdmExclude = ve_config_get_string (ve_config_get (config_file), GDM_KEY_EXCLUDE); GdmSoundProgram = ve_config_get_string (ve_config_get (config_file), GDM_KEY_SOUND_PROGRAM); GdmAllowRoot = ve_config_get_bool (ve_config_get (config_file), GDM_KEY_ALLOWROOT); GdmAllowRemoteRoot = ve_config_get_bool (ve_config_get (config_file), GDM_KEY_ALLOWREMOTEROOT); if (ve_string_empty (GdmSoundProgram) || access (GdmSoundProgram, X_OK) != 0) { g_free (GdmSoundProgram); GdmSoundProgram = NULL; } setup_gui (); if (RUNNING_UNDER_GDM) { guint sid; /* also setup third button to work as first to work in reverse situations transparently */ sid = g_signal_lookup ("event", GTK_TYPE_WIDGET); g_signal_add_emission_hook (sid, 0 /* detail */, gdm_event, NULL /* data */, NULL /* destroy_notify */); setup_disable_handler (); setup_cursor (GDK_LEFT_PTR); } gtk_main (); return 0; } /* EOF */