/* 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 "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vicious.h" #include "viciousui.h" #include "gdm.h" #include "gdmcommon.h" #include "misc.h" #include "gdmcomm.h" #include "gdmuser.h" #include "gdmconfig.h" static char *GdmSoundProgram = NULL; static gchar *GdmExclude = NULL; static gchar *GdmInclude = NULL; static gint GdmMinimalUID = 100; static gint GdmIconMaxHeight; static gint GdmIconMaxWidth; static gboolean GdmIncludeAll; static gboolean GdmAllowRoot; static gboolean GdmAllowRemoteRoot; static gboolean GdmUserChangesUnsaved; /* 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; static gboolean gdm_running = FALSE; static GladeXML *xml; static GladeXML *xml_add_users; static GladeXML *xml_add_xservers; static GladeXML *xml_xdmcp; static GladeXML *xml_xservers; static GtkWidget *setup_notebook; static GList *timeout_widgets = NULL; static gchar *last_theme_installed = NULL; static char *selected_themes = NULL; static char *selected_theme = NULL; static gchar *config_file; static gchar *custom_config_file; static GSList *xservers; 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_SCREENSHOT, THEME_COLUMN_MARKUP, THEME_COLUMN_NAME, THEME_COLUMN_DESCRIPTION, THEME_COLUMN_AUTHOR, THEME_COLUMN_COPYRIGHT, THEME_NUM_COLUMNS }; enum { USERLIST_NAME, USERLIST_NUM_COLUMNS }; enum { ONE_THEME, RANDOM_THEME }; enum { LOCAL_TAB, REMOTE_TAB, ACCESSIBILITY_TAB, SECURITY_TAB, USERS_TAB }; enum { LOCAL_PLAIN, LOCAL_PLAIN_WITH_FACE, LOCAL_THEMED }; enum { REMOTE_DISABLED, REMOTE_SAME_AS_LOCAL, REMOTE_PLAIN = 2, REMOTE_THEMED = 2, REMOTE_PLAIN_WITH_FACE = 3 }; enum { XSERVER_LAUNCH_GREETER, XSERVER_LAUNCH_CHOOSER }; enum { BACKGROUND_NONE, BACKGROUND_IMAGE_AND_COLOR, BACKGROUND_COLOR, BACKGROUND_IMAGE }; static GtkTargetEntry target_table[] = { { "text/uri-list", 0, 0 } }; static guint n_targets = sizeof (target_table) / sizeof (target_table[0]); 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 (FALSE); 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 *key) { if (key == NULL) return; /* recheck for gdm */ gdm_running = gdmcomm_check (FALSE); if (gdm_running) { char *ret; char *s = g_strdup_printf ("%s %s", GDM_SUP_UPDATE_CONFIG, key); ret = gdmcomm_call_gdm (s, NULL /* auth_cookie */, "2.3.90.2", 5); g_free (s); g_free (ret); } } static void gdm_setup_config_set_bool (const char *key, gboolean val) { VeConfig *cfg = ve_config_get (config_file); VeConfig *custom_cfg = ve_config_get (custom_config_file); gboolean defaultval = ve_config_get_bool (cfg, key); if (val == defaultval) { ve_config_delete_key (custom_cfg, key); } else { ve_config_set_bool (custom_cfg, key, val); } ve_config_save (custom_cfg, FALSE /* force */); update_key (key); } static void gdm_setup_config_set_int (const char *key, int val) { VeConfig *cfg = ve_config_get (config_file); VeConfig *custom_cfg = ve_config_get (custom_config_file); int defaultval = ve_config_get_int (cfg, key); if (val == defaultval) { ve_config_delete_key (custom_cfg, key); } else { ve_config_set_int (custom_cfg, key, val); } ve_config_save (custom_cfg, FALSE /* force */); update_key (key); } static void gdm_setup_config_set_string (const char *key, gchar *val) { VeConfig *cfg = ve_config_get (config_file); VeConfig *custom_cfg = ve_config_get (custom_config_file); gchar *defaultval = ve_config_get_string (cfg, key); if (defaultval != NULL && strcmp (ve_sure_string (val), ve_sure_string (defaultval)) == 0) { ve_config_delete_key (custom_cfg, key); } else { ve_config_set_string (custom_cfg, key, val); } if (defaultval) g_free (defaultval); ve_config_save (custom_cfg, FALSE /* force */); update_key (key); } static gboolean toggle_timeout (GtkWidget *toggle) { const char *key = g_object_get_data (G_OBJECT (toggle), "key"); gboolean val = gdm_config_get_bool ((gchar *)key); if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) { gdm_setup_config_set_bool (key, GTK_TOGGLE_BUTTON (toggle)->active); } return FALSE; } static gboolean logo_toggle_timeout (GtkWidget *toggle) { const char *key = g_object_get_data (G_OBJECT (toggle), "key"); GtkWidget *chooserbutton; gchar *filename; chooserbutton = glade_helper_get (xml, "local_logo_image_chooserbutton", GTK_TYPE_FILE_CHOOSER_BUTTON); filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooserbutton)); if ((GTK_TOGGLE_BUTTON (toggle)->active) == FALSE) { gdm_setup_config_set_string (GDM_KEY_CHOOSER_BUTTON_LOGO, filename); gdm_setup_config_set_string (key, ""); } else if (filename != NULL) { gdm_setup_config_set_string (GDM_KEY_CHOOSER_BUTTON_LOGO, filename); gdm_setup_config_set_string (key, filename); } update_greeters (); g_free (filename); return FALSE; } static void logo_toggle_toggled (GtkWidget *toggle, gpointer data) { if (gtk_notebook_get_current_page (GTK_NOTEBOOK (setup_notebook)) == LOCAL_TAB) { GtkWidget *checkbutton; checkbutton = glade_helper_get (xml, "remote_logo_image_checkbutton", GTK_TYPE_CHECK_BUTTON); g_signal_handlers_disconnect_by_func (checkbutton, (gpointer) logo_toggle_toggled, NULL); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), GTK_TOGGLE_BUTTON (toggle)->active); g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (logo_toggle_toggled), NULL); } else { GtkWidget *checkbutton; checkbutton = glade_helper_get (xml, "local_logo_image_checkbutton", GTK_TYPE_CHECK_BUTTON); g_signal_handlers_disconnect_by_func (checkbutton, (gpointer) logo_toggle_toggled, NULL); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), GTK_TOGGLE_BUTTON (toggle)->active); g_signal_connect (G_OBJECT (checkbutton), "toggled", G_CALLBACK (logo_toggle_toggled), NULL); } run_timeout (toggle, 200, logo_toggle_timeout); } static gboolean intspin_timeout (GtkWidget *spin) { const char *key = g_object_get_data (G_OBJECT (spin), "key"); int new_val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin)); int val; val = gdm_config_get_int ((gchar *)key); if (val != new_val) gdm_setup_config_set_int (key, new_val); return FALSE; } static gint display_sort_func (gpointer d1, gpointer d2) { return (strcmp (ve_sure_string ((gchar *)d1), ve_sure_string ((gchar *)d2))); } static GSList *displays = NULL; static GSList *displays_inactive = NULL; static GHashTable *dispval_hash = NULL; static void gdm_load_displays (VeConfig *cfg, GList *list ) { GList *li; GSList *li2; for (li = list; li != NULL; li = li->next) { const gchar *key = li->data; if (isdigit (*key)) { gchar *fullkey; gchar *dispval; int keynum = atoi (key); gboolean skip_entry = FALSE; fullkey = g_strdup_printf ("%s/%s", GDM_KEY_SECTION_SERVERS, key); dispval = ve_config_get_string (cfg, fullkey); g_free (fullkey); /* Do not add if already in the list */ for (li2 = displays; li2 != NULL; li2 = li2->next) { gchar *disp = li2->data; if (atoi (disp) == keynum) { skip_entry = TRUE; break; } } /* Do not add if this display was marked as inactive already */ for (li2 = displays_inactive; li2 != NULL; li2 = li2->next) { gchar *disp = li2->data; if (atoi (disp) == keynum) { skip_entry = TRUE; break; } } if (skip_entry == TRUE) { g_free (dispval); continue; } if (g_ascii_strcasecmp (ve_sure_string (dispval), "inactive") == 0) { displays_inactive = g_slist_append (displays_inactive, g_strdup (key)); } else { if (dispval_hash == NULL) dispval_hash = g_hash_table_new (g_str_hash, g_str_equal); displays = g_slist_insert_sorted (displays, g_strdup (key), (GCompareFunc) display_sort_func); g_hash_table_insert (dispval_hash, g_strdup (key), g_strdup (dispval)); } g_free (dispval); } } } static void xservers_get_displays (GtkListStore *store) { /* Find server definitions */ VeConfig *custom_cfg = ve_config_get (custom_config_file); VeConfig *cfg = ve_config_get (config_file); GList *list; GSList *li; gchar *server, *options; /* Fill list with all the active displays */ if (custom_cfg) { list = ve_config_get_keys (custom_cfg, GDM_KEY_SECTION_SERVERS); gdm_load_displays (custom_cfg, list); ve_config_free_list_of_strings (list); } list = ve_config_get_keys (cfg, GDM_KEY_SECTION_SERVERS); gdm_load_displays (cfg, list); ve_config_free_list_of_strings (list); for (li = displays; li != NULL; li = li->next) { GtkTreeIter iter; gchar *key = li->data; int vt = atoi (key); server = ve_first_word (g_hash_table_lookup (dispval_hash, key)); options = ve_rest (g_hash_table_lookup (dispval_hash, key)); 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); } for (li = displays; li != NULL; li = li->next) { gchar *disp = li->data; g_free (disp); } g_slist_free (displays); displays = NULL; for (li = displays_inactive; li != NULL; li = li->next) { gchar *disp = li->data; g_free (disp); } g_slist_free (displays_inactive); displays_inactive = NULL; if (dispval_hash) { g_hash_table_destroy (dispval_hash); dispval_hash = NULL; } } static void xserver_update_delete_sensitivity () { GtkWidget *modify_combobox, *delete_button; GtkListStore *store; GtkTreeIter iter; GdmXserver *xserver; gchar *text; gchar *selected; gboolean valid; gint i; modify_combobox = glade_helper_get (xml_xservers, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); delete_button = glade_helper_get (xml_xservers, "xserver_deletebutton", 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 */); /* Get list of servers and determine which one was selected */ xservers_get_displays (store); 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 last 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 (ve_sure_string (text), ve_sure_string (selected)) == 0) { gtk_widget_set_sensitive(delete_button, FALSE); break; } valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); } } } } static void init_servers_combobox (int index) { GtkWidget *mod_combobox; GtkWidget *name_entry; GtkWidget *command_entry; GtkWidget *style_combobox; GtkWidget *handled_checkbutton; GtkWidget *flexible_checkbutton; GtkListStore *store; GdmXserver *xserver; mod_combobox = glade_helper_get (xml_xservers, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); name_entry = glade_helper_get (xml_xservers, "xserver_name_entry", GTK_TYPE_ENTRY); command_entry = glade_helper_get (xml_xservers, "xserver_command_entry", GTK_TYPE_ENTRY); style_combobox = glade_helper_get (xml_xservers, "xserver_style_combobox", GTK_TYPE_COMBO_BOX); handled_checkbutton = glade_helper_get (xml_xservers, "xserver_handled_checkbutton", GTK_TYPE_CHECK_BUTTON); flexible_checkbutton = glade_helper_get (xml_xservers, "xserver_flexible_checkbutton", GTK_TYPE_CHECK_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_displays (store); xserver = g_slist_nth_data (xservers, index); gtk_combo_box_set_active (GTK_COMBO_BOX (mod_combobox), index); gtk_entry_set_text (GTK_ENTRY (name_entry), xserver->name); gtk_entry_set_text (GTK_ENTRY (command_entry), xserver->command); if (!xserver->chooser) { gtk_combo_box_set_active (GTK_COMBO_BOX (style_combobox), XSERVER_LAUNCH_GREETER); } else { gtk_combo_box_set_active (GTK_COMBO_BOX (style_combobox), XSERVER_LAUNCH_CHOOSER); } gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (handled_checkbutton), xserver->handled); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (flexible_checkbutton), xserver->flexible); xserver_update_delete_sensitivity (); } static void update_remote_sensitivity (gboolean value) { GtkWidget *remote_background_color_hbox; GtkWidget *remote_background_image_hhox; GtkWidget *remote_background_image_checkbutton; GtkWidget *remote_background_image_chooserbutton; GtkWidget *remote_logo_image_checkbutton; GtkWidget *remote_plain_logo_hbox; GtkWidget *remote_theme_background_hbox; GtkWidget *remote_theme_mode_hbox; GtkWidget *remote_theme_select_hbox; GtkWidget *sg_scale_background_remote_hbox; remote_background_color_hbox = glade_helper_get (xml, "remote_background_color_hbox", GTK_TYPE_HBOX); remote_background_image_hhox = glade_helper_get (xml, "remote_background_image_hhox", GTK_TYPE_HBOX); remote_background_image_checkbutton = glade_helper_get (xml, "remote_background_image_checkbutton", GTK_TYPE_CHECK_BUTTON); remote_background_image_chooserbutton = glade_helper_get (xml, "remote_background_image_chooserbutton", GTK_TYPE_FILE_CHOOSER_BUTTON); remote_logo_image_checkbutton = glade_helper_get (xml, "remote_logo_image_checkbutton", GTK_TYPE_CHECK_BUTTON); remote_plain_logo_hbox = glade_helper_get (xml, "remote_plain_logo_hbox", GTK_TYPE_HBOX); remote_theme_background_hbox = glade_helper_get (xml, "remote_theme_background_hbox", GTK_TYPE_TABLE); remote_theme_mode_hbox = glade_helper_get (xml, "remote_theme_mode_hbox", GTK_TYPE_HBOX); remote_theme_select_hbox = glade_helper_get (xml, "remote_theme_select_hbox", GTK_TYPE_HBOX); sg_scale_background_remote_hbox = glade_helper_get (xml, "sg_scale_background_remote_hbox", GTK_TYPE_HBOX); gtk_widget_set_sensitive (remote_background_color_hbox, value); gtk_widget_set_sensitive (remote_background_image_hhox, value); gtk_widget_set_sensitive (remote_background_image_checkbutton, value); gtk_widget_set_sensitive (remote_background_image_chooserbutton, value); gtk_widget_set_sensitive (remote_logo_image_checkbutton, value); gtk_widget_set_sensitive (remote_plain_logo_hbox, value); gtk_widget_set_sensitive (remote_theme_background_hbox, value); gtk_widget_set_sensitive (remote_theme_mode_hbox, value); gtk_widget_set_sensitive (remote_theme_select_hbox, value); gtk_widget_set_sensitive (sg_scale_background_remote_hbox, value); } static void refresh_remote_tab (void) { GtkWidget *local_greeter; GtkWidget *remote_greeter; GtkWidget *remote_plain_vbox; GtkWidget *remote_themed_vbox; GtkWidget *configure_xdmcp_vbox; GtkWidget *welcome_message_vbox; GtkWidget *allowremoteroot; GtkWidget *allowremoteauto; gchar *remote_style; gint local_style; local_greeter = glade_helper_get (xml, "local_greeter", GTK_TYPE_COMBO_BOX); remote_greeter = glade_helper_get (xml, "remote_greeter", GTK_TYPE_COMBO_BOX); remote_plain_vbox = glade_helper_get (xml, "remote_plain_properties_vbox", GTK_TYPE_VBOX); remote_themed_vbox = glade_helper_get (xml, "remote_themed_properties_vbox", GTK_TYPE_VBOX); configure_xdmcp_vbox = glade_helper_get (xml, "remote_configure_xdmcp_vbox", GTK_TYPE_VBOX); welcome_message_vbox = glade_helper_get (xml, "remote_welcome_message_vbox", GTK_TYPE_VBOX); allowremoteroot = glade_helper_get (xml, "allowremoteroot", GTK_TYPE_BUTTON); allowremoteauto = glade_helper_get (xml, "allowremoteauto", GTK_TYPE_CHECK_BUTTON); /* Remove previously added items from the combobox */ gtk_combo_box_remove_text (GTK_COMBO_BOX (remote_greeter), REMOTE_PLAIN_WITH_FACE); gtk_combo_box_remove_text (GTK_COMBO_BOX (remote_greeter), REMOTE_PLAIN); local_style = gtk_combo_box_get_active (GTK_COMBO_BOX (local_greeter)); remote_style = gdm_config_get_string (GDM_KEY_REMOTE_GREETER); if (gdm_config_get_bool (GDM_KEY_XDMCP) == FALSE) { if (local_style == LOCAL_PLAIN || local_style == LOCAL_PLAIN_WITH_FACE) { gtk_combo_box_append_text (GTK_COMBO_BOX (remote_greeter), _("Themed")); } else { gtk_combo_box_append_text (GTK_COMBO_BOX (remote_greeter), _("Plain")); gtk_combo_box_append_text (GTK_COMBO_BOX (remote_greeter), _("Plain with face browser")); } gtk_combo_box_set_active (GTK_COMBO_BOX (remote_greeter), REMOTE_DISABLED); gtk_widget_set_sensitive (allowremoteroot, FALSE); gtk_widget_set_sensitive (allowremoteauto, FALSE); gtk_widget_hide (remote_plain_vbox); gtk_widget_hide (remote_themed_vbox); gtk_widget_hide (welcome_message_vbox); gtk_widget_hide (configure_xdmcp_vbox); } else { if (local_style == LOCAL_PLAIN || local_style == LOCAL_PLAIN_WITH_FACE) { gtk_combo_box_append_text (GTK_COMBO_BOX (remote_greeter), _("Themed")); if (strstr (remote_style, "/gdmlogin") != NULL) { gtk_combo_box_set_active (GTK_COMBO_BOX (remote_greeter), REMOTE_SAME_AS_LOCAL); update_remote_sensitivity (FALSE); gtk_widget_show (remote_plain_vbox); gtk_widget_hide (remote_themed_vbox); } else if (strstr (remote_style, "/gdmgreeter") != NULL) { gtk_combo_box_set_active (GTK_COMBO_BOX (remote_greeter), REMOTE_THEMED); update_remote_sensitivity (TRUE); gtk_widget_hide (remote_plain_vbox); gtk_widget_show (remote_themed_vbox); } } else { gtk_combo_box_append_text (GTK_COMBO_BOX (remote_greeter), _("Plain")); gtk_combo_box_append_text (GTK_COMBO_BOX (remote_greeter), _("Plain with face browser")); if (strstr (remote_style, "/gdmlogin") != NULL) { gboolean use_browser; use_browser = gdm_config_get_bool (GDM_KEY_BROWSER); if (use_browser == FALSE) { gtk_combo_box_set_active (GTK_COMBO_BOX (remote_greeter), REMOTE_PLAIN); } else { gtk_combo_box_set_active (GTK_COMBO_BOX (remote_greeter), REMOTE_PLAIN_WITH_FACE); } update_remote_sensitivity (TRUE); gtk_widget_hide (remote_themed_vbox); gtk_widget_show (remote_plain_vbox); } else if (strstr (remote_style, "/gdmgreeter") != NULL) { gtk_combo_box_set_active (GTK_COMBO_BOX (remote_greeter), REMOTE_SAME_AS_LOCAL); update_remote_sensitivity (FALSE); gtk_widget_hide (remote_plain_vbox); gtk_widget_show (remote_themed_vbox); } } gtk_widget_set_sensitive (allowremoteauto, gdm_config_get_bool (GDM_KEY_XDMCP)); gtk_widget_set_sensitive (allowremoteroot, TRUE); gtk_widget_show (welcome_message_vbox); gtk_widget_show (configure_xdmcp_vbox); } } /* * We probably should check the server definition in the defaults.conf file * and just erase the section if the values are the same, like we do for the * displays section and the normal configuration sections. */ static void update_xserver (gchar *section, GdmXserver *svr) { VeConfig *custom_cfg = ve_config_get (custom_config_file); gchar *real_section = g_strdup_printf ("%s%s", GDM_KEY_SERVER_PREFIX, section); gchar *key; key = g_strconcat (real_section, "/" GDM_KEY_SERVER_NAME, NULL); ve_config_set_string (custom_cfg, key, svr->name); g_free (key); key = g_strconcat (real_section, "/" GDM_KEY_SERVER_COMMAND, NULL); ve_config_set_string (custom_cfg, key, svr->command); g_free (key); key = g_strconcat (real_section, "/", GDM_KEY_SERVER_CHOOSER, NULL); ve_config_set_bool (custom_cfg, key, svr->chooser); g_free (key); key = g_strconcat (real_section, "/" GDM_KEY_SERVER_HANDLED, NULL); ve_config_set_bool (custom_cfg, key, svr->handled); g_free (key); key = g_strconcat (real_section, "/" GDM_KEY_SERVER_FLEXIBLE, NULL); ve_config_set_bool (custom_cfg, key, svr->flexible); g_free (key); key = g_strconcat (real_section, "/" GDM_KEY_SERVER_PRIORITY, NULL); ve_config_set_int (custom_cfg, key, svr->priority); g_free (key); g_free (real_section); ve_config_save (custom_cfg, FALSE); update_key ("xservers/PARAMETERS"); } 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)); /* Local Greeter Comboboxes */ if (strcmp (ve_sure_string (key), GDM_KEY_GREETER) == 0) { gchar *old_key_val; gchar *new_key_val; gboolean browser_val; old_key_val = gdm_config_get_string ((gchar *)key); new_key_val = NULL; if (selected == LOCAL_PLAIN_WITH_FACE) { new_key_val = g_strdup (LIBEXECDIR "/gdmlogin"); browser_val = TRUE; } else if (selected == LOCAL_THEMED) { new_key_val = g_strdup (LIBEXECDIR "/gdmgreeter"); browser_val = gdm_config_get_bool (GDM_KEY_BROWSER); } else { /* Plain style */ new_key_val = g_strdup (LIBEXECDIR "/gdmlogin"); browser_val = FALSE; } if (new_key_val && strcmp (ve_sure_string (old_key_val), ve_sure_string (new_key_val)) != 0) { gdm_setup_config_set_string (key, new_key_val); gdm_setup_config_set_bool (GDM_KEY_BROWSER, browser_val); } else { gdm_setup_config_set_bool (GDM_KEY_BROWSER, browser_val); } update_greeters (); refresh_remote_tab (); g_free (new_key_val); } /* Remote Greeter Comboboxes */ else if (strcmp (ve_sure_string (key), GDM_KEY_REMOTE_GREETER) == 0) { if (selected == REMOTE_DISABLED) { gdm_setup_config_set_bool (GDM_KEY_XDMCP, FALSE); } else { gchar *new_key_val = NULL; gboolean free_new_val = TRUE; if (selected == REMOTE_SAME_AS_LOCAL) { new_key_val = gdm_config_get_string (GDM_KEY_GREETER); free_new_val = FALSE; } else if (selected == REMOTE_PLAIN_WITH_FACE) { new_key_val = g_strdup (LIBEXECDIR "/gdmlogin"); gdm_setup_config_set_bool (GDM_KEY_BROWSER, TRUE); } else { gchar *selected_text; selected_text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (combo_box)); if (strcmp (ve_sure_string (selected_text), _("Themed")) == 0) { new_key_val = g_strdup (LIBEXECDIR "/gdmgreeter"); } else { new_key_val = g_strdup (LIBEXECDIR "/gdmlogin"); gdm_setup_config_set_bool (GDM_KEY_BROWSER, FALSE); } g_free (selected_text); } gdm_setup_config_set_string (key, new_key_val); gdm_setup_config_set_bool (GDM_KEY_XDMCP, TRUE); if (free_new_val) g_free (new_key_val); } update_greeters (); return FALSE; /* Automatic Login Combobox */ } else if (strcmp (ve_sure_string (key), GDM_KEY_AUTOMATIC_LOGIN) == 0 || strcmp (ve_sure_string (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 = gdm_config_get_string ((gchar *)key); if (new_val && strcmp (ve_sure_string (val), ve_sure_string (new_val)) != 0) { gdm_setup_config_set_string (key, new_val); } g_free (new_val); } else if (strcmp (ve_sure_string (key), GDM_KEY_GRAPHICAL_THEME_RAND) == 0 ) { /* Theme Combobox */ gboolean new_val; gboolean old_val ; old_val = gdm_config_get_bool ((gchar *)key); /* Choose to display radio or checkbox toggle column */ if (selected == RANDOM_THEME) new_val = TRUE; else /* Default to one theme */ new_val = FALSE; /* Update config */ if (new_val != old_val) gdm_setup_config_set_bool (key, new_val); } /* Style combobox */ else if (strcmp (ve_sure_string (key), GDM_KEY_SERVER_CHOOSER) == 0) { GtkWidget *mod_combobox; GtkWidget *style_combobox; GSList *li; gchar *section; gboolean val_old, val_new; mod_combobox = glade_helper_get (xml_xservers, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); style_combobox = glade_helper_get (xml_xservers, "xserver_style_combobox", GTK_TYPE_COMBO_BOX); /* Get xserver section to update */ section = gtk_combo_box_get_active_text (GTK_COMBO_BOX (mod_combobox)); for (li = xservers; li != NULL; li = li->next) { GdmXserver *svr = li->data; if (strcmp (ve_sure_string (svr->id), ve_sure_string (section)) == 0) { val_old = svr->chooser; val_new = (gtk_combo_box_get_active (GTK_COMBO_BOX (style_combobox)) != 0); /* Update this servers configuration */ if (! ve_bool_equal (val_old, val_new)) { svr->chooser = val_new; update_xserver (section, svr); } break; } } g_free (section); } return FALSE; } static void toggle_toggled (GtkWidget *toggle) { run_timeout (toggle, 200, toggle_timeout); } static void list_selection_toggled (GtkWidget *toggle, gpointer data) { GtkWidget *widget = data; GtkWidget *include_treeview; GtkTreeSelection *selection; GtkTreeModel *include_model; GtkTreeIter iter; gboolean val; val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)); include_treeview = glade_helper_get (xml, "fb_include_treeview", GTK_TYPE_TREE_VIEW); include_model = gtk_tree_view_get_model (GTK_TREE_VIEW (include_treeview)); selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (include_treeview)); if ((val == FALSE) && (gtk_tree_selection_get_selected (selection, &(include_model), &iter))) { 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) { const char *key = g_object_get_data (G_OBJECT (combobox), "key"); if (strcmp (ve_sure_string (key), GDM_KEY_GREETER) == 0) { GtkWidget *local_plain_vbox; GtkWidget *local_themed_vbox; gint selected; local_plain_vbox = glade_helper_get (xml, "local_plain_properties_vbox", GTK_TYPE_VBOX); local_themed_vbox = glade_helper_get (xml, "local_themed_properties_vbox", GTK_TYPE_VBOX); selected = gtk_combo_box_get_active (GTK_COMBO_BOX (combobox)); if (selected == LOCAL_PLAIN_WITH_FACE) { gtk_widget_show (local_plain_vbox); gtk_widget_hide (local_themed_vbox); } else if (selected == LOCAL_THEMED) { gtk_widget_hide (local_plain_vbox); gtk_widget_show (local_themed_vbox); } else { /* Plain style */ gtk_widget_show (local_plain_vbox); gtk_widget_hide (local_themed_vbox); } } else if (strcmp (ve_sure_string (key), GDM_KEY_REMOTE_GREETER) == 0) { GtkWidget *remote_plain_vbox; GtkWidget *remote_themed_vbox; GtkWidget *configure_xdmcp_vbox; GtkWidget *welcome_message_vbox; gint selected; remote_plain_vbox = glade_helper_get (xml, "remote_plain_properties_vbox", GTK_TYPE_VBOX); remote_themed_vbox = glade_helper_get (xml, "remote_themed_properties_vbox", GTK_TYPE_VBOX); configure_xdmcp_vbox = glade_helper_get (xml, "remote_configure_xdmcp_vbox", GTK_TYPE_VBOX); welcome_message_vbox = glade_helper_get (xml, "remote_welcome_message_vbox", GTK_TYPE_VBOX); selected = gtk_combo_box_get_active (GTK_COMBO_BOX (combobox)); if (selected == REMOTE_DISABLED) { GtkWidget *allowremoteauto; GtkWidget *allowremoteroot; allowremoteauto = glade_helper_get (xml, "allowremoteauto", GTK_TYPE_CHECK_BUTTON); allowremoteroot = glade_helper_get (xml, "allowremoteroot", GTK_TYPE_CHECK_BUTTON); gtk_widget_set_sensitive (allowremoteauto, FALSE); gtk_widget_set_sensitive (allowremoteroot, FALSE); gtk_widget_hide (remote_plain_vbox); gtk_widget_hide (remote_themed_vbox); gtk_widget_hide (welcome_message_vbox); gtk_widget_hide (configure_xdmcp_vbox); } else { GtkWidget *timedlogin; GtkWidget *allowremoteauto; GtkWidget *allowremoteroot; timedlogin = glade_helper_get (xml, "timedlogin", GTK_TYPE_CHECK_BUTTON); allowremoteauto = glade_helper_get (xml, "allowremoteauto", GTK_TYPE_CHECK_BUTTON); allowremoteroot = glade_helper_get (xml, "allowremoteroot", GTK_TYPE_CHECK_BUTTON); gtk_widget_set_sensitive (allowremoteauto, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (timedlogin))); gtk_widget_set_sensitive (allowremoteroot, TRUE); gtk_widget_show (welcome_message_vbox); gtk_widget_show (configure_xdmcp_vbox); if (selected == REMOTE_SAME_AS_LOCAL) { gchar *greeter_style; greeter_style = gdm_config_get_string (GDM_KEY_GREETER); update_remote_sensitivity (FALSE); if (strstr (greeter_style, "/gdmgreeter") != NULL) { gtk_widget_hide (remote_plain_vbox); gtk_widget_show (remote_themed_vbox); } else { gtk_widget_hide (remote_themed_vbox); gtk_widget_show (remote_plain_vbox); } } else if (selected == REMOTE_PLAIN_WITH_FACE) { update_remote_sensitivity (TRUE); gtk_widget_hide (remote_themed_vbox); gtk_widget_show (remote_plain_vbox); } else { gchar *selected_text; selected_text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (combobox)); update_remote_sensitivity (TRUE); if (strcmp (ve_sure_string (selected_text), _("Themed")) == 0) { gtk_widget_hide (remote_plain_vbox); gtk_widget_show (remote_themed_vbox); } else { gtk_widget_hide (remote_themed_vbox); gtk_widget_show (remote_plain_vbox); } g_free (selected_text); } } } else if (strcmp (ve_sure_string (key), GDM_KEY_GRAPHICAL_THEME_RAND) == 0) { GtkWidget *theme_list; GtkWidget *theme_list_remote; GtkWidget *delete_button; GtkWidget *delete_button_remote; GtkTreeViewColumn *radioColumn = NULL; GtkTreeViewColumn *radioColumnRemote = NULL; GtkTreeViewColumn *checkboxColumn = NULL; GtkTreeViewColumn *checkboxColumnRemote = NULL; GtkTreeSelection *selection; GtkTreeIter iter; gint selected; theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); theme_list_remote = glade_helper_get (xml, "gg_theme_list_remote", GTK_TYPE_TREE_VIEW); delete_button = glade_helper_get (xml, "gg_delete_theme", GTK_TYPE_BUTTON); delete_button_remote = glade_helper_get (xml, "gg_delete_theme_remote", GTK_TYPE_BUTTON); selected = gtk_combo_box_get_active (GTK_COMBO_BOX (combobox)); if (gtk_notebook_get_current_page (GTK_NOTEBOOK (setup_notebook)) == LOCAL_TAB) { GtkWidget *mode_combobox; mode_combobox = glade_helper_get (xml, "gg_mode_combobox_remote", GTK_TYPE_COMBO_BOX); gtk_combo_box_set_active (GTK_COMBO_BOX (mode_combobox), selected); } else { GtkWidget *mode_combobox; mode_combobox = glade_helper_get (xml, "gg_mode_combobox", GTK_TYPE_COMBO_BOX); gtk_combo_box_set_active (GTK_COMBO_BOX (mode_combobox), selected); } radioColumn = gtk_tree_view_get_column (GTK_TREE_VIEW (theme_list), THEME_COLUMN_SELECTED); radioColumnRemote = gtk_tree_view_get_column (GTK_TREE_VIEW (theme_list_remote), THEME_COLUMN_SELECTED); checkboxColumn = gtk_tree_view_get_column (GTK_TREE_VIEW (theme_list), THEME_COLUMN_SELECTED_LIST); checkboxColumnRemote = gtk_tree_view_get_column (GTK_TREE_VIEW (theme_list_remote), THEME_COLUMN_SELECTED_LIST); /* Choose to display radio or checkbox toggle column */ if (selected == RANDOM_THEME) { if (GTK_IS_TREE_VIEW_COLUMN (radioColumn)) gtk_tree_view_column_set_visible (radioColumn, FALSE); if (GTK_IS_TREE_VIEW_COLUMN (radioColumnRemote)) gtk_tree_view_column_set_visible (radioColumnRemote, FALSE); if (GTK_IS_TREE_VIEW_COLUMN (checkboxColumn)) gtk_tree_view_column_set_visible (checkboxColumn, TRUE); if (GTK_IS_TREE_VIEW_COLUMN (checkboxColumnRemote)) gtk_tree_view_column_set_visible (checkboxColumnRemote, TRUE); } else { /* Default to one theme */ if (GTK_IS_TREE_VIEW_COLUMN (radioColumn)) gtk_tree_view_column_set_visible (radioColumn, TRUE); if (GTK_IS_TREE_VIEW_COLUMN (radioColumnRemote)) gtk_tree_view_column_set_visible (radioColumnRemote, TRUE); if (GTK_IS_TREE_VIEW_COLUMN (checkboxColumn)) gtk_tree_view_column_set_visible (checkboxColumn, FALSE); if (GTK_IS_TREE_VIEW_COLUMN (checkboxColumnRemote)) gtk_tree_view_column_set_visible (checkboxColumnRemote, FALSE); } /* Update delete button's sensitivity */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) { gtk_widget_set_sensitive (delete_button, FALSE); gtk_widget_set_sensitive (delete_button_remote, FALSE); } else { GValue value = {0, }; GtkTreeModel *model; gboolean GdmGraphicalThemeRand; /* Determine if the theme selected is currently active */ model = gtk_tree_view_get_model (GTK_TREE_VIEW (theme_list)); GdmGraphicalThemeRand = gdm_config_get_bool (GDM_KEY_GRAPHICAL_THEME_RAND); 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); } if (g_value_get_boolean (&value)) { /* Do not allow deleting of active themes */ gtk_widget_set_sensitive (delete_button, FALSE); gtk_widget_set_sensitive (delete_button_remote, FALSE); } else { gtk_widget_set_sensitive (delete_button, TRUE); gtk_widget_set_sensitive (delete_button_remote, TRUE); } } } else if (strcmp (ve_sure_string (key), GDM_KEY_SERVER_PREFIX) == 0 ) { init_servers_combobox (gtk_combo_box_get_active (GTK_COMBO_BOX (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 toggle_toggled_sensitivity_positive (GtkWidget *toggle, GtkWidget *depend) { gtk_widget_set_sensitive (depend, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle))); } static void timedlogin_allow_remote_toggled (GtkWidget *toggle, GtkWidget *depend) { if (gdm_config_get_bool (GDM_KEY_XDMCP) == TRUE) { gtk_widget_set_sensitive (depend, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle))); } else { gtk_widget_set_sensitive (depend, FALSE); } } static void setup_notify_toggle (const char *name, const char *key) { GtkWidget *toggle; gboolean val; toggle = glade_helper_get (xml, name, GTK_TYPE_TOGGLE_BUTTON); val = gdm_config_get_bool ((gchar *)key); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), val); g_object_set_data_full (G_OBJECT (toggle), "key", g_strdup (key), (GDestroyNotify) g_free); if (strcmp (ve_sure_string (name), "sysmenu") == 0) { GtkWidget *config_available; GtkWidget *chooser_button; config_available = glade_helper_get (xml, "config_available", GTK_TYPE_CHECK_BUTTON); chooser_button = glade_helper_get (xml, "chooser_button", GTK_TYPE_CHECK_BUTTON); gtk_widget_set_sensitive (config_available, val); gtk_widget_set_sensitive (chooser_button, val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled), toggle); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), config_available); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), chooser_button); } else if (strcmp ("autologin", ve_sure_string (name)) == 0) { GtkWidget *autologin_label; GtkWidget *autologin_combo; autologin_label = glade_helper_get (xml, "autologin_label", GTK_TYPE_LABEL); autologin_combo = glade_helper_get (xml, "autologin_combo", GTK_TYPE_COMBO_BOX); gtk_widget_set_sensitive (autologin_label, val); gtk_widget_set_sensitive (autologin_combo, val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), autologin_label); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), autologin_combo); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled), toggle); } else if (strcmp ("timedlogin", ve_sure_string (name)) == 0) { GtkWidget *timedlogin_label; GtkWidget *timedlogin_combo; GtkWidget *timedlogin_seconds_label; GtkWidget *timedlogin_seconds_spin_button; GtkWidget *timedlogin_seconds_units; GtkWidget *timedlogin_allow_remote; timedlogin_label = glade_helper_get (xml, "timed_login_label", GTK_TYPE_LABEL); timedlogin_combo = glade_helper_get (xml, "timedlogin_combo", GTK_TYPE_COMBO_BOX); timedlogin_seconds_label = glade_helper_get (xml, "timedlogin_seconds_label", GTK_TYPE_LABEL); timedlogin_seconds_spin_button = glade_helper_get (xml,"timedlogin_seconds", GTK_TYPE_SPIN_BUTTON); timedlogin_seconds_units = glade_helper_get (xml,"timedlogin_seconds_units", GTK_TYPE_LABEL); timedlogin_allow_remote = glade_helper_get (xml, "allowremoteauto", GTK_TYPE_CHECK_BUTTON); gtk_widget_set_sensitive (timedlogin_label, val); gtk_widget_set_sensitive (timedlogin_combo, val); gtk_widget_set_sensitive (timedlogin_seconds_label, val); gtk_widget_set_sensitive (timedlogin_seconds_spin_button, val); gtk_widget_set_sensitive (timedlogin_seconds_units, val); if (gdm_config_get_bool (GDM_KEY_XDMCP) == FALSE) { gtk_widget_set_sensitive (timedlogin_allow_remote, FALSE); } else { gtk_widget_set_sensitive (timedlogin_allow_remote, val); } g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled), toggle); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), timedlogin_label); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), timedlogin_combo); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), timedlogin_seconds_label); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), timedlogin_seconds_spin_button); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), timedlogin_seconds_units); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (timedlogin_allow_remote_toggled), timedlogin_allow_remote); } else { g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled), NULL); } } #ifdef HAVE_LIBXDMCP static void setup_xdmcp_notify_toggle (const char *name, const char *key) { GtkWidget *toggle; gboolean val; toggle = glade_helper_get (xml_xdmcp, name, GTK_TYPE_TOGGLE_BUTTON); val = gdm_config_get_bool ((gchar *)key); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), val); g_object_set_data_full (G_OBJECT (toggle), "key", g_strdup (key), (GDestroyNotify) g_free); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled), NULL); } #endif 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; } } static gint users_string_compare_func (gconstpointer a, gconstpointer b) { return strcmp(a, b); } /* 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 = gdm_config_get_string ((gchar *)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_sort (users_string, users_string_compare_func); cnt=0; for (li = users_string; li != NULL; li = li->next) { if (strcmp (li->data, ve_sure_string (selected_user)) == 0) selected=cnt; gtk_list_store_append (combobox_store, &iter); 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); } 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) { GtkWidget *spin = glade_helper_get (xml, name, GTK_TYPE_SPIN_BUTTON); int val = gdm_config_get_int ((gchar *)key); g_object_set_data_full (G_OBJECT (spin), "key", g_strdup (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); } #ifdef HAVE_LIBXDMCP static void setup_xdmcp_intspin (const char *name, const char *key) { GtkWidget *spin; int val = gdm_config_get_int ((gchar *)key); spin = glade_helper_get (xml_xdmcp, name, GTK_TYPE_SPIN_BUTTON); g_object_set_data_full (G_OBJECT (spin), "key", g_strdup (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); } #endif 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 ((! ve_string_empty (GdmInclude)) && (strcmp (ve_sure_string (key), GDM_KEY_INCLUDE) == 0)) list = g_strsplit (GdmInclude, ",", 0); else if ((! ve_string_empty (GdmExclude)) && (strcmp (ve_sure_string (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 *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 *allusers; } FaceCommon; typedef struct _FaceData { FaceCommon *fc; FaceType type; } FaceData; typedef struct _FaceApply { FaceData *exclude; FaceData *include; } FaceApply; static void face_add (FaceData *fd) { GtkWidget *user_entry; const char *text = NULL; const char *model_text; GtkTreeIter iter; gboolean valid; user_entry = glade_helper_get (xml_add_users, "fb_addentry", GTK_TYPE_ENTRY); text = gtk_entry_get_text (GTK_ENTRY (user_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 (ve_sure_string (text), ve_sure_string (model_text)) == 0) { GtkWidget *setup_dialog; GtkWidget *dialog; gchar *str; str = g_strdup_printf (_("The \"%s\" user already exists in the include list."), text); setup_dialog = glade_helper_get (xml_add_users, "add_user_dialog", GTK_TYPE_WINDOW); dialog = ve_hig_dialog_new (GTK_WINDOW (setup_dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Cannot add user"), str); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); g_free (str); 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 (ve_sure_string (text), ve_sure_string (model_text)) == 0) { GtkWidget *setup_dialog; GtkWidget *dialog; gchar *str; str = g_strdup_printf (_("The \"%s\" user already exists in the exclude list."), text); setup_dialog = glade_helper_get (xml_add_users, "add_user_dialog", GTK_TYPE_WINDOW); dialog = ve_hig_dialog_new (GTK_WINDOW (setup_dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Cannot add user"), str); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); g_free (str); 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); } 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_widget_set_sensitive (fd->fc->apply, TRUE); GdmUserChangesUnsaved = TRUE; } else { GtkWidget *setup_dialog; GtkWidget *dialog; gchar *str; str = g_strdup_printf (_("The \"%s\" user does not exist."), text); setup_dialog = glade_helper_get (xml_add_users, "add_user_dialog", GTK_TYPE_WINDOW); dialog = ve_hig_dialog_new (GTK_WINDOW (setup_dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Cannot add user"), str); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); g_free (str); } } 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); GdmUserChangesUnsaved = 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); GdmUserChangesUnsaved = 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); GdmUserChangesUnsaved = TRUE; } } static void browser_apply (GtkWidget *button, gpointer data) { FaceCommon *fc = data; 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 = gdm_config_get_string (GDM_KEY_INCLUDE); if (strcmp (ve_sure_string (val), ve_sure_string (userlist->str)) != 0) { gdm_setup_config_set_string (GDM_KEY_INCLUDE, userlist->str); update_greet = TRUE; } g_string_free (userlist, TRUE); 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 = gdm_config_get_string (GDM_KEY_EXCLUDE); if (strcmp (ve_sure_string (val), ve_sure_string (userlist->str)) != 0) { gdm_setup_config_set_string (GDM_KEY_EXCLUDE, userlist->str); update_greet = TRUE; } if (update_greet) update_greeters (); /* Re-initialize combox with updated userlist. */ GdmInclude = gdm_config_get_string (GDM_KEY_INCLUDE); GdmExclude = gdm_config_get_string (GDM_KEY_EXCLUDE); setup_user_combobox_list ("autologin_combo", GDM_KEY_AUTOMATIC_LOGIN); setup_user_combobox_list ("timedlogin_combo", GDM_KEY_TIMED_LOGIN); gtk_widget_set_sensitive (button, FALSE); GdmUserChangesUnsaved = FALSE; g_string_free (userlist, TRUE); } 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_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 users_add_button_clicked (GtkWidget *button, gpointer data) { static GtkWidget *dialog = NULL; FaceData *fd = data; GtkWidget *user_entry; GtkWidget *parent; if (dialog == NULL) { parent = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); dialog = glade_helper_get (xml_add_users, "add_user_dialog", GTK_TYPE_DIALOG); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent)); gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); } user_entry = glade_helper_get (xml_add_users, "fb_addentry", GTK_TYPE_ENTRY); gtk_widget_grab_focus (user_entry); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { face_add (fd); } gtk_widget_hide (dialog); } static void setup_face (void) { 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.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_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; xml_add_users = glade_helper_load ("gdmsetup.glade", "add_user_dialog", GTK_TYPE_DIALOG, TRUE); g_signal_connect (G_OBJECT (fc.include_add), "clicked", G_CALLBACK (users_add_button_clicked), &fd_include); g_signal_connect (fc.exclude_add, "clicked", G_CALLBACK (users_add_button_clicked), &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_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 void include_all_toggle (GtkWidget *toggle) { if (GTK_TOGGLE_BUTTON (toggle)->active) GdmIncludeAll = TRUE; else GdmIncludeAll = FALSE; setup_user_combobox_list ("autologin_combo", GDM_KEY_AUTOMATIC_LOGIN); setup_user_combobox_list ("timedlogin_combo", GDM_KEY_TIMED_LOGIN); } static gboolean greeter_toggle_timeout (GtkWidget *toggle) { const char *key = g_object_get_data (G_OBJECT (toggle), "key"); gboolean val = gdm_config_get_bool ((gchar *)key); if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) { if (strcmp (ve_sure_string (key), GDM_KEY_BACKGROUND_SCALE_TO_FIT) == 0) { if (gtk_notebook_get_current_page (GTK_NOTEBOOK (setup_notebook)) == LOCAL_TAB) { GtkWidget *checkbutton; checkbutton = glade_helper_get (xml, "sg_scale_background_remote", GTK_TYPE_CHECK_BUTTON); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), GTK_TOGGLE_BUTTON (toggle)->active); } else { GtkWidget *checkbutton; checkbutton = glade_helper_get (xml, "sg_scale_background", GTK_TYPE_CHECK_BUTTON); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), GTK_TOGGLE_BUTTON (toggle)->active); } } gdm_setup_config_set_bool (key, GTK_TOGGLE_BUTTON (toggle)->active); update_greeters (); if (strcmp (ve_sure_string (key), GDM_KEY_INCLUDE_ALL) == 0) { include_all_toggle (toggle); } } return FALSE; } static void greeter_toggle_toggled (GtkWidget *toggle) { run_timeout (toggle, 500, greeter_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, 500, greeter_toggle_timeout); } static gboolean local_background_type_toggle_timeout (GtkWidget *toggle) { GtkWidget *color_radiobutton; GtkWidget *image_radiobutton; GtkWidget *color_remote_radiobutton; GtkWidget *image_remote_radiobutton; gboolean image_value; gboolean color_value; image_radiobutton = glade_helper_get (xml, "local_background_image_checkbutton", GTK_TYPE_CHECK_BUTTON); color_radiobutton = glade_helper_get (xml, "local_background_color_checkbutton", GTK_TYPE_CHECK_BUTTON); image_remote_radiobutton = glade_helper_get (xml, "remote_background_image_checkbutton", GTK_TYPE_CHECK_BUTTON); color_remote_radiobutton = glade_helper_get (xml, "remote_background_color_checkbutton", GTK_TYPE_CHECK_BUTTON); if (gtk_notebook_get_current_page (GTK_NOTEBOOK (setup_notebook)) == LOCAL_TAB) { image_value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (image_radiobutton)); color_value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (color_radiobutton)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_remote_radiobutton), image_value); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_remote_radiobutton), color_value); } else { image_value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (image_remote_radiobutton)); color_value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (color_remote_radiobutton)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), image_value); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), color_value); } if (image_value == TRUE && color_value == TRUE) { /* Image & color */ gdm_setup_config_set_int (GDM_KEY_BACKGROUND_TYPE, 1); } else if (image_value == FALSE && color_value == TRUE) { /* Color only */ gdm_setup_config_set_int (GDM_KEY_BACKGROUND_TYPE, 2); } else if (image_value == TRUE && color_value == FALSE) { /* Image only*/ gdm_setup_config_set_int (GDM_KEY_BACKGROUND_TYPE, 3); } else { /* No Background */ gdm_setup_config_set_int (GDM_KEY_BACKGROUND_TYPE, 0); } update_greeters (); return FALSE; } static void local_background_type_toggled (GtkWidget *toggle) { run_timeout (toggle, 200, local_background_type_toggle_timeout); } static void setup_greeter_toggle (const char *name, const char *key) { GtkWidget *toggle = glade_helper_get (xml, name, GTK_TYPE_TOGGLE_BUTTON); gboolean val = gdm_config_get_bool ((gchar *)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", ve_sure_string (name)) == 0) { GtkWidget *welcome = glade_helper_get (xml, "welcome", GTK_TYPE_ENTRY); GtkWidget *custom = glade_helper_get (xml, "sg_customwelcome", GTK_TYPE_RADIO_BUTTON); gtk_widget_set_sensitive (welcome, !val); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (custom), !val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), welcome); } else if (strcmp ("sg_defaultwelcomeremote", ve_sure_string (name)) == 0) { GtkWidget *welcomeremote = glade_helper_get (xml, "welcomeremote", GTK_TYPE_ENTRY); GtkWidget *customremote = glade_helper_get (xml, "sg_customwelcomeremote", GTK_TYPE_RADIO_BUTTON); gtk_widget_set_sensitive (welcomeremote, !val); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (customremote), !val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), welcomeremote); } else if (strcmp ("fb_allusers", ve_sure_string (name)) == 0) { GtkWidget *fb_includetree = glade_helper_get (xml, "fb_include_treeview", GTK_TYPE_TREE_VIEW); GtkWidget *fb_buttonbox = glade_helper_get (xml, "UsersButtonBox", GTK_TYPE_VBOX); GtkWidget *fb_includeadd = glade_helper_get (xml, "fb_includeadd", GTK_TYPE_BUTTON); GtkWidget *fb_includeremove = glade_helper_get (xml, "fb_includedelete", GTK_TYPE_BUTTON); GtkWidget *fb_includelabel = glade_helper_get (xml, "fb_includelabel", GTK_TYPE_LABEL); gtk_widget_set_sensitive (fb_buttonbox, !val); gtk_widget_set_sensitive (fb_includetree, !val); gtk_widget_set_sensitive (fb_includelabel, !val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), fb_buttonbox); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), fb_includetree); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), fb_includeadd); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (list_selection_toggled), fb_includeremove); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (sensitive_entry_toggled), fb_includelabel); } else if (strcmp ("acc_sound_ready", ve_sure_string (name)) == 0) { GtkWidget *file_chooser; GtkWidget *play_button; file_chooser = glade_helper_get (xml, "acc_sound_ready_button", GTK_TYPE_FILE_CHOOSER_BUTTON); play_button = glade_helper_get (xml, "acc_soundtest_ready_button", GTK_TYPE_BUTTON); gtk_widget_set_sensitive (file_chooser, val); gtk_widget_set_sensitive (play_button, val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), file_chooser); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), play_button); } else if (strcmp ("acc_sound_success", ve_sure_string (name)) == 0) { GtkWidget *file_chooser; GtkWidget *play_button; file_chooser = glade_helper_get (xml, "acc_sound_success_button", GTK_TYPE_FILE_CHOOSER_BUTTON); play_button = glade_helper_get (xml, "acc_soundtest_success_button", GTK_TYPE_BUTTON); gtk_widget_set_sensitive (file_chooser, val); gtk_widget_set_sensitive (play_button, val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), file_chooser); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), play_button); } else if (strcmp ("acc_sound_failure", ve_sure_string (name)) == 0) { GtkWidget *file_chooser; GtkWidget *play_button; file_chooser = glade_helper_get (xml, "acc_sound_failure_button", GTK_TYPE_FILE_CHOOSER_BUTTON); play_button = glade_helper_get (xml, "acc_soundtest_failure_button", GTK_TYPE_BUTTON); gtk_widget_set_sensitive (file_chooser, val); gtk_widget_set_sensitive (play_button, val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), file_chooser); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), play_button); } else if (strcmp ("local_logo_image_checkbutton", ve_sure_string (name)) == 0) { GtkWidget *file_chooser; GtkWidget *file_chooser_remote; GtkWidget *checkbutton; checkbutton = glade_helper_get (xml, "remote_logo_image_checkbutton", GTK_TYPE_CHECK_BUTTON); file_chooser = glade_helper_get (xml, "local_logo_image_chooserbutton", GTK_TYPE_FILE_CHOOSER_BUTTON); file_chooser_remote = glade_helper_get (xml, "remote_logo_image_chooserbutton", GTK_TYPE_FILE_CHOOSER_BUTTON); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), val); gtk_widget_set_sensitive (file_chooser, val); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), file_chooser); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), file_chooser_remote); g_signal_connect (G_OBJECT (toggle), "toggled", G_CALLBACK (logo_toggle_toggled), 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"); GdkColor color_val; char *val, *color; gtk_color_button_get_color (GTK_COLOR_BUTTON (picker), &color_val); if (gtk_notebook_get_current_page (GTK_NOTEBOOK (setup_notebook)) == LOCAL_TAB) { GtkWidget *colorbutton; if (strcmp (GDM_KEY_GRAPHICAL_THEMED_COLOR, ve_sure_string (key)) == 0) { colorbutton = glade_helper_get (xml, "remote_background_theme_colorbutton", GTK_TYPE_COLOR_BUTTON); } else { colorbutton = glade_helper_get (xml, "remote_background_colorbutton", GTK_TYPE_COLOR_BUTTON); } gtk_color_button_set_color (GTK_COLOR_BUTTON (colorbutton), &color_val); } else { GtkWidget *colorbutton; if (strcmp (GDM_KEY_GRAPHICAL_THEMED_COLOR, ve_sure_string (key)) == 0) { colorbutton = glade_helper_get (xml, "local_background_theme_colorbutton", GTK_TYPE_COLOR_BUTTON); } else { colorbutton = glade_helper_get (xml, "local_background_colorbutton", GTK_TYPE_COLOR_BUTTON); } gtk_color_button_set_color (GTK_COLOR_BUTTON (colorbutton), &color_val); } color = g_strdup_printf ("#%02x%02x%02x", (guint16)color_val.red / 256, (guint16)color_val.green / 256, (guint16)color_val.blue / 256); val = gdm_config_get_string ((gchar *)key); if (strcmp (ve_sure_string (val), ve_sure_string (color)) != 0) { gdm_setup_config_set_string (key, ve_sure_string (color)); update_greeters (); } 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, GTK_TYPE_COLOR_BUTTON); char *val = gdm_config_get_string ((gchar *)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)) { gtk_color_button_set_color (GTK_COLOR_BUTTON (picker), &color); } } g_signal_connect (G_OBJECT (picker), "color_set", G_CALLBACK (greeter_color_changed), NULL); } typedef enum { BACKIMAGE, LOGO } ImageType; typedef struct _ImageData { GtkWidget *image; gchar *filename; gchar *key; } ImageData; /* * Do we really want to throw away the user's translations just because they * changed the non-translated value? */ static gboolean greeter_entry_untranslate_timeout (GtkWidget *entry) { VeConfig *custom_cfg = ve_config_get (custom_config_file); const char *key = g_object_get_data (G_OBJECT (entry), "key"); const char *text; text = gtk_entry_get_text (GTK_ENTRY (entry)); ve_config_delete_translations (custom_cfg, key); gdm_setup_config_set_string (key, (char *)ve_sure_string (text)); 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 = gdm_config_get_translated_string ((gchar *)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); } #ifdef HAVE_LIBXDMCP static void xdmcp_button_clicked (void) { static GtkWidget *dialog = NULL; if (dialog == NULL) { GtkWidget *parent; xml_xdmcp = glade_helper_load ("gdmsetup.glade", "xdmcp_dialog", GTK_TYPE_DIALOG, TRUE); parent = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); dialog = glade_helper_get (xml_xdmcp, "xdmcp_dialog", GTK_TYPE_DIALOG); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent)); gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); setup_xdmcp_notify_toggle ("honour_indirect", GDM_KEY_INDIRECT); setup_xdmcp_intspin ("udpport", GDM_KEY_UDP_PORT); setup_xdmcp_intspin ("maxpending", GDM_KEY_MAX_PENDING); setup_xdmcp_intspin ("maxpendingindirect", GDM_KEY_MAX_INDIRECT); setup_xdmcp_intspin ("maxremotesessions", GDM_KEY_MAX_SESSIONS); setup_xdmcp_intspin ("maxwait", GDM_KEY_MAX_WAIT); setup_xdmcp_intspin ("maxwaitindirect", GDM_KEY_MAX_WAIT_INDIRECT); setup_xdmcp_intspin ("displaysperhost", GDM_KEY_DISPLAYS_PER_HOST); setup_xdmcp_intspin ("pinginterval", GDM_KEY_PING_INTERVAL); } gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_hide (dialog); } #endif static void vt_spinbutton_activate (GtkWidget * widget, gpointer data) { GtkDialog * dialog = data; gtk_dialog_response (dialog, GTK_RESPONSE_OK); } static void setup_greeter_combobox (const char *name, const char *key) { GtkWidget *combobox = glade_helper_get (xml, name, GTK_TYPE_COMBO_BOX); char *greetval = g_strdup (gdm_config_get_string ((gchar *)key)); if (greetval != NULL && strcmp (ve_sure_string (greetval), LIBEXECDIR "/gdmlogin --disable-sound --disable-crash-dialog") == 0) { g_free (greetval); greetval = g_strdup (LIBEXECDIR "/gdmlogin"); } /* Set initial state of local style combo box. */ if (strcmp (ve_sure_string (key), GDM_KEY_GREETER) == 0) { if (strstr (greetval, "/gdmlogin") != NULL) { GtkWidget *local_plain_vbox; GtkWidget *local_themed_vbox; gboolean val; val = gdm_config_get_bool (GDM_KEY_BROWSER); local_plain_vbox = glade_helper_get (xml, "local_plain_properties_vbox", GTK_TYPE_VBOX); local_themed_vbox = glade_helper_get (xml, "local_themed_properties_vbox", GTK_TYPE_VBOX); if (val == FALSE) { gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), LOCAL_PLAIN); } else { gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), LOCAL_PLAIN_WITH_FACE); } gtk_widget_show (local_plain_vbox); gtk_widget_hide (local_themed_vbox); } else if (strstr (greetval, "/gdmgreeter") != NULL) { GtkWidget *local_plain_vbox; GtkWidget *local_themed_vbox; local_plain_vbox = glade_helper_get (xml, "local_plain_properties_vbox", GTK_TYPE_VBOX); local_themed_vbox = glade_helper_get (xml, "local_themed_properties_vbox", GTK_TYPE_VBOX); gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), LOCAL_THEMED); gtk_widget_hide (local_plain_vbox); gtk_widget_show (local_themed_vbox); } } /* Set initial state of remote style combo box. */ else if (strcmp (ve_sure_string (key), GDM_KEY_REMOTE_GREETER) == 0) { refresh_remote_tab (); } 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); g_free (greetval); } static void setup_xdmcp_support (void) { GtkWidget *xdmcp_button; xdmcp_button = glade_helper_get (xml, "xdmcp_configbutton", GTK_TYPE_BUTTON); #ifndef HAVE_LIBXDMCP /* HAVE_LIBXDMCP */ gtk_widget_set_sensitive (xdmcp_button, FALSE); #else /* HAVE_LIBXDMCP */ gtk_widget_set_sensitive (xdmcp_button, TRUE); #endif } 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 (ve_sure_string (base1), "lib", 3) == 0) strcpy (base1, &base1[3]); if (strncmp (ve_sure_string (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 (ve_sure_string (base1), ve_sure_string (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 (ve_sure_string (vec[i]), ve_sure_string (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) { gboolean add_gtk_modules = gdm_config_get_bool (GDM_KEY_ADD_GTK_MODULES); char *modules_list = g_strdup (gdm_config_get_string (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, LIBDIR "/gtk-2.0/modules/libkeymouselistener", GDM_DELIMITER_MODULES); modules_list = strings_list_add (modules_list, LIBDIR "/gtk-2.0/modules/libdwellmouselistener", GDM_DELIMITER_MODULES); add_gtk_modules = TRUE; } if (ve_string_empty (modules_list)) add_gtk_modules = FALSE; gdm_setup_config_set_string (GDM_KEY_GTK_MODULES_LIST, ve_sure_string (modules_list)); gdm_setup_config_set_bool (GDM_KEY_ADD_GTK_MODULES, add_gtk_modules); g_free (modules_list); } static void test_sound (GtkWidget *button, gpointer data) { GtkWidget *acc_sound_file_chooser = data; gchar *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (acc_sound_file_chooser)); const char *argv[3]; if ((filename == NULL) || g_access (filename, R_OK) != 0 || ve_string_empty (GdmSoundProgram)) return; argv[0] = GdmSoundProgram; argv[1] = filename; 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 */); g_free (filename); } static void sound_response (GtkWidget *file_chooser, gpointer data) { gchar *filename; gchar *sound_key; gchar *value; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser)); sound_key = g_object_get_data (G_OBJECT (file_chooser), "key"); value = gdm_config_get_string (sound_key); if (strcmp (ve_sure_string (value), ve_sure_string (filename)) != 0) { gdm_setup_config_set_string (sound_key, (char *)ve_sure_string (filename)); update_greeters (); } g_free (filename); } static void setup_users_tab (void) { setup_greeter_toggle ("fb_allusers", GDM_KEY_INCLUDE_ALL); setup_face (); } static void setup_accessibility_tab (void) { GtkWidget *enable_accessible_login; GtkWidget *access_sound_ready_file_chooser; GtkWidget *access_sound_ready_play_button; GtkWidget *access_sound_success_file_chooser; GtkWidget *access_sound_success_play_button; GtkWidget *access_sound_failure_file_chooser; GtkWidget *access_sound_failure_play_button; GtkFileFilter *all_sounds_filter; GtkFileFilter *all_files_filter; gboolean add_gtk_modules; gchar *gdm_key_sound_ready; gchar *gdm_key_sound_success; gchar *gdm_key_sound_failure; gchar *modules_list; gchar *value; enable_accessible_login = glade_helper_get (xml, "acc_modules", GTK_TYPE_CHECK_BUTTON); access_sound_ready_file_chooser = glade_helper_get (xml, "acc_sound_ready_button", GTK_TYPE_FILE_CHOOSER_BUTTON); access_sound_ready_play_button = glade_helper_get (xml, "acc_soundtest_ready_button", GTK_TYPE_BUTTON); access_sound_success_file_chooser = glade_helper_get (xml, "acc_sound_success_button", GTK_TYPE_FILE_CHOOSER_BUTTON); access_sound_success_play_button = glade_helper_get (xml, "acc_soundtest_success_button", GTK_TYPE_BUTTON); access_sound_failure_file_chooser = glade_helper_get (xml, "acc_sound_failure_button", GTK_TYPE_FILE_CHOOSER_BUTTON); access_sound_failure_play_button = glade_helper_get (xml, "acc_soundtest_failure_button", GTK_TYPE_BUTTON); setup_greeter_toggle ("acc_theme", GDM_KEY_ALLOW_GTK_THEME_CHANGE); setup_greeter_toggle ("acc_sound_ready", GDM_KEY_SOUND_ON_LOGIN); setup_greeter_toggle ("acc_sound_success", GDM_KEY_SOUND_ON_LOGIN_SUCCESS); setup_greeter_toggle ("acc_sound_failure", GDM_KEY_SOUND_ON_LOGIN_FAILURE); add_gtk_modules = gdm_config_get_bool (GDM_KEY_ADD_GTK_MODULES); modules_list = gdm_config_get_string (GDM_KEY_GTK_MODULES_LIST); 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 (enable_accessible_login), FALSE); } else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable_accessible_login), TRUE); } all_sounds_filter = gtk_file_filter_new (); gtk_file_filter_set_name (all_sounds_filter, _("Sounds")); gtk_file_filter_add_mime_type (all_sounds_filter, "audio/x-wav"); gtk_file_filter_add_mime_type (all_sounds_filter, "application/ogg"); all_files_filter = gtk_file_filter_new (); gtk_file_filter_set_name (all_files_filter, _("All Files")); gtk_file_filter_add_pattern(all_files_filter, "*"); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (access_sound_ready_file_chooser), all_sounds_filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (access_sound_ready_file_chooser), all_files_filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (access_sound_success_file_chooser), all_sounds_filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (access_sound_success_file_chooser), all_files_filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (access_sound_failure_file_chooser), all_sounds_filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (access_sound_failure_file_chooser), all_files_filter); value = gdm_config_get_string (GDM_KEY_SOUND_ON_LOGIN_FILE); if (value != NULL && *value != '\0') { gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (access_sound_ready_file_chooser), value); } else { gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (access_sound_ready_file_chooser), DATADIR"/sounds"); } value = gdm_config_get_string (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE); if (value != NULL && *value != '\0') { gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (access_sound_success_file_chooser), value); } else { gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (access_sound_success_file_chooser), DATADIR"/sounds"); } value = gdm_config_get_string (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE); if (value != NULL && *value != '\0') { gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (access_sound_failure_file_chooser), value); } else { gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (access_sound_failure_file_chooser), DATADIR"/sounds"); } gdm_key_sound_ready = g_strdup (GDM_KEY_SOUND_ON_LOGIN_FILE); g_object_set_data (G_OBJECT (access_sound_ready_file_chooser), "key", gdm_key_sound_ready); gdm_key_sound_success = g_strdup (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE); g_object_set_data (G_OBJECT (access_sound_success_file_chooser), "key", gdm_key_sound_success); gdm_key_sound_failure = g_strdup (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE); g_object_set_data (G_OBJECT (access_sound_failure_file_chooser), "key", gdm_key_sound_failure); g_signal_connect (G_OBJECT (enable_accessible_login), "toggled", G_CALLBACK (acc_modules_toggled), NULL); g_signal_connect (G_OBJECT (access_sound_ready_play_button), "clicked", G_CALLBACK (test_sound), access_sound_ready_file_chooser); g_signal_connect (G_OBJECT (access_sound_success_play_button), "clicked", G_CALLBACK (test_sound), access_sound_success_file_chooser); g_signal_connect (G_OBJECT (access_sound_failure_play_button), "clicked", G_CALLBACK (test_sound), access_sound_failure_file_chooser); g_signal_connect (G_OBJECT (access_sound_ready_file_chooser), "selection-changed", G_CALLBACK (sound_response), access_sound_ready_file_chooser); g_signal_connect (G_OBJECT (access_sound_success_file_chooser), "selection-changed", G_CALLBACK (sound_response), access_sound_success_file_chooser); g_signal_connect (G_OBJECT (access_sound_failure_file_chooser), "selection-changed", G_CALLBACK (sound_response), access_sound_failure_file_chooser); } static char * get_theme_dir (void) { /* * We always want to free the value returned from this function, since * we use strdup to build a reasonable value if the configuration value * is not good. So use g_strdup here. */ char *theme_dir = g_strdup (gdm_config_get_string (GDM_KEY_GRAPHICAL_THEME_DIR)); if (theme_dir == NULL || theme_dir[0] == '\0' || g_access (theme_dir, R_OK) != 0) { theme_dir = g_strdup (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) { static gboolean FirstPass = TRUE; GtkWidget *label; GtkWidget *label_remote; GtkWidget *delete_button; GtkWidget *delete_button_remote; GtkTreeModel *model; GtkTreeIter iter; GtkTextBuffer *buffer_local, *buffer_remote; GtkTextIter iter_local, iter_remote; GValue value = {0, }; gboolean GdmGraphicalThemeRand; gchar *str; delete_button = glade_helper_get (xml, "gg_delete_theme", GTK_TYPE_BUTTON); delete_button_remote = glade_helper_get (xml, "gg_delete_theme_remote", GTK_TYPE_BUTTON); if ( !gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_widget_set_sensitive (delete_button, FALSE); gtk_widget_set_sensitive (delete_button_remote, FALSE); return; } /* Default to allow deleting of themes */ if (gtk_notebook_get_current_page (GTK_NOTEBOOK (setup_notebook)) == LOCAL_TAB) { GtkWidget *theme_list; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreePath *path; theme_list = glade_helper_get (xml, "gg_theme_list_remote", GTK_TYPE_TREE_VIEW); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list)); model = gtk_tree_view_get_model (GTK_TREE_VIEW (theme_list)); if (model != NULL) { path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); if (path != NULL) { gtk_tree_selection_select_path (selection, path); if (GTK_WIDGET_REALIZED(theme_list)) { gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (theme_list), path, NULL, FALSE, 0.0, 0.0); } } } gtk_widget_set_sensitive (delete_button, TRUE); gtk_widget_set_sensitive (delete_button_remote, TRUE); } else { GtkWidget *theme_list; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreePath *path; theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list)); model = gtk_tree_view_get_model (GTK_TREE_VIEW (theme_list)); if (model != NULL) { path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); if (path != NULL) { gtk_tree_selection_select_path (selection, path); if (GTK_WIDGET_REALIZED(theme_list)) { gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (theme_list), path, NULL, FALSE, 0.0, 0.0); } } } gtk_widget_set_sensitive (delete_button, TRUE); gtk_widget_set_sensitive (delete_button_remote, TRUE); } /* Determine if the theme selected is currently active */ GdmGraphicalThemeRand = gdm_config_get_bool (GDM_KEY_GRAPHICAL_THEME_RAND); 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 (delete_button, FALSE); gtk_widget_set_sensitive (delete_button_remote, FALSE); } g_value_unset (&value); gtk_tree_model_get_value (model, &iter, THEME_COLUMN_AUTHOR, &value); if (!ve_string_empty (ve_sure_string (g_value_get_string (&value)))) { str = g_strconcat (ve_sure_string (g_value_get_string (&value)), NULL); } else { str = g_strconcat (_("None"), NULL); } label = glade_helper_get (xml, "gg_author_text_view", GTK_TYPE_TEXT_VIEW); label_remote = glade_helper_get (xml, "gg_author_text_view_remote", GTK_TYPE_TEXT_VIEW); textview_set_buffer (GTK_TEXT_VIEW (label), ""); textview_set_buffer (GTK_TEXT_VIEW (label_remote), ""); buffer_local = gtk_text_view_get_buffer (GTK_TEXT_VIEW (label)); buffer_remote = gtk_text_view_get_buffer (GTK_TEXT_VIEW (label_remote)); gtk_text_buffer_get_iter_at_offset (buffer_local, &iter_local, 0); gtk_text_buffer_get_iter_at_offset (buffer_remote, &iter_remote, 0); if (FirstPass == TRUE) { gtk_text_buffer_create_tag (buffer_local, "small", "scale", PANGO_SCALE_SMALL, NULL); gtk_text_buffer_create_tag (buffer_remote, "small", "scale", PANGO_SCALE_SMALL, NULL); } gtk_text_buffer_insert_with_tags_by_name (buffer_local, &iter_local, str, -1, "small", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer_remote, &iter_remote, str, -1, "small", NULL); g_value_unset (&value); g_free (str); gtk_tree_model_get_value (model, &iter, THEME_COLUMN_COPYRIGHT, &value); label = glade_helper_get (xml, "gg_copyright_text_view", GTK_TYPE_TEXT_VIEW); label_remote = glade_helper_get (xml, "gg_copyright_text_view_remote", GTK_TYPE_TEXT_VIEW); textview_set_buffer (GTK_TEXT_VIEW (label), ""); textview_set_buffer (GTK_TEXT_VIEW (label_remote), ""); buffer_local = gtk_text_view_get_buffer (GTK_TEXT_VIEW (label)); buffer_remote = gtk_text_view_get_buffer (GTK_TEXT_VIEW (label_remote)); gtk_text_buffer_get_iter_at_offset (buffer_local, &iter_local, 0); gtk_text_buffer_get_iter_at_offset (buffer_remote, &iter_remote, 0); if (FirstPass == TRUE) { gtk_text_buffer_create_tag (buffer_local, "small", "scale", PANGO_SCALE_SMALL, NULL); gtk_text_buffer_create_tag (buffer_remote, "small", "scale", PANGO_SCALE_SMALL, NULL); } if (!ve_string_empty (ve_sure_string (g_value_get_string (&value)))) { str = g_strconcat (ve_sure_string (g_value_get_string (&value)), NULL); } else { str = g_strconcat (_("None"), NULL); } gtk_text_buffer_insert_with_tags_by_name (buffer_local, &iter_local, str, -1, "small", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer_remote, &iter_remote, str, -1, "small", NULL); FirstPass = FALSE; g_value_unset (&value); } static GtkTreeIter * read_themes (GtkListStore *store, const char *theme_dir, DIR *dir, const char *select_item) { struct dirent *dent; GtkTreeIter *select_iter = NULL; GdkPixbuf *pb = NULL; gchar *markup; 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 (g_access (n, R_OK) != 0) { g_free (n); n = g_strconcat (theme_dir, "/", dent->d_name, "/GdmGreeterTheme.info", NULL); } if (g_access (n, R_OK) != 0) { g_free (n); continue; } theme_file = ve_config_new (n); file = gdm_get_theme_greeter (n, dent->d_name); full = g_strconcat (theme_dir, "/", dent->d_name, "/", file, NULL); if (g_access (full, R_OK) != 0) { g_free (file); g_free (full); g_free (n); continue; } g_free (full); if (selected_theme != NULL && strcmp (ve_sure_string (dent->d_name), ve_sure_string (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; if ( ! ve_string_empty (full) && g_access (full, R_OK) == 0) { pb = gdk_pixbuf_new_from_file (full, NULL); if (pb != NULL) { if (gdk_pixbuf_get_width (pb) > 64 || gdk_pixbuf_get_height (pb) > 50) { GdkPixbuf *pb2; pb2 = gdk_pixbuf_scale_simple (pb, 64, 50, GDK_INTERP_BILINEAR); g_object_unref (G_OBJECT (pb)); pb = pb2; } } } markup = g_markup_printf_escaped ("%s\n%s", name, desc); 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_SCREENSHOT, pb, THEME_COLUMN_MARKUP, markup, THEME_COLUMN_NAME, name, THEME_COLUMN_DESCRIPTION, desc, THEME_COLUMN_AUTHOR, author, THEME_COLUMN_COPYRIGHT, copyright, -1); if (select_item != NULL && strcmp (ve_sure_string (dent->d_name), ve_sure_string (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; theme = gdm_config_get_string (GDM_KEY_GRAPHICAL_THEME); themes = gdm_config_get_string (GDM_KEY_GRAPHICAL_THEMES); /* If no checkbox themes selected */ if (selected_themes == NULL) selected_themes = ""; /* If themes have changed from the custom_config file, update it. */ if (strcmp (ve_sure_string (theme), ve_sure_string (selected_theme)) != 0) { gdm_setup_config_set_string (GDM_KEY_GRAPHICAL_THEME, selected_theme); update_greeters (); } if (strcmp (ve_sure_string (themes), ve_sure_string (selected_themes)) != 0) { gdm_setup_config_set_string (GDM_KEY_GRAPHICAL_THEMES, selected_themes); update_greeters (); } 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); GtkWidget *del_button_remote = glade_helper_get (xml, "gg_delete_theme_remote", 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); gtk_widget_set_sensitive (del_button_remote, 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); gtk_widget_set_sensitive (del_button_remote, 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_widget_set_sensitive (del_button_remote, 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 (gchar *filename, const char *ext) { const char *dot; dot = strrchr (filename, '.'); if (dot == NULL) return FALSE; if (strcmp (ve_sure_string (dot), ve_sure_string (ext)) == 0) return TRUE; else return FALSE; } /* sense the right unzip program */ static char * find_unzip (gchar *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 (g_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 (g_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 (g_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 (g_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 (g_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 (ve_sure_string (buf), ve_sure_string (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 (ve_sure_string (buf), ve_sure_string (s)) == 0) got_info = TRUE; g_free (s); } if ( ! got_info) { s = g_strconcat (dir, "/GdmGreeterTheme.desktop", NULL); if (strcmp (ve_sure_string (buf), ve_sure_string (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 (gchar *filename, char **untar_cmd, char **error) { char *quoted; char *tar; char *unzip; char *cmd; char *dir; FILE *fp; *untar_cmd = NULL; *error = NULL; if (g_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 (ve_sure_string (dent->d_name), ve_sure_string (dir)) == 0) { closedir (dp); return TRUE; } } closedir (dp); return FALSE; } static void install_theme_file (gchar *filename, GtkListStore *store, GtkWindow *parent) { GtkTreeSelection *selection; GtkTreeIter *select_iter = NULL; GtkWidget *theme_list; DIR *dp; gchar *cwd; gchar *dir; gchar *error; gchar *theme_dir; gchar *untar_cmd; gboolean success = FALSE; theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); cwd = g_get_current_dir (); theme_dir = get_theme_dir (); if ( !g_path_is_absolute (filename)) { gchar *temp; temp = g_build_filename (cwd, filename, NULL); g_free (filename); filename = temp; } dir = get_archive_dir (filename, &untar_cmd, &error); /* FIXME: perhaps do a little bit more sanity checking of * the archive */ if (dir == NULL) { GtkWidget *dialog; gchar *msg; msg = g_strdup_printf (_("%s"), error); dialog = ve_hig_dialog_new (GTK_WINDOW (parent), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Not a theme archive"), msg); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); g_free (theme_dir); g_free (untar_cmd); g_free (cwd); g_free (msg); return; } if (dir_exists (theme_dir, dir)) { GtkWidget *button; GtkWidget *dialog; gchar *fname; gchar *s; fname = ve_filename_to_utf8 (dir); /* 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); dialog = ve_hig_dialog_new (GTK_WINDOW (parent), 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 (dialog), 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 (dialog), button, GTK_RESPONSE_YES); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_show (button); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_YES) { gtk_widget_destroy (dialog); g_free (theme_dir); g_free (untar_cmd); g_free (cwd); g_free (dir); return; } gtk_widget_destroy (dialog); } g_assert (untar_cmd != NULL); if (g_chdir (theme_dir) == 0 && /* this is a security sanity check */ strchr (dir, '/') == NULL && system (untar_cmd) == 0) { gchar *argv[5]; gchar *quoted; gchar *chown; gchar *chmod; quoted = g_strconcat ("./", dir, NULL); chown = find_chown (); 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 *dialog; dialog = ve_hig_dialog_new (GTK_WINDOW (parent), 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 (dialog)); gtk_widget_destroy (dialog); } 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 (theme_dir); g_free (dir); g_free (cwd); } static void theme_install_response (GtkWidget *chooser, gint response, gpointer data) { GtkListStore *store = data; gchar *filename; if (response != GTK_RESPONSE_OK) { gtk_widget_destroy (chooser); return; } if (last_theme_installed != NULL) { g_free (last_theme_installed); } filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)); last_theme_installed = g_strdup (filename); if (filename == NULL) { GtkWidget *dialog; dialog = 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 (dialog)); gtk_widget_destroy (dialog); return; } install_theme_file (filename, store, GTK_WINDOW (chooser)); gtk_widget_destroy (chooser); g_free (filename); } static void install_new_theme (GtkWidget *button, gpointer data) { GtkListStore *store = data; static GtkWidget *chooser = NULL; GtkWidget *setup_dialog; setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); chooser = gtk_file_chooser_dialog_new (_("Select Theme Archive"), 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 (GTK_FILE_CHOOSER (chooser), FALSE); 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 *theme_list_remote; GtkWidget *setup_dialog; GtkWidget *del_button; GtkWidget *del_button_remote; GtkTreeSelection *selection; char *dir, *name; GtkTreeModel *model; GtkTreeIter iter; GValue value = {0, }; GtkWidget *dlg; char *s; gboolean GdmGraphicalThemeRand; setup_dialog = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); theme_list_remote = glade_helper_get (xml, "gg_theme_list_remote", GTK_TYPE_TREE_VIEW); del_button = glade_helper_get (xml, "gg_delete_theme", GTK_TYPE_BUTTON); del_button_remote = glade_helper_get (xml, "gg_delete_theme_remote", GTK_TYPE_BUTTON); if (gtk_notebook_get_current_page (GTK_NOTEBOOK (setup_notebook)) == LOCAL_TAB) { selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list)); } else { selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (theme_list_remote)); } if ( ! gtk_tree_selection_get_selected (selection, &model, &iter)) { /* should never get here since the button shuld not be * enabled */ return; } GdmGraphicalThemeRand = gdm_config_get_bool (GDM_KEY_GRAPHICAL_THEME_RAND); 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 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 (_("Remove the \"%s\" theme?"), name); dlg = ve_hig_dialog_new (GTK_WINDOW (setup_dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, s, _("If you choose to remove the theme, it will be permanently lost.")); 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 (g_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); } } g_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) { GtkWidget *mod_combobox; GSList *li; const char *key = g_object_get_data (G_OBJECT (entry), "key"); const char *text = gtk_entry_get_text (GTK_ENTRY (entry)); gchar *string_old = NULL; gchar *section; mod_combobox = glade_helper_get (xml_xservers, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); /* Get xserver section to update */ section = gtk_combo_box_get_active_text (GTK_COMBO_BOX (mod_combobox)); for (li = xservers; li != NULL; li = li->next) { GdmXserver *svr = li->data; if (strcmp (ve_sure_string (svr->id), ve_sure_string (section)) == 0) { if (strcmp (ve_sure_string (key), ve_sure_string (GDM_KEY_SERVER_NAME)) == 0) string_old = svr->name; else if (strcmp (ve_sure_string (key), ve_sure_string (GDM_KEY_SERVER_COMMAND)) == 0) string_old = svr->command; /* Update this servers configuration */ if (strcmp (ve_sure_string (string_old), ve_sure_string (text)) != 0) { if (strcmp (ve_sure_string (key), ve_sure_string (GDM_KEY_SERVER_NAME)) == 0) { if (svr->name) g_free (svr->name); svr->name = g_strdup (text); } else if (strcmp (ve_sure_string (key), ve_sure_string (GDM_KEY_SERVER_COMMAND)) == 0) { if (svr->command) g_free (svr->command); svr->command = g_strdup (text);; } update_xserver (section, svr); } break; } } g_free (section); return FALSE; } static gboolean xserver_toggle_timeout (GtkWidget *toggle) { GtkWidget *mod_combobox; const char *key = g_object_get_data (G_OBJECT (toggle), "key"); GSList *li; gboolean val = FALSE; gchar *section; mod_combobox = glade_helper_get (xml_xservers, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); /* Get xserver section to update */ section = gtk_combo_box_get_active_text (GTK_COMBO_BOX (mod_combobox)); /* Locate this server's section */ for (li = xservers; li != NULL; li = li->next) { GdmXserver *svr = li->data; if (strcmp (ve_sure_string (svr->id), ve_sure_string (section)) == 0) { if (strcmp (ve_sure_string (key), ve_sure_string (GDM_KEY_SERVER_HANDLED)) == 0) { val = svr->handled; } else if (strcmp (ve_sure_string (key), ve_sure_string (GDM_KEY_SERVER_FLEXIBLE)) == 0) { val = svr->flexible; } /* Update this servers configuration */ if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) { gboolean new_val = GTK_TOGGLE_BUTTON (toggle)->active; if (strcmp (ve_sure_string (key), ve_sure_string (GDM_KEY_SERVER_HANDLED)) == 0) svr->handled = new_val; else if (strcmp (ve_sure_string (key), ve_sure_string (GDM_KEY_SERVER_FLEXIBLE)) == 0) svr->flexible = new_val; update_xserver (section, svr); } break; } } 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; /* 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 */ 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_xservers, "xserver_tree_view", GTK_TYPE_TREE_VIEW); GtkWidget *remove_button = glade_helper_get (xml_xservers, "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_displays (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 *remove_button; /* Init widget states */ xserver_init_server_list(); remove_button = glade_helper_get (xml_xservers, "xserver_remove_button", GTK_TYPE_BUTTON); gtk_widget_set_sensitive (remove_button, FALSE); } static void xserver_row_selected(GtkTreeSelection *selection, gpointer data) { GtkWidget *remove_button; remove_button = glade_helper_get (xml_xservers, "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_display (gpointer data) { GtkWidget *treeview, *combo; GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; gint vt; char vt_value[3]; treeview = glade_helper_get (xml_xservers, "xserver_tree_view", GTK_TYPE_TREE_VIEW); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { VeConfig *cfg = ve_config_get (config_file); VeConfig *custom_cfg = ve_config_get (custom_config_file); gchar *defaultval; gchar *key; combo = glade_helper_get (xml_add_xservers, "xserver_server_combobox", GTK_TYPE_COMBO_BOX); /* Update config */ gtk_tree_model_get (model, &iter, XSERVER_COLUMN_VT, &vt, -1); g_snprintf (vt_value, sizeof (vt_value), "%d", vt); key = g_strconcat (GDM_KEY_SECTION_SERVERS, "/", vt_value, "=", NULL); defaultval = ve_config_get_string (cfg, key); /* * If the value is in the default config file, set it to inactive in * the custom config file, else delete it */ if (! ve_string_empty (defaultval)) { ve_config_set_string (custom_cfg, key, "inactive"); } else { ve_config_delete_key (custom_cfg, key); } g_free (defaultval); ve_config_save (custom_cfg, FALSE /* force */); /* Update gdmsetup */ xserver_init_server_list (); xserver_update_delete_sensitivity (); } } /* Add a display to the list of displays to start */ static void xserver_add_display (gpointer data) { VeConfig *cfg = ve_config_get (config_file); VeConfig *custom_cfg = ve_config_get (custom_config_file); GtkWidget *spinner, *combo, *entry, *button; gchar *string; gchar *defaultval; char spinner_value[3], *key; /* Get Widgets from glade */ spinner = glade_helper_get (xml_add_xservers, "xserver_spin_button", GTK_TYPE_SPIN_BUTTON); entry = glade_helper_get (xml_add_xservers, "xserver_options_entry", GTK_TYPE_ENTRY); combo = glade_helper_get (xml_add_xservers, "xserver_server_combobox", GTK_TYPE_COMBO_BOX); button = glade_helper_get (xml_xservers, "xserver_add_button", GTK_TYPE_BUTTON); /* 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 (GDM_KEY_SECTION_SERVERS, "/", spinner_value, "=", NULL); if (! ve_string_empty (gtk_entry_get_text (GTK_ENTRY (entry)))) { string = g_strconcat (gtk_combo_box_get_active_text (GTK_COMBO_BOX (combo)), " ", gtk_entry_get_text (GTK_ENTRY (entry)), NULL); } else { string = g_strdup (gtk_combo_box_get_active_text (GTK_COMBO_BOX (combo))); } defaultval = ve_config_get_string (cfg, key); /* Add to config */ if (strcmp (ve_sure_string (defaultval), ve_sure_string (string)) == 0) ve_config_delete_key (custom_cfg, key); else ve_config_set_string (custom_cfg, key, ve_sure_string(string)); ve_config_save (custom_cfg, FALSE /* force */); /* Reinitialize gdmsetup */ xserver_init_servers (); xserver_update_delete_sensitivity (); /* Free memory */ g_free (defaultval); g_free (string); g_free (key); } static void xserver_add_button_clicked (void) { static GtkWidget *dialog = NULL; GtkWidget *options_entry; GtkWidget *server_combobox; GtkWidget *vt_spinbutton; GtkWidget *parent; GtkWidget *treeview; GtkTreeSelection *selection; GtkTreeModel *treeview_model; GtkTreeIter treeview_iter; guint activate_signal_id; gboolean res; if (dialog == NULL) { parent = glade_helper_get (xml_xservers, "xserver_dialog", GTK_TYPE_WINDOW); dialog = glade_helper_get (xml_add_xservers, "add_xserver_dialog", GTK_TYPE_DIALOG); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent)); gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); } vt_spinbutton = glade_helper_get (xml_add_xservers, "xserver_spin_button", GTK_TYPE_SPIN_BUTTON); server_combobox = glade_helper_get (xml_add_xservers, "xserver_server_combobox", GTK_TYPE_COMBO_BOX); options_entry = glade_helper_get (xml_add_xservers, "xserver_options_entry", GTK_TYPE_ENTRY); activate_signal_id = g_signal_connect (G_OBJECT (vt_spinbutton), "activate", G_CALLBACK (vt_spinbutton_activate), (gpointer) dialog); xserver_populate_combobox (GTK_COMBO_BOX (server_combobox)); gtk_widget_grab_focus (vt_spinbutton); treeview = glade_helper_get (xml_xservers, "xserver_tree_view", GTK_TYPE_TREE_VIEW); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); /* set default values */ if (gtk_tree_selection_get_selected (selection, &treeview_model, &treeview_iter)) { GtkTreeModel *combobox_model; GtkTreeIter combobox_iter; gchar *label; gchar *server; gint vt; gtk_tree_model_get (treeview_model, &treeview_iter, XSERVER_COLUMN_VT, &vt, -1); gtk_spin_button_set_value (GTK_SPIN_BUTTON (vt_spinbutton), vt); gtk_tree_model_get (GTK_TREE_MODEL (treeview_model), &treeview_iter, XSERVER_COLUMN_SERVER, &server, -1); combobox_model = gtk_combo_box_get_model (GTK_COMBO_BOX (server_combobox)); for (res = gtk_tree_model_get_iter_first (combobox_model, &combobox_iter); res; res = gtk_tree_model_iter_next (combobox_model, &combobox_iter)) { gtk_tree_model_get (combobox_model, &combobox_iter, 0, &label, -1); if (strcmp (ve_sure_string (label), ve_sure_string (server)) == 0) { gtk_combo_box_set_active_iter (GTK_COMBO_BOX (server_combobox), &combobox_iter); } g_free (label); } gtk_tree_model_get (GTK_TREE_MODEL (treeview_model), &treeview_iter, XSERVER_COLUMN_OPTIONS, &server, -1); if (server != NULL) gtk_entry_set_text (GTK_ENTRY (options_entry), server); } else { gint high_value = 0; gint vt; for (res = gtk_tree_model_get_iter_first (treeview_model, &treeview_iter); res; res = gtk_tree_model_iter_next (treeview_model, &treeview_iter)) { gtk_tree_model_get (treeview_model, &treeview_iter, XSERVER_COLUMN_VT, &vt, -1); if (high_value < vt) { high_value = vt; } } gtk_spin_button_set_value (GTK_SPIN_BUTTON (vt_spinbutton), ++high_value); gtk_combo_box_set_active (GTK_COMBO_BOX (server_combobox), 0); gtk_entry_set_text (GTK_ENTRY (options_entry), ""); } if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { xserver_add_display (NULL); } g_signal_handler_disconnect (vt_spinbutton, activate_signal_id); gtk_widget_hide (dialog); } /* * 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) */ #ifdef GDM_TODO_CODE 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 (custom_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); } } #endif static void xserver_init_definitions () { GtkWidget *style_combobox; GtkWidget *modify_combobox; style_combobox = glade_helper_get (xml_xservers, "xserver_style_combobox", GTK_TYPE_COMBO_BOX); modify_combobox = glade_helper_get (xml_xservers, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); xserver_populate_combobox (GTK_COMBO_BOX (modify_combobox)); gtk_combo_box_set_active (GTK_COMBO_BOX (style_combobox), 0); init_servers_combobox (gtk_combo_box_get_active (GTK_COMBO_BOX (style_combobox))); } /* * Deletes a server definition (not the same as removing a server * from the list of servers to start) * * NOTE, now that we have the %{datadir}/gdm/defaults.conf and * %{etc}/gdm/custom.conf files, this will need to work like the displays. * So if you want to delete something that is defaults.conf you will need * to write a new value to custom.conf section for this xserver like * "inactive=true". For this to work, daemon/gdmconfig.c will also need * to be modified so that it doesn't bother loading xservers that are * marked as inactive in the custom.conf file. As I said, this * is the same way the displays already work so the code should be * similar. Or perhaps it makes more sense to just not allow * deleting of server-foo sections as defined in the defaults.conf * file. If the user doesn't want to use them, they can always * create new server-foo sections in custom.conf and define their * displays to only use the ones they define. */ #ifdef GDM_UNUSED_CODE static void xserver_delete (gpointer data) { /* Get xserver section to delete */ GtkWidget *combobox = glade_helper_get (xml_xservers, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); gchar *section = gtk_combo_box_get_active_text ( GTK_COMBO_BOX (combobox)); /* Delete xserver section */ VeConfig *custom_cfg = ve_config_get (custom_config_file); ve_config_delete_section (custom_cfg, g_strconcat (GDM_KEY_SERVER_PREFIX, section, NULL)); /* Reinitialize definitions */ xserver_init_definitions(); } #endif static void setup_xserver_support (GladeXML *xml_xservers) { GtkWidget *command_entry; GtkWidget *name_entry; GtkWidget *handled_check; GtkWidget *flexible_check; GtkWidget *create_button; GtkWidget *delete_button; GtkWidget *remove_button; GtkWidget *servers_combobox; GtkWidget *style_combobox; GtkWidget *treeview; GtkCellRenderer *renderer; GtkTreeSelection *selection; GtkTreeViewColumn *column; /* 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 */ treeview = glade_helper_get (xml_xservers, "xserver_tree_view", GTK_TYPE_TREE_VIEW); name_entry = glade_helper_get (xml_xservers, "xserver_name_entry", GTK_TYPE_ENTRY); command_entry = glade_helper_get (xml_xservers, "xserver_command_entry", GTK_TYPE_ENTRY); handled_check = glade_helper_get (xml_xservers, "xserver_handled_checkbutton", GTK_TYPE_CHECK_BUTTON); flexible_check = glade_helper_get (xml_xservers, "xserver_flexible_checkbutton", GTK_TYPE_CHECK_BUTTON); style_combobox = glade_helper_get (xml_xservers, "xserver_style_combobox", GTK_TYPE_COMBO_BOX); servers_combobox = glade_helper_get (xml_xservers, "xserver_mod_combobox", GTK_TYPE_COMBO_BOX); create_button = glade_helper_get (xml_xservers, "xserver_createbutton", GTK_TYPE_BUTTON); delete_button = glade_helper_get (xml_xservers, "xserver_deletebutton", GTK_TYPE_BUTTON); remove_button = glade_helper_get (xml_xservers, "xserver_remove_button", GTK_TYPE_BUTTON); glade_helper_tagify_label (xml_xservers, "xserver_informationlabel", "i"); glade_helper_tagify_label (xml_xservers, "xserver_informationlabel", "small"); glade_helper_tagify_label (xml_xservers, "server_to_start_label", "b"); glade_helper_tagify_label (xml_xservers, "server_settings_label", "b"); /* 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 (servers_combobox), "key", g_strdup (GDM_KEY_SERVER_PREFIX), (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 (style_combobox), "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 (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 (servers_combobox), "changed", G_CALLBACK (combobox_changed), NULL); g_signal_connect (G_OBJECT (style_combobox), "changed", G_CALLBACK (combobox_changed), NULL); g_signal_connect (G_OBJECT (remove_button), "clicked", G_CALLBACK (xserver_remove_display), NULL); g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (xserver_row_selected), NULL); /* TODO: In the future, allow creation & delection of servers g_signal_connect (create_button, "clicked", G_CALLBACK (xserver_create), NULL); g_signal_connect (delete_button, "clicked", G_CALLBACK (xserver_delete), NULL); */ } static void xserver_button_clicked (void) { static GtkWidget *dialog = NULL; int response; if (dialog == NULL) { GtkWidget *parent; GtkWidget *button; xml_xservers = glade_helper_load ("gdmsetup.glade", "xserver_dialog", GTK_TYPE_DIALOG, TRUE); xml_add_xservers = glade_helper_load ("gdmsetup.glade", "add_xserver_dialog", GTK_TYPE_DIALOG, TRUE); parent = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); dialog = glade_helper_get (xml_xservers, "xserver_dialog", GTK_TYPE_DIALOG); button = glade_helper_get (xml_xservers, "xserver_add_button", GTK_TYPE_BUTTON); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent)); gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (xserver_add_button_clicked), NULL); setup_xserver_support (xml_xservers); } do { response = gtk_dialog_run (GTK_DIALOG (dialog)); if (response == GTK_RESPONSE_HELP) { g_spawn_command_line_sync ("gnome-open ghelp:gdm", NULL, NULL, NULL, NULL); } } while (response != GTK_RESPONSE_CLOSE && response != GTK_RESPONSE_DELETE_EVENT); gtk_widget_hide (dialog); } static void setup_security_tab (void) { GtkWidget *checkbox; GtkWidget *label; GtkWidget *XDMCPbutton; /* Setup Local administrator login setttings */ setup_notify_toggle ("allowroot", GDM_KEY_ALLOW_ROOT); /* Setup Remote administrator login setttings */ setup_notify_toggle ("allowremoteroot", GDM_KEY_ALLOW_REMOTE_ROOT); /* Setup Enable debug message to system log */ setup_notify_toggle ("enable_debug", GDM_KEY_DEBUG); /* Setup Deny TCP connections to Xserver */ setup_notify_toggle ("disallow_tcp", GDM_KEY_DISALLOW_TCP); /* Setup Retry delay */ setup_intspin ("retry_delay", GDM_KEY_RETRY_DELAY); /* Bold the Enable automatic login label */ checkbox = glade_helper_get (xml, "autologin", GTK_TYPE_CHECK_BUTTON); label = gtk_bin_get_child (GTK_BIN (checkbox)); g_object_set (G_OBJECT (label), "use_markup", TRUE, NULL); /* Bold the Enable timed login label */ checkbox = glade_helper_get (xml, "timedlogin", GTK_TYPE_CHECK_BUTTON); label = gtk_bin_get_child (GTK_BIN (checkbox)); g_object_set (G_OBJECT (label), "use_markup", TRUE, NULL); /* Setup Enable automatic login */ setup_user_combobox ("autologin_combo", GDM_KEY_AUTOMATIC_LOGIN); setup_notify_toggle ("autologin", GDM_KEY_AUTOMATIC_LOGIN_ENABLE); /* Setup Enable timed login */ setup_user_combobox ("timedlogin_combo", GDM_KEY_TIMED_LOGIN); setup_intspin ("timedlogin_seconds", GDM_KEY_TIMED_LOGIN_DELAY); setup_notify_toggle ("timedlogin", GDM_KEY_TIMED_LOGIN_ENABLE); /* Setup Allow remote timed logins */ setup_notify_toggle ("allowremoteauto", GDM_KEY_ALLOW_REMOTE_AUTOLOGIN); /* Setup Configure XDMCP button */ XDMCPbutton = glade_helper_get (xml, "config_xserverbutton", GTK_TYPE_BUTTON); setup_xdmcp_support (); g_signal_connect (G_OBJECT (XDMCPbutton), "clicked", G_CALLBACK (xserver_button_clicked), NULL); } static GList * get_file_list_from_uri_list (gchar *uri_list) { GList *list = NULL; gchar **uris = NULL; gint index; if (uri_list == NULL) { return NULL; } uris = g_uri_list_extract_uris (uri_list); for (index = 0; uris[index] != NULL; index++) { gchar *filename; if (g_path_is_absolute (uris[index]) == TRUE) { filename = g_strdup (uris[index]); } else { gchar *host = NULL; filename = g_filename_from_uri (uris[index], &host, NULL); /* Sorry, we can only accept local files. */ if (host != NULL) { g_free (filename); g_free (host); filename = NULL; } } if (filename != NULL) { list = g_list_prepend (list, filename); } } g_strfreev (uris); return g_list_reverse (list); } static void theme_list_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer extra_data) { GtkWidget *parent; GtkWidget *theme_list; GtkListStore *store; GList *list; parent = glade_helper_get (xml, "setup_dialog", GTK_TYPE_WINDOW); theme_list = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (theme_list))); gtk_drag_finish (context, TRUE, FALSE, time); for (list = get_file_list_from_uri_list ((gchar *)data->data); list != NULL; list = list-> next) { GtkWidget *prompt; gchar *base; gchar *mesg; gchar *detail; gint response; base = g_path_get_basename ((gchar *)list->data); mesg = g_strdup_printf (_("Install the theme from '%s'?"), base); detail = g_strdup_printf (_("Select install to add the theme from the file '%s'."), (gchar *)list->data); prompt = ve_hig_dialog_new (GTK_WINDOW (parent), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, mesg, detail); gtk_dialog_add_button (GTK_DIALOG (prompt), "gtk-cancel", GTK_RESPONSE_CANCEL); gtk_dialog_add_button (GTK_DIALOG (prompt), _("_Install"), GTK_RESPONSE_OK); response = gtk_dialog_run (GTK_DIALOG (prompt)); gtk_widget_destroy (prompt); g_free (mesg); if (response == GTK_RESPONSE_OK) { install_theme_file (list->data, store, GTK_WINDOW (parent)); } } } static gboolean theme_list_equal_func (GtkTreeModel * model, gint column, const gchar * key, GtkTreeIter * iter, gpointer search_data) { gboolean results = TRUE; gchar *name; gtk_tree_model_get (model, iter, THEME_COLUMN_MARKUP, &name, -1); if (name != NULL) { gchar * casefold_key; gchar * casefold_name; casefold_key = g_utf8_casefold (key, -1); casefold_name = g_utf8_casefold (name, -1); if ((casefold_key != NULL) && (casefold_name != NULL) && (strstr (casefold_name, casefold_key) != NULL)) { results = FALSE; } g_free (casefold_key); g_free (casefold_name); g_free (name); } return results; } static void setup_local_themed_settings (void) { gboolean GdmGraphicalThemeRand; DIR *dir; GtkListStore *store; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; GtkTreeIter *select_iter = NULL; GtkWidget *color_colorbutton; GtkWidget *style_label; GtkWidget *theme_label; GtkSizeGroup *size_group; char *theme_dir; 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); style_label = glade_helper_get (xml, "local_stylelabel", GTK_TYPE_LABEL); theme_label = glade_helper_get (xml, "local_theme_label", GTK_TYPE_LABEL); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget (size_group, style_label); gtk_size_group_add_widget (size_group, theme_label); color_colorbutton = glade_helper_get (xml, "local_background_theme_colorbutton", GTK_TYPE_COLOR_BUTTON); g_object_set_data (G_OBJECT (color_colorbutton), "key", GDM_KEY_GRAPHICAL_THEMED_COLOR); setup_greeter_color ("local_background_theme_colorbutton", GDM_KEY_GRAPHICAL_THEMED_COLOR); theme_dir = get_theme_dir (); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (theme_list), TRUE); selected_theme = gdm_config_get_string (GDM_KEY_GRAPHICAL_THEME); selected_themes = gdm_config_get_string (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 = gdm_config_get_bool (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 */, GDK_TYPE_PIXBUF /* preview */, G_TYPE_STRING /* markup */, G_TYPE_STRING /* name */, G_TYPE_STRING /* desc */, G_TYPE_STRING /* author */, G_TYPE_STRING /* copyright */); /* 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 preview column */ column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_pixbuf_new (); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", THEME_COLUMN_SCREENSHOT, NULL); /* The markup column */ renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "markup", THEME_COLUMN_MARKUP, NULL); gtk_tree_view_column_set_spacing (column, 6); gtk_tree_view_append_column (GTK_TREE_VIEW (theme_list), column); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), THEME_COLUMN_MARKUP, GTK_SORT_ASCENDING); gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (theme_list), theme_list_equal_func, NULL, NULL); /* 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); gtk_drag_dest_set (theme_list, GTK_DEST_DEFAULT_ALL, target_table, n_targets, GDK_ACTION_COPY); g_signal_connect (theme_list, "drag_data_received", G_CALLBACK (theme_list_drag_data_received), 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) { 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) { gint exit_status; if (g_spawn_command_line_sync ("gnome-open ghelp:gdm", NULL, NULL, &exit_status, NULL) && exit_status == 0) return; } /* 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."), custom_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 background_filechooser_response (GtkWidget *file_chooser, gpointer data) { gchar *filename = NULL; gchar *key; gchar *value; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser)); key = g_object_get_data (G_OBJECT (file_chooser), "key"); value = gdm_config_get_string (key); /* * File_name should never be NULL, but something about this GUI causes * this function to get called on startup and filename=NULL even * though we set the filename in hookup_*_background. Resetting the * value to the default in this case seems to work around this. */ if (filename == NULL && !ve_string_empty (value)) filename = g_strdup (value); if (filename != NULL && (strcmp (ve_sure_string (value), ve_sure_string (filename)) != 0)) { gchar *old_filename; old_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser)); if (strcmp (old_filename, filename) == 0) gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (file_chooser), filename); g_free (old_filename); if (strcmp (ve_sure_string (value), ve_sure_string (filename)) != 0) { gdm_setup_config_set_string (key, (char *)ve_sure_string (filename)); update_greeters (); } } g_free (filename); } static void logo_filechooser_response (GtkWidget *file_chooser, gpointer data) { GtkWidget *image_toggle; gchar *filename; gchar *key; gchar *value; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser)); key = g_object_get_data (G_OBJECT (file_chooser), "key"); value = gdm_config_get_string (key); /* * File_name should never be NULL, but something about this GUI causes * this function to get called on startup and filename=NULL even * though we set the filename in hookup_*_background. Resetting the * value to the default in this case seems to work around this. */ if (filename == NULL && !ve_string_empty (value)) filename = g_strdup (value); if (filename == NULL) { value = gdm_config_get_string (GDM_KEY_CHOOSER_BUTTON_LOGO); if (!ve_string_empty (value)) filename = g_strdup (value); } if (gtk_notebook_get_current_page (GTK_NOTEBOOK (setup_notebook)) == LOCAL_TAB) { image_toggle = glade_helper_get (xml, "remote_logo_image_checkbutton", GTK_TYPE_CHECK_BUTTON); } else { image_toggle = glade_helper_get (xml, "remote_logo_image_checkbutton", GTK_TYPE_CHECK_BUTTON); } if (filename != NULL && (strcmp (ve_sure_string (value), ve_sure_string (filename)) != 0)) { gchar *old_filename; old_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser)); if (strcmp (old_filename, filename) != 0) gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (file_chooser), filename); g_free (old_filename); if (GTK_TOGGLE_BUTTON (image_toggle)->active == TRUE) { gdm_setup_config_set_string (key, (char *)ve_sure_string (filename)); update_greeters (); } } g_free (filename); } static GdkPixbuf * create_preview_pixbuf (gchar *uri) { GdkPixbuf *pixbuf = NULL; if ((uri != NULL) && (uri[0] != '\0')) { gchar *file = NULL; if (g_path_is_absolute (uri) == TRUE) { file = g_strdup (uri); } else { /* URIs are local, because gtk_file_chooser_get_local_only() is true. */ file = g_filename_from_uri (uri, NULL, NULL); } if (file != NULL) { GdkPixbufFormat *info; gint width; gint height; info = gdk_pixbuf_get_file_info (file, &width, &height); if (width > 128 || height > 128) { pixbuf = gdk_pixbuf_new_from_file_at_size (file, 128, 128, NULL); } else { pixbuf = gdk_pixbuf_new_from_file (file, NULL); } g_free (file); } } return pixbuf; } static void update_image_preview (GtkFileChooser *chooser) { GtkWidget *image; gchar *uri; image = gtk_file_chooser_get_preview_widget (GTK_FILE_CHOOSER (chooser)); uri = gtk_file_chooser_get_preview_uri (chooser); if (uri != NULL) { GdkPixbuf *pixbuf = NULL; pixbuf = create_preview_pixbuf (uri); if (pixbuf != NULL) { gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); g_object_unref (pixbuf); } else { gtk_image_set_from_stock (GTK_IMAGE (image), "gtk-dialog-question", GTK_ICON_SIZE_DIALOG); } } gtk_file_chooser_set_preview_widget_active (chooser, TRUE); } static void hookup_plain_background (void) { /* Initialize and hookup callbacks for plain background settings */ GtkFileFilter *filter; GtkWidget *color_radiobutton; GtkWidget *color_colorbutton; GtkWidget *image_radiobutton; GtkWidget *image_filechooser; GtkWidget *image_scale_to_fit; GtkWidget *image_preview; gchar *background_filename; color_radiobutton = glade_helper_get (xml, "local_background_color_checkbutton", GTK_TYPE_CHECK_BUTTON); color_colorbutton = glade_helper_get (xml, "local_background_colorbutton", GTK_TYPE_COLOR_BUTTON); image_radiobutton = glade_helper_get (xml, "local_background_image_checkbutton", GTK_TYPE_CHECK_BUTTON); image_filechooser = glade_helper_get (xml, "local_background_image_chooserbutton", GTK_TYPE_FILE_CHOOSER_BUTTON); image_scale_to_fit = glade_helper_get (xml, "sg_scale_background", GTK_TYPE_CHECK_BUTTON); setup_greeter_color ("local_background_colorbutton", GDM_KEY_BACKGROUND_COLOR); setup_greeter_toggle ("sg_scale_background", GDM_KEY_BACKGROUND_SCALE_TO_FIT); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_scale_to_fit), gdm_config_get_bool (GDM_KEY_BACKGROUND_SCALE_TO_FIT)); filter = gtk_file_filter_new (); gtk_file_filter_set_name (filter, _("Images")); gtk_file_filter_add_pixbuf_formats (filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (image_filechooser), filter); 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 (image_filechooser), filter); background_filename = gdm_config_get_string (GDM_KEY_BACKGROUND_IMAGE); if (ve_string_empty (background_filename)) { gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (image_filechooser), PIXMAPDIR); } else { gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (image_filechooser), background_filename); } switch (gdm_config_get_int (GDM_KEY_BACKGROUND_TYPE)) { case BACKGROUND_IMAGE_AND_COLOR: { /* Image & Color background type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), TRUE); gtk_widget_set_sensitive (image_scale_to_fit, TRUE); gtk_widget_set_sensitive (image_filechooser, TRUE); gtk_widget_set_sensitive (color_colorbutton, TRUE); break; } case BACKGROUND_COLOR: { /* Color background type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), TRUE); gtk_widget_set_sensitive (image_scale_to_fit, FALSE); gtk_widget_set_sensitive (image_filechooser, FALSE); gtk_widget_set_sensitive (color_colorbutton, TRUE); break; } case BACKGROUND_IMAGE: { /* Image background type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), FALSE); gtk_widget_set_sensitive (image_scale_to_fit, TRUE); gtk_widget_set_sensitive (image_filechooser, TRUE); gtk_widget_set_sensitive (color_colorbutton, FALSE); break; } default: { /* No background type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), FALSE); gtk_widget_set_sensitive (color_colorbutton, FALSE); gtk_widget_set_sensitive (image_scale_to_fit, FALSE); gtk_widget_set_sensitive (image_filechooser, FALSE); } } gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (image_filechooser), FALSE); image_preview = gtk_image_new (); if (!ve_string_empty (background_filename)) { gtk_image_set_from_pixbuf (GTK_IMAGE (image_preview), create_preview_pixbuf (background_filename)); } gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (image_filechooser), image_preview); gtk_widget_set_size_request (image_preview, 128, -1); gtk_widget_show (image_preview); g_object_set_data (G_OBJECT (color_radiobutton), "key", GDM_KEY_BACKGROUND_TYPE); g_object_set_data (G_OBJECT (color_colorbutton), "key", GDM_KEY_BACKGROUND_COLOR); g_object_set_data (G_OBJECT (image_radiobutton), "key", GDM_KEY_BACKGROUND_TYPE); g_object_set_data (G_OBJECT (image_filechooser), "key", GDM_KEY_BACKGROUND_IMAGE); g_object_set_data (G_OBJECT (image_scale_to_fit), "key", GDM_KEY_BACKGROUND_SCALE_TO_FIT); g_signal_connect (G_OBJECT (color_radiobutton), "toggled", G_CALLBACK (local_background_type_toggled), NULL); g_signal_connect (G_OBJECT (color_radiobutton), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), color_colorbutton); g_signal_connect (G_OBJECT (image_radiobutton), "toggled", G_CALLBACK (local_background_type_toggled), NULL); g_signal_connect (G_OBJECT (image_radiobutton), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), image_filechooser); g_signal_connect (G_OBJECT (image_radiobutton), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), image_scale_to_fit); g_signal_connect (G_OBJECT (image_filechooser), "selection-changed", G_CALLBACK (background_filechooser_response), image_filechooser); g_signal_connect (G_OBJECT (image_filechooser), "update-preview", G_CALLBACK (update_image_preview), NULL); } static void hookup_plain_logo (void) { /* Initialize and hookup callbacks for plain logo settings */ GtkFileFilter *filter; GtkWidget *logo_checkbutton; GtkWidget *logo_button; GtkWidget *image_preview; gchar *logo_filename; logo_checkbutton = glade_helper_get (xml, "local_logo_image_checkbutton", GTK_TYPE_CHECK_BUTTON); logo_button = glade_helper_get (xml, "local_logo_image_chooserbutton", GTK_TYPE_FILE_CHOOSER_BUTTON); gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (logo_button), FALSE); filter = gtk_file_filter_new (); gtk_file_filter_set_name (filter, _("Images")); gtk_file_filter_add_pixbuf_formats (filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (logo_button), filter); 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 (logo_button), filter); logo_filename = gdm_config_get_string (GDM_KEY_LOGO); if (ve_string_empty (logo_filename)) { logo_filename = gdm_config_get_string (GDM_KEY_CHOOSER_BUTTON_LOGO); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (logo_checkbutton), FALSE); gtk_widget_set_sensitive (logo_button, FALSE); } else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (logo_checkbutton), TRUE); gtk_widget_set_sensitive (logo_button, TRUE); } if (ve_string_empty (logo_filename)) { gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (logo_button), PIXMAPDIR); } else { gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (logo_button), logo_filename); } image_preview = gtk_image_new (); if (!ve_string_empty (logo_filename)) { gtk_image_set_from_pixbuf (GTK_IMAGE (image_preview), create_preview_pixbuf (logo_filename)); } gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (logo_button), image_preview); gtk_widget_set_size_request (image_preview, 128, -1); gtk_widget_show (image_preview); g_object_set_data (G_OBJECT (logo_button), "key", GDM_KEY_LOGO); g_object_set_data (G_OBJECT (logo_checkbutton), "key", GDM_KEY_LOGO); g_signal_connect (G_OBJECT (logo_checkbutton), "toggled", G_CALLBACK (logo_toggle_toggled), NULL); g_signal_connect (G_OBJECT (logo_checkbutton), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), logo_button); g_signal_connect (G_OBJECT (logo_button), "selection-changed", G_CALLBACK (logo_filechooser_response), logo_button); g_signal_connect (G_OBJECT (logo_button), "update-preview", G_CALLBACK (update_image_preview), NULL); } static void setup_plain_menubar (void) { /* Initialize and hookup callbacks for plain menu bar settings */ setup_notify_toggle ("sysmenu", GDM_KEY_SYSTEM_MENU); setup_notify_toggle ("config_available", GDM_KEY_CONFIG_AVAILABLE); setup_notify_toggle ("chooser_button", GDM_KEY_CHOOSER_BUTTON); } static void setup_local_welcome_message (void) { /* Initialize and hookup callbacks for local welcome message settings */ setup_greeter_toggle ("sg_defaultwelcome", GDM_KEY_DEFAULT_WELCOME); setup_greeter_untranslate_entry ("welcome", GDM_KEY_WELCOME); } static void setup_remote_welcome_message (void) { /* Initialize and hookup callbacks for local welcome message settings */ setup_greeter_toggle ("sg_defaultwelcomeremote", GDM_KEY_DEFAULT_REMOTE_WELCOME); setup_greeter_untranslate_entry ("welcomeremote", GDM_KEY_REMOTE_WELCOME); } static void setup_local_plain_settings (void) { /* Style setting */ setup_greeter_combobox ("local_greeter", GDM_KEY_GREETER); /* Plain background settings */ hookup_plain_background (); /* Plain logo settings */ hookup_plain_logo (); /* Plain menu bar settings */ setup_plain_menubar (); /* Local welcome message settings */ setup_local_welcome_message (); } static void setup_local_tab (void) { setup_local_plain_settings (); setup_local_themed_settings (); } static void hookup_remote_plain_background (void) { /* Initialize and hookup callbacks for plain background settings */ GtkFileFilter *filter; GtkWidget *color_radiobutton; GtkWidget *color_colorbutton; GtkWidget *image_radiobutton; GtkWidget *image_filechooser; GtkWidget *image_scale_to_fit; GtkWidget *image_preview; gchar *background_filename; color_radiobutton = glade_helper_get (xml, "remote_background_color_checkbutton", GTK_TYPE_CHECK_BUTTON); color_colorbutton = glade_helper_get (xml, "remote_background_colorbutton", GTK_TYPE_COLOR_BUTTON); image_radiobutton = glade_helper_get (xml, "remote_background_image_checkbutton", GTK_TYPE_CHECK_BUTTON); image_filechooser = glade_helper_get (xml, "remote_background_image_chooserbutton", GTK_TYPE_FILE_CHOOSER_BUTTON); image_scale_to_fit = glade_helper_get (xml, "sg_scale_background_remote", GTK_TYPE_CHECK_BUTTON); setup_greeter_color ("remote_background_colorbutton", GDM_KEY_BACKGROUND_COLOR); setup_greeter_toggle ("sg_scale_background_remote", GDM_KEY_BACKGROUND_SCALE_TO_FIT); setup_greeter_toggle ("sg_remote_color_only", GDM_KEY_BACKGROUND_REMOTE_ONLY_COLOR); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_scale_to_fit), gdm_config_get_bool (GDM_KEY_BACKGROUND_SCALE_TO_FIT)); filter = gtk_file_filter_new (); gtk_file_filter_set_name (filter, _("Images")); gtk_file_filter_add_pixbuf_formats (filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (image_filechooser), filter); 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 (image_filechooser), filter); background_filename = gdm_config_get_string (GDM_KEY_BACKGROUND_IMAGE); if (ve_string_empty (background_filename)) { gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (image_filechooser), PIXMAPDIR); } else { gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (image_filechooser), background_filename); } switch (gdm_config_get_int (GDM_KEY_BACKGROUND_TYPE)) { case BACKGROUND_IMAGE_AND_COLOR: { /* Image & Color background type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), TRUE); gtk_widget_set_sensitive (image_scale_to_fit, TRUE); gtk_widget_set_sensitive (image_filechooser, TRUE); gtk_widget_set_sensitive (color_colorbutton, TRUE); break; } case BACKGROUND_COLOR: { /* Color background type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), TRUE); gtk_widget_set_sensitive (image_scale_to_fit, FALSE); gtk_widget_set_sensitive (image_filechooser, FALSE); gtk_widget_set_sensitive (color_colorbutton, TRUE); break; } case BACKGROUND_IMAGE: { /* Image background type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), FALSE); gtk_widget_set_sensitive (image_scale_to_fit, TRUE); gtk_widget_set_sensitive (image_filechooser, TRUE); gtk_widget_set_sensitive (color_colorbutton, FALSE); break; } default: { /* No background type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (image_radiobutton), FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (color_radiobutton), FALSE); gtk_widget_set_sensitive (color_colorbutton, FALSE); gtk_widget_set_sensitive (image_scale_to_fit, FALSE); gtk_widget_set_sensitive (image_filechooser, FALSE); } } gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (image_filechooser), FALSE); image_preview = gtk_image_new (); if (!ve_string_empty (background_filename)) { gtk_image_set_from_pixbuf (GTK_IMAGE (image_preview), create_preview_pixbuf (background_filename)); } gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (image_filechooser), image_preview); gtk_widget_set_size_request (image_preview, 128, -1); gtk_widget_show (image_preview); g_object_set_data (G_OBJECT (color_radiobutton), "key", GDM_KEY_BACKGROUND_TYPE); g_object_set_data (G_OBJECT (color_colorbutton), "key", GDM_KEY_BACKGROUND_COLOR); g_object_set_data (G_OBJECT (image_radiobutton), "key", GDM_KEY_BACKGROUND_TYPE); g_object_set_data (G_OBJECT (image_filechooser), "key", GDM_KEY_BACKGROUND_IMAGE); g_object_set_data (G_OBJECT (image_scale_to_fit), "key", GDM_KEY_BACKGROUND_SCALE_TO_FIT); g_signal_connect (G_OBJECT (color_radiobutton), "toggled", G_CALLBACK (local_background_type_toggled), NULL); g_signal_connect (G_OBJECT (color_radiobutton), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), color_colorbutton); g_signal_connect (G_OBJECT (image_radiobutton), "toggled", G_CALLBACK (local_background_type_toggled), NULL); g_signal_connect (G_OBJECT (image_radiobutton), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), image_filechooser); g_signal_connect (G_OBJECT (image_radiobutton), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), image_scale_to_fit); g_signal_connect (G_OBJECT (image_filechooser), "selection-changed", G_CALLBACK (background_filechooser_response), image_filechooser); g_signal_connect (G_OBJECT (image_filechooser), "update-preview", G_CALLBACK (update_image_preview), NULL); } static void hookup_remote_plain_logo (void) { /* Initialize and hookup callbacks for plain logo settings */ GtkFileFilter *filter; GtkWidget *logo_checkbutton; GtkWidget *logo_button; GtkWidget *image_preview; gchar *logo_filename; logo_checkbutton = glade_helper_get (xml, "remote_logo_image_checkbutton", GTK_TYPE_CHECK_BUTTON); logo_button = glade_helper_get (xml, "remote_logo_image_chooserbutton", GTK_TYPE_FILE_CHOOSER_BUTTON); gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (logo_button), FALSE); filter = gtk_file_filter_new (); gtk_file_filter_set_name (filter, _("Images")); gtk_file_filter_add_pixbuf_formats (filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (logo_button), filter); 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 (logo_button), filter); logo_filename = gdm_config_get_string (GDM_KEY_LOGO); if (ve_string_empty (logo_filename)) { logo_filename = gdm_config_get_string (GDM_KEY_CHOOSER_BUTTON_LOGO); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (logo_checkbutton), FALSE); gtk_widget_set_sensitive (logo_button, FALSE); } else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (logo_checkbutton), TRUE); gtk_widget_set_sensitive (logo_button, TRUE); } if (ve_string_empty (logo_filename)) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (logo_button), PIXMAPDIR); else gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (logo_button), logo_filename); image_preview = gtk_image_new (); if (!ve_string_empty (logo_filename)) { gtk_image_set_from_pixbuf (GTK_IMAGE (image_preview), create_preview_pixbuf (logo_filename)); } gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (logo_button), image_preview); gtk_widget_set_size_request (image_preview, 128, -1); gtk_widget_show (image_preview); g_object_set_data (G_OBJECT (logo_button), "key", GDM_KEY_LOGO); g_object_set_data (G_OBJECT (logo_checkbutton), "key", GDM_KEY_LOGO); g_signal_connect (G_OBJECT (logo_checkbutton), "toggled", G_CALLBACK (logo_toggle_toggled), NULL); g_signal_connect (G_OBJECT (logo_checkbutton), "toggled", G_CALLBACK (toggle_toggled_sensitivity_positive), logo_button); g_signal_connect (G_OBJECT (logo_button), "selection-changed", G_CALLBACK (logo_filechooser_response), logo_button); g_signal_connect (G_OBJECT (logo_button), "update-preview", G_CALLBACK (update_image_preview), NULL); } static void setup_remote_plain_settings (void) { GtkSizeGroup *size_group; GtkWidget *image_checkbutton; GtkWidget *color_checkbutton; image_checkbutton = glade_helper_get (xml, "remote_background_image_checkbutton", GTK_TYPE_CHECK_BUTTON); color_checkbutton = glade_helper_get (xml, "remote_background_color_checkbutton", GTK_TYPE_CHECK_BUTTON); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget (size_group, image_checkbutton); gtk_size_group_add_widget (size_group, color_checkbutton); /* Style setting */ setup_greeter_combobox ("remote_greeter", GDM_KEY_REMOTE_GREETER); /* Plain background settings */ hookup_remote_plain_background (); /* Plain logo settings */ hookup_remote_plain_logo (); /* Remote welcome message settings */ setup_remote_welcome_message (); } static void setup_remote_themed_settings (void) { gboolean GdmGraphicalThemeRand; GtkListStore *store; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; GtkTreeIter *select_iter = NULL; GtkWidget *color_colorbutton; GtkWidget *style_label; GtkWidget *theme_label; GtkSizeGroup *size_group; GtkWidget *theme_list = glade_helper_get (xml, "gg_theme_list_remote", GTK_TYPE_TREE_VIEW); GtkWidget *theme_list_local = glade_helper_get (xml, "gg_theme_list", GTK_TYPE_TREE_VIEW); GtkWidget *button = glade_helper_get (xml, "gg_install_new_theme_remote", GTK_TYPE_BUTTON); GtkWidget *del_button = glade_helper_get (xml, "gg_delete_theme_remote", GTK_TYPE_BUTTON); GtkWidget *mode_combobox = glade_helper_get (xml, "gg_mode_combobox_remote", GTK_TYPE_COMBO_BOX); style_label = glade_helper_get (xml, "remote_stylelabel", GTK_TYPE_LABEL); theme_label = glade_helper_get (xml, "remote_theme_label", GTK_TYPE_LABEL); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget (size_group, style_label); gtk_size_group_add_widget (size_group, theme_label); color_colorbutton = glade_helper_get (xml, "remote_background_theme_colorbutton", GTK_TYPE_COLOR_BUTTON); g_object_set_data (G_OBJECT (color_colorbutton), "key", GDM_KEY_GRAPHICAL_THEMED_COLOR); setup_greeter_color ("remote_background_theme_colorbutton", GDM_KEY_GRAPHICAL_THEMED_COLOR); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (theme_list), TRUE); GdmGraphicalThemeRand = gdm_config_get_bool (GDM_KEY_GRAPHICAL_THEME_RAND); /* Register theme mode combobox */ g_object_set_data_full (G_OBJECT (mode_combobox), "key", g_strdup (GDM_KEY_GRAPHICAL_THEME_RAND), (GDestroyNotify) g_free); store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (theme_list_local))); gtk_tree_view_set_model (GTK_TREE_VIEW (theme_list), GTK_TREE_MODEL (store)); /* 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); /* 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 preview column */ column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_pixbuf_new (); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", THEME_COLUMN_SCREENSHOT, NULL); /* The markup column */ renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "markup", THEME_COLUMN_MARKUP, NULL); gtk_tree_view_column_set_spacing (column, 6); gtk_tree_view_append_column (GTK_TREE_VIEW (theme_list), column); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), THEME_COLUMN_MARKUP, GTK_SORT_ASCENDING); gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (theme_list), theme_list_equal_func, NULL, NULL); /* 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); gtk_drag_dest_set (theme_list, GTK_DEST_DEFAULT_ALL, target_table, n_targets, GDK_ACTION_COPY); g_signal_connect (theme_list, "drag_data_received", G_CALLBACK (theme_list_drag_data_received), NULL); if (select_iter != NULL) { gtk_tree_selection_select_iter (selection, select_iter); g_free (select_iter); } } static void setup_remote_tab (void) { GtkWidget *xdmcp_button; xdmcp_button = glade_helper_get (xml, "xdmcp_configbutton", GTK_TYPE_BUTTON); #ifndef HAVE_LIBXDMCP gtk_widget_set_sensitive (xdmcp_button, FALSE); #else g_signal_connect (G_OBJECT (xdmcp_button), "clicked", G_CALLBACK (xdmcp_button_clicked), NULL); #endif setup_remote_plain_settings (); setup_remote_themed_settings (); } static GtkWidget * setup_gui (void) { GtkWidget *dialog; 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); 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_notebook = glade_helper_get (xml, "setup_notebook", GTK_TYPE_NOTEBOOK); /* Markup glade labels */ glade_helper_tagify_label (xml, "themes_label", "b"); glade_helper_tagify_label (xml, "sounds_label", "b"); glade_helper_tagify_label (xml, "local_background_label", "b"); glade_helper_tagify_label (xml, "local_logo_label", "b"); glade_helper_tagify_label (xml, "local_menubar_label", "b"); glade_helper_tagify_label (xml, "local_welcome_message_label", "b"); glade_helper_tagify_label (xml, "label_welcome_note", "i"); glade_helper_tagify_label (xml, "label_welcome_note", "small"); glade_helper_tagify_label (xml, "gg_author_label", "b"); glade_helper_tagify_label (xml, "gg_author_label", "small"); glade_helper_tagify_label (xml, "gg_copyright_label", "b"); glade_helper_tagify_label (xml, "gg_copyright_label", "small"); glade_helper_tagify_label (xml, "remote_plain_background_label", "b"); glade_helper_tagify_label (xml, "remote_logo_label", "b"); glade_helper_tagify_label (xml, "remote_welcome_message_label", "b"); glade_helper_tagify_label (xml, "label_welcomeremote_note", "i"); glade_helper_tagify_label (xml, "label_welcomeremote_note", "small"); glade_helper_tagify_label (xml, "autologin", "b"); glade_helper_tagify_label (xml, "timedlogin", "b"); glade_helper_tagify_label (xml, "security_label", "b"); glade_helper_tagify_label (xml, "xforwarding_label", "i"); glade_helper_tagify_label (xml, "xforwarding_label", "small"); glade_helper_tagify_label (xml, "fb_informationlabel", "i"); glade_helper_tagify_label (xml, "fb_informationlabel", "small"); /* Setup preference tabs */ setup_local_tab (); setup_remote_tab (); setup_accessibility_tab (); setup_security_tab (); setup_users_tab (); return (dialog); } 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; } static void apply_user_changes (GObject *object, gint arg1, gpointer user_data) { GtkWidget *dialog = user_data; if (GdmUserChangesUnsaved == TRUE) { GtkWidget *prompt; gint response; prompt = ve_hig_dialog_new (GTK_WINDOW (dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, _("Apply the changes to users before closing?"), _("If you don't apply, the changes made on " "the Users tab will be disregarded.")); gtk_dialog_add_button (GTK_DIALOG (prompt), _("Close _without Applying"), GTK_RESPONSE_CLOSE); gtk_dialog_add_button (GTK_DIALOG (prompt), "gtk-cancel", GTK_RESPONSE_CANCEL); gtk_dialog_add_button (GTK_DIALOG (prompt), "gtk-apply", GTK_RESPONSE_APPLY); response = gtk_dialog_run (GTK_DIALOG (prompt)); gtk_widget_destroy (prompt); if (response == GTK_RESPONSE_APPLY) { GtkWidget *apply_button; apply_button = glade_helper_get (xml, "fb_faceapply", GTK_TYPE_WIDGET); g_signal_emit_by_name (G_OBJECT (apply_button), "clicked"); } gtk_main_quit (); if (response == GTK_RESPONSE_CANCEL) { gtk_main (); } } } int main (int argc, char *argv[]) { GtkWidget *dialog; gdm_config_never_cache (TRUE); 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); gtk_init (&argc, &argv); gtk_window_set_default_icon_from_file (DATADIR"/pixmaps/gdm-setup.png", NULL); glade_gnome_init(); /* Start using socket */ gdmcomm_comm_bulk_start (); config_file = gdm_common_get_config_file (); if (config_file == NULL) { /* Done using socket */ gdmcomm_comm_bulk_stop (); g_print (_("Could not access GDM configuration file.\n")); exit (EXIT_FAILURE); } custom_config_file = gdm_common_get_custom_config_file (); if (custom_config_file == NULL) { /* Done using socket */ gdmcomm_comm_bulk_stop (); g_print (_("Could not access GDM configuration file.\n")); exit (EXIT_FAILURE); } gdm_running = gdmcomm_check (FALSE); if (RUNNING_UNDER_GDM) { char *gtkrc; char *theme_name; /* Set busy cursor */ setup_cursor (GDK_WATCH); /* parse the given gtk rc first */ gtkrc = gdm_config_get_string (GDM_KEY_GTKRC); if ( ! ve_string_empty (gtkrc)) gtk_rc_parse (gtkrc); theme_name = g_strdup (g_getenv ("GDM_GTK_THEME")); if (ve_string_empty (theme_name)) { g_free (theme_name); theme_name = gdm_config_get_string (GDM_KEY_GTK_THEME); gdm_set_theme (theme_name); } else { 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; /* Done using socket */ gdmcomm_comm_bulk_stop (); 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 = gdm_config_get_int (GDM_KEY_MAX_ICON_HEIGHT); GdmIconMaxWidth = gdm_config_get_int (GDM_KEY_MAX_ICON_WIDTH); GdmMinimalUID = gdm_config_get_int (GDM_KEY_MINIMAL_UID); GdmIncludeAll = gdm_config_get_bool (GDM_KEY_INCLUDE_ALL); GdmInclude = gdm_config_get_string (GDM_KEY_INCLUDE); GdmExclude = gdm_config_get_string (GDM_KEY_EXCLUDE); GdmSoundProgram = gdm_config_get_string (GDM_KEY_SOUND_PROGRAM); GdmAllowRoot = gdm_config_get_bool (GDM_KEY_ALLOW_ROOT); GdmAllowRemoteRoot = gdm_config_get_bool (GDM_KEY_ALLOW_REMOTE_ROOT); if (ve_string_empty (GdmSoundProgram) || g_access (GdmSoundProgram, X_OK) != 0) { GdmSoundProgram = NULL; } xservers = gdm_config_get_xservers (FALSE); dialog = setup_gui (); /* Done using socket */ gdmcomm_comm_bulk_stop (); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (apply_user_changes), dialog); gtk_widget_show (dialog); 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 */