From fff4ecc82f2bcfa7427596e7ad9c3769fcab040b Mon Sep 17 00:00:00 2001 From: Perberos Date: Fri, 4 Nov 2011 22:16:15 -0300 Subject: first commit --- src/mate-screensaver-preferences.c | 1781 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1781 insertions(+) create mode 100644 src/mate-screensaver-preferences.c (limited to 'src/mate-screensaver-preferences.c') diff --git a/src/mate-screensaver-preferences.c b/src/mate-screensaver-preferences.c new file mode 100644 index 0000000..5bcf5e5 --- /dev/null +++ b/src/mate-screensaver-preferences.c @@ -0,0 +1,1781 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2004-2006 William Jon McCann + * + * 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. + * + * Authors: William Jon McCann + * Rodrigo Moya + * + */ + +#include "config.h" + +#define _GNU_SOURCE +#include +#include +#include +#include /* For uid_t, gid_t */ + +#include +#include +#include +#include + +#include + +#include "copy-theme-dialog.h" + +#include "gs-theme-manager.h" +#include "gs-job.h" +#include "gs-prefs.h" /* for GS_MODE enum */ + +#define GTK_BUILDER_FILE "mate-screensaver-preferences.ui" + +#define MATE_LOCKDOWN_DIR "/desktop/mate/lockdown" +#define KEY_LOCK_DISABLE MATE_LOCKDOWN_DIR "/disable_lock_screen" + +#define KEY_DIR "/apps/mate-screensaver" +#define MATE_SESSION_DIR "/desktop/mate/session" +#define KEY_LOCK KEY_DIR "/lock_enabled" +#define KEY_IDLE_ACTIVATION_ENABLED KEY_DIR "/idle_activation_enabled" +#define KEY_MODE KEY_DIR "/mode" +#define KEY_ACTIVATE_DELAY MATE_SESSION_DIR "/idle_delay" +#define KEY_LOCK_DELAY KEY_DIR "/lock_delay" +#define KEY_CYCLE_DELAY KEY_DIR "/cycle_delay" +#define KEY_THEMES KEY_DIR "/themes" + +#define GPM_COMMAND "mate-power-preferences" + +enum +{ + NAME_COLUMN = 0, + ID_COLUMN, + N_COLUMNS +}; + +static MateConfEnumStringPair mode_enum_map [] = +{ + { GS_MODE_BLANK_ONLY, "blank-only" }, + { GS_MODE_RANDOM, "random" }, + { GS_MODE_SINGLE, "single" }, + { 0, NULL } +}; + +/* Drag and drop info */ +enum +{ + TARGET_URI_LIST, + TARGET_NS_URL +}; + +static GtkTargetEntry drop_types [] = +{ + { "text/uri-list", 0, TARGET_URI_LIST }, + { "_NETSCAPE_URL", 0, TARGET_NS_URL } +}; + +static GtkBuilder *builder = NULL; +static GSThemeManager *theme_manager = NULL; +static GSJob *job = NULL; + +static gint32 +config_get_activate_delay (gboolean *is_writable) +{ + MateConfClient *client; + gint32 delay; + + client = mateconf_client_get_default (); + + if (is_writable) + { + *is_writable = mateconf_client_key_is_writable (client, + KEY_ACTIVATE_DELAY, + NULL); + } + + delay = mateconf_client_get_int (client, KEY_ACTIVATE_DELAY, NULL); + + if (delay < 1) + { + delay = 1; + } + + g_object_unref (client); + + return delay; +} + +static void +config_set_activate_delay (gint32 timeout) +{ + MateConfClient *client; + + client = mateconf_client_get_default (); + + mateconf_client_set_int (client, KEY_ACTIVATE_DELAY, timeout, NULL); + + g_object_unref (client); +} + +static int +config_get_mode (gboolean *is_writable) +{ + MateConfClient *client; + int mode; + char *string; + + client = mateconf_client_get_default (); + + if (is_writable) + { + *is_writable = mateconf_client_key_is_writable (client, + KEY_MODE, + NULL); + } + + string = mateconf_client_get_string (client, KEY_MODE, NULL); + if (string) + { + mateconf_string_to_enum (mode_enum_map, string, &mode); + g_free (string); + } + else + { + mode = GS_MODE_BLANK_ONLY; + } + + g_object_unref (client); + + return mode; +} + +static void +config_set_mode (int mode) +{ + MateConfClient *client; + const char *mode_string; + + client = mateconf_client_get_default (); + + mode_string = mateconf_enum_to_string (mode_enum_map, mode); + mateconf_client_set_string (client, KEY_MODE, mode_string, NULL); + + g_object_unref (client); +} + +static char * +config_get_theme (gboolean *is_writable) +{ + MateConfClient *client; + char *name; + int mode; + + client = mateconf_client_get_default (); + + if (is_writable) + { + gboolean can_write_theme; + gboolean can_write_mode; + + can_write_theme = mateconf_client_key_is_writable (client, + KEY_THEMES, + NULL); + can_write_mode = mateconf_client_key_is_writable (client, + KEY_MODE, + NULL); + *is_writable = can_write_theme && can_write_mode; + } + + mode = config_get_mode (NULL); + + name = NULL; + if (mode == GS_MODE_BLANK_ONLY) + { + name = g_strdup ("__blank-only"); + } + else if (mode == GS_MODE_RANDOM) + { + name = g_strdup ("__random"); + } + else + { + GSList *list; + list = mateconf_client_get_list (client, + KEY_THEMES, + MATECONF_VALUE_STRING, + NULL); + if (list != NULL) + { + name = g_strdup (list->data); + } + else + { + /* TODO: handle error */ + /* default to blank */ + name = g_strdup ("__blank-only"); + } + + g_slist_foreach (list, (GFunc)g_free, NULL); + g_slist_free (list); + } + + g_object_unref (client); + + return name; +} + +static GSList * +get_all_theme_ids (GSThemeManager *theme_manager) +{ + GSList *ids = NULL; + GSList *entries; + GSList *l; + + entries = gs_theme_manager_get_info_list (theme_manager); + for (l = entries; l; l = l->next) + { + GSThemeInfo *info = l->data; + + ids = g_slist_prepend (ids, g_strdup (gs_theme_info_get_id (info))); + gs_theme_info_unref (info); + } + g_slist_free (entries); + + return ids; +} + +static void +config_set_theme (const char *theme_id) +{ + MateConfClient *client; + GSList *list = NULL; + int mode; + + client = mateconf_client_get_default (); + + if (theme_id && strcmp (theme_id, "__blank-only") == 0) + { + mode = GS_MODE_BLANK_ONLY; + } + else if (theme_id && strcmp (theme_id, "__random") == 0) + { + mode = GS_MODE_RANDOM; + + /* set the themes key to contain all available screensavers */ + list = get_all_theme_ids (theme_manager); + } + else + { + mode = GS_MODE_SINGLE; + list = g_slist_append (list, g_strdup (theme_id)); + } + + config_set_mode (mode); + + mateconf_client_set_list (client, + KEY_THEMES, + MATECONF_VALUE_STRING, + list, + NULL); + + g_slist_foreach (list, (GFunc) g_free, NULL); + g_slist_free (list); + + g_object_unref (client); +} + +static gboolean +config_get_enabled (gboolean *is_writable) +{ + int enabled; + MateConfClient *client; + + client = mateconf_client_get_default (); + + if (is_writable) + { + *is_writable = mateconf_client_key_is_writable (client, + KEY_LOCK, + NULL); + } + + enabled = mateconf_client_get_bool (client, KEY_IDLE_ACTIVATION_ENABLED, NULL); + + g_object_unref (client); + + return enabled; +} + +static void +config_set_enabled (gboolean enabled) +{ + MateConfClient *client; + + client = mateconf_client_get_default (); + + mateconf_client_set_bool (client, KEY_IDLE_ACTIVATION_ENABLED, enabled, NULL); + + g_object_unref (client); +} + +static gboolean +config_get_lock (gboolean *is_writable) +{ + MateConfClient *client; + gboolean lock; + + client = mateconf_client_get_default (); + + if (is_writable) + { + *is_writable = mateconf_client_key_is_writable (client, + KEY_LOCK, + NULL); + } + + lock = mateconf_client_get_bool (client, KEY_LOCK, NULL); + + g_object_unref (client); + + return lock; +} + +static gboolean +config_get_lock_disabled () +{ + MateConfClient *client; + gboolean lock; + + client = mateconf_client_get_default (); + + lock = mateconf_client_get_bool (client, KEY_LOCK_DISABLE, NULL); + + g_object_unref (client); + return lock; +} + +static void +config_set_lock (gboolean lock) +{ + MateConfClient *client; + + client = mateconf_client_get_default (); + + mateconf_client_set_bool (client, KEY_LOCK, lock, NULL); + + g_object_unref (client); +} + +static void +preview_clear (GtkWidget *widget) +{ + GdkColor color = { 0, 0, 0 }; + + gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &color); + gdk_window_clear (widget->window); +} + +static void +job_set_theme (GSJob *job, + const char *theme) +{ + GSThemeInfo *info; + const char *command; + + command = NULL; + + info = gs_theme_manager_lookup_theme_info (theme_manager, theme); + if (info != NULL) + { + command = gs_theme_info_get_exec (info); + } + + gs_job_set_command (job, command); + + if (info != NULL) + { + gs_theme_info_unref (info); + } +} + +static void +preview_set_theme (GtkWidget *widget, + const char *theme, + const char *name) +{ + GtkWidget *label; + char *markup; + + if (job != NULL) + { + gs_job_stop (job); + } + + preview_clear (widget); + + label = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_theme_label")); + markup = g_markup_printf_escaped ("%s", name); + gtk_label_set_markup (GTK_LABEL (label), markup); + g_free (markup); + + if ((theme && strcmp (theme, "__blank-only") == 0)) + { + + } + else if (theme && strcmp (theme, "__random") == 0) + { + GSList *themes; + + themes = get_all_theme_ids (theme_manager); + if (themes != NULL) + { + GSList *l; + gint32 i; + + i = g_random_int_range (0, g_slist_length (themes)); + l = g_slist_nth (themes, i); + + job_set_theme (job, (const char *) l->data); + g_slist_foreach (themes, (GFunc) g_free, NULL); + g_slist_free (themes); + + gs_job_start (job); + } + } + else + { + job_set_theme (job, theme); + gs_job_start (job); + } +} + +static void +help_display (void) +{ + GError *error = NULL; + char *command; + const char *lang; + char *uri = NULL; + GdkScreen *gscreen; + int i; + + const char * const * langs = g_get_language_names (); + + for (i = 0; langs[i] != NULL; i++) + { + lang = langs[i]; + if (strchr (lang, '.')) + { + continue; + } + + uri = g_build_filename (DATADIR, + "/mate/help/user-guide/", + lang, + "/user-guide.xml", + NULL); + + if (g_file_test (uri, G_FILE_TEST_EXISTS)) + { + break; + } + } + + command = g_strconcat ("mate-open ghelp://", + uri, + "?prefs-screensaver", + NULL); + gscreen = gdk_screen_get_default (); + gdk_spawn_command_line_on_screen (gscreen, command, &error); + + if (error != NULL) + { + GtkWidget *d; + + d = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + "%s", error->message); + gtk_dialog_run (GTK_DIALOG (d)); + gtk_widget_destroy (d); + g_error_free (error); + } + + g_free (command); + g_free (uri); +} + +static void +response_cb (GtkWidget *widget, + int response_id) +{ + + if (response_id == GTK_RESPONSE_HELP) + { + help_display (); + } + else if (response_id == GTK_RESPONSE_REJECT) + { + GError *error; + gboolean res; + + error = NULL; + + res = gdk_spawn_command_line_on_screen (gdk_screen_get_default (), + GPM_COMMAND, + &error); + if (! res) + { + g_warning ("Unable to start power management preferences: %s", error->message); + g_error_free (error); + } + } + else + { + gtk_widget_destroy (widget); + gtk_main_quit (); + } +} + +static GSList * +get_theme_info_list (void) +{ + return gs_theme_manager_get_info_list (theme_manager); +} + +static void +populate_model (GtkTreeStore *store) +{ + GtkTreeIter iter; + GSList *themes = NULL; + GSList *l; + + gtk_tree_store_append (store, &iter, NULL); + gtk_tree_store_set (store, &iter, + NAME_COLUMN, _("Blank screen"), + ID_COLUMN, "__blank-only", + -1); + + gtk_tree_store_append (store, &iter, NULL); + gtk_tree_store_set (store, &iter, + NAME_COLUMN, _("Random"), + ID_COLUMN, "__random", + -1); + + gtk_tree_store_append (store, &iter, NULL); + gtk_tree_store_set (store, &iter, + NAME_COLUMN, NULL, + ID_COLUMN, "__separator", + -1); + + themes = get_theme_info_list (); + + if (themes == NULL) + { + return; + } + + for (l = themes; l; l = l->next) + { + const char *name; + const char *id; + GSThemeInfo *info = l->data; + + if (info == NULL) + { + continue; + } + + name = gs_theme_info_get_name (info); + id = gs_theme_info_get_id (info); + + gtk_tree_store_append (store, &iter, NULL); + gtk_tree_store_set (store, &iter, + NAME_COLUMN, name, + ID_COLUMN, id, + -1); + + gs_theme_info_unref (info); + } + + g_slist_free (themes); +} + +static void +tree_selection_previous (GtkTreeSelection *selection) +{ + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + + if (! gtk_tree_selection_get_selected (selection, &model, &iter)) + { + return; + } + + path = gtk_tree_model_get_path (model, &iter); + if (gtk_tree_path_prev (path)) + { + gtk_tree_selection_select_path (selection, path); + } +} + +static void +tree_selection_next (GtkTreeSelection *selection) +{ + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + + if (! gtk_tree_selection_get_selected (selection, &model, &iter)) + { + return; + } + + path = gtk_tree_model_get_path (model, &iter); + gtk_tree_path_next (path); + gtk_tree_selection_select_path (selection, path); +} + +static void +tree_selection_changed_cb (GtkTreeSelection *selection, + GtkWidget *preview) +{ + GtkTreeIter iter; + GtkTreeModel *model; + char *theme; + char *name; + + if (! gtk_tree_selection_get_selected (selection, &model, &iter)) + { + return; + } + + gtk_tree_model_get (model, &iter, ID_COLUMN, &theme, NAME_COLUMN, &name, -1); + + if (theme == NULL) + { + g_free (name); + return; + } + + preview_set_theme (preview, theme, name); + config_set_theme (theme); + + g_free (theme); + g_free (name); +} + +static void +activate_delay_value_changed_cb (GtkRange *range, + gpointer user_data) +{ + gdouble value; + + value = gtk_range_get_value (range); + config_set_activate_delay ((gint32)value); +} + +static int +compare_theme_names (char *name_a, + char *name_b, + char *id_a, + char *id_b) +{ + + if (id_a == NULL) + { + return 1; + } + else if (id_b == NULL) + { + return -1; + } + + if (strcmp (id_a, "__blank-only") == 0) + { + return -1; + } + else if (strcmp (id_b, "__blank-only") == 0) + { + return 1; + } + else if (strcmp (id_a, "__random") == 0) + { + return -1; + } + else if (strcmp (id_b, "__random") == 0) + { + return 1; + } + else if (strcmp (id_a, "__separator") == 0) + { + return -1; + } + else if (strcmp (id_b, "__separator") == 0) + { + return 1; + } + + if (name_a == NULL) + { + return 1; + } + else if (name_b == NULL) + { + return -1; + } + + return g_utf8_collate (name_a, name_b); +} + +static int +compare_theme (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + char *name_a; + char *name_b; + char *id_a; + char *id_b; + int result; + + gtk_tree_model_get (model, a, NAME_COLUMN, &name_a, -1); + gtk_tree_model_get (model, b, NAME_COLUMN, &name_b, -1); + gtk_tree_model_get (model, a, ID_COLUMN, &id_a, -1); + gtk_tree_model_get (model, b, ID_COLUMN, &id_b, -1); + + result = compare_theme_names (name_a, name_b, id_a, id_b); + + g_free (name_a); + g_free (name_b); + g_free (id_a); + g_free (id_b); + + return result; +} + +static gboolean +separator_func (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + int column = GPOINTER_TO_INT (data); + char *text; + + gtk_tree_model_get (model, iter, column, &text, -1); + + if (text != NULL && strcmp (text, "__separator") == 0) + { + return TRUE; + } + + g_free (text); + + return FALSE; +} + +static void +setup_treeview (GtkWidget *tree, + GtkWidget *preview) +{ + GtkTreeStore *store; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkTreeSelection *select; + + store = gtk_tree_store_new (N_COLUMNS, + G_TYPE_STRING, + G_TYPE_STRING); + populate_model (store); + + gtk_tree_view_set_model (GTK_TREE_VIEW (tree), + GTK_TREE_MODEL (store)); + + g_object_unref (store); + +#if GTK_CHECK_VERSION(2,10,0) + g_object_set (tree, "show-expanders", FALSE, NULL); +#endif + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Name", renderer, + "text", NAME_COLUMN, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); + + gtk_tree_view_column_set_sort_column_id (column, NAME_COLUMN); + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), + NAME_COLUMN, + compare_theme, + NULL, NULL); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), + NAME_COLUMN, + GTK_SORT_ASCENDING); + + gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (tree), + separator_func, + GINT_TO_POINTER (ID_COLUMN), + NULL); + + select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)); + gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE); + g_signal_connect (G_OBJECT (select), "changed", + G_CALLBACK (tree_selection_changed_cb), + preview); + +} + +static void +setup_treeview_selection (GtkWidget *tree) +{ + char *theme; + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path = NULL; + gboolean is_writable; + + theme = config_get_theme (&is_writable); + + if (! is_writable) + { + gtk_widget_set_sensitive (tree, FALSE); + } + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree)); + + if (theme && gtk_tree_model_get_iter_first (model, &iter)) + { + + do + { + char *id; + gboolean found; + + gtk_tree_model_get (model, &iter, + ID_COLUMN, &id, -1); + found = (id && strcmp (id, theme) == 0); + g_free (id); + + if (found) + { + path = gtk_tree_model_get_path (model, &iter); + break; + } + + } + while (gtk_tree_model_iter_next (model, &iter)); + } + + if (path) + { + gtk_tree_view_set_cursor (GTK_TREE_VIEW (tree), + path, + NULL, + FALSE); + + gtk_tree_path_free (path); + } + + g_free (theme); +} + +static void +reload_themes (void) +{ + GtkWidget *treeview; + GtkTreeModel *model; + + treeview = GTK_WIDGET (gtk_builder_get_object (builder, "savers_treeview")); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)); + gtk_tree_store_clear (GTK_TREE_STORE (model)); + populate_model (GTK_TREE_STORE (model)); + + gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), + GTK_TREE_MODEL (model)); +} + +static void +theme_copy_complete_cb (GtkWidget *dialog, gpointer user_data) +{ + reload_themes (); + gtk_widget_destroy (dialog); +} + +static void +theme_installer_run (GtkWidget *prefs_dialog, GList *files) +{ + GtkWidget *copy_dialog; + + copy_dialog = copy_theme_dialog_new (files); + g_list_foreach (files, (GFunc) (g_object_unref), NULL); + g_list_free (files); + + gtk_window_set_transient_for (GTK_WINDOW (copy_dialog), + GTK_WINDOW (prefs_dialog)); + gtk_window_set_icon_name (GTK_WINDOW (copy_dialog), + "preferences-desktop-screensaver"); + + g_signal_connect (copy_dialog, "complete", + G_CALLBACK (theme_copy_complete_cb), NULL); + + copy_theme_dialog_begin (COPY_THEME_DIALOG (copy_dialog)); +} + +/* Callback issued during drag movements */ +static gboolean +drag_motion_cb (GtkWidget *widget, + GdkDragContext *context, + int x, + int y, + guint time, + gpointer data) +{ + return FALSE; +} + +/* Callback issued during drag leaves */ +static void +drag_leave_cb (GtkWidget *widget, + GdkDragContext *context, + guint time, + gpointer data) +{ + gtk_widget_queue_draw (widget); +} + +/* GIO has no version of mate_vfs_uri_list_parse(), so copy from MateVFS + * and re-work to create GFiles. +**/ +static GList * +uri_list_parse (const gchar *uri_list) +{ + const gchar *p, *q; + gchar *retval; + GFile *file; + GList *result = NULL; + + g_return_val_if_fail (uri_list != NULL, NULL); + + p = uri_list; + + /* We don't actually try to validate the URI according to RFC + * 2396, or even check for allowed characters - we just ignore + * comments and trim whitespace off the ends. We also + * allow LF delimination as well as the specified CRLF. + */ + while (p != NULL) + { + if (*p != '#') + { + while (g_ascii_isspace (*p)) + p++; + + q = p; + while ((*q != '\0') + && (*q != '\n') + && (*q != '\r')) + q++; + + if (q > p) + { + q--; + while (q > p + && g_ascii_isspace (*q)) + q--; + + retval = g_malloc (q - p + 2); + strncpy (retval, p, q - p + 1); + retval[q - p + 1] = '\0'; + + file = g_file_new_for_uri (retval); + + g_free (retval); + + if (file != NULL) + result = g_list_prepend (result, file); + } + } + p = strchr (p, '\n'); + if (p != NULL) + p++; + } + + return g_list_reverse (result); +} + +/* Callback issued on actual drops. Attempts to load the file dropped. */ +static void +drag_data_received_cb (GtkWidget *widget, + GdkDragContext *context, + int x, + int y, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer data) +{ + GList *files; + + if (!(info == TARGET_URI_LIST || info == TARGET_NS_URL)) + return; + + files = uri_list_parse ((char *) selection_data->data); + if (files != NULL) + { + GtkWidget *prefs_dialog; + + prefs_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_dialog")); + theme_installer_run (prefs_dialog, files); + } +} + +/* Adapted from totem_time_to_string_text */ +static char * +time_to_string_text (long time) +{ + char *secs, *mins, *hours, *string; + int sec, min, hour; + + sec = time % 60; + time = time - sec; + min = (time % (60 * 60)) / 60; + time = time - (min * 60); + hour = time / (60 * 60); + + hours = g_strdup_printf (ngettext ("%d hour", + "%d hours", hour), hour); + + mins = g_strdup_printf (ngettext ("%d minute", + "%d minutes", min), min); + + secs = g_strdup_printf (ngettext ("%d second", + "%d seconds", sec), sec); + + if (hour > 0) + { + if (sec > 0) + { + /* hour:minutes:seconds */ + string = g_strdup_printf (_("%s %s %s"), hours, mins, secs); + } + else if (min > 0) + { + /* hour:minutes */ + string = g_strdup_printf (_("%s %s"), hours, mins); + } + else + { + /* hour */ + string = g_strdup_printf (_("%s"), hours); + } + } + else if (min > 0) + { + if (sec > 0) + { + /* minutes:seconds */ + string = g_strdup_printf (_("%s %s"), mins, secs); + } + else + { + /* minutes */ + string = g_strdup_printf (_("%s"), mins); + } + } + else + { + /* seconds */ + string = g_strdup_printf (_("%s"), secs); + } + + g_free (hours); + g_free (mins); + g_free (secs); + + return string; +} + +static char * +format_value_callback_time (GtkScale *scale, + gdouble value) +{ + if (value == 0) + return g_strdup_printf (_("Never")); + + return time_to_string_text (value * 60.0); +} + +static void +lock_checkbox_toggled (GtkToggleButton *button, gpointer user_data) +{ + config_set_lock (gtk_toggle_button_get_active (button)); +} + +static void +enabled_checkbox_toggled (GtkToggleButton *button, gpointer user_data) +{ + config_set_enabled (gtk_toggle_button_get_active (button)); +} + +static void +invalid_type_warning (const char *type) +{ + g_warning ("Error retrieving configuration key '%s': Invalid type", + type); +} + +static void +ui_disable_lock (gboolean disable) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (gtk_builder_get_object (builder, "lock_checkbox")); + gtk_widget_set_sensitive (widget, !disable); + if (disable) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE); + } +} + +static void +ui_set_lock (gboolean enabled) +{ + GtkWidget *widget; + gboolean active; + gboolean lock_disabled; + + widget = GTK_WIDGET (gtk_builder_get_object (builder, "lock_checkbox")); + + active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + if (active != enabled) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), enabled); + } + lock_disabled = config_get_lock_disabled (); + ui_disable_lock (lock_disabled); +} + +static void +ui_set_enabled (gboolean enabled) +{ + GtkWidget *widget; + gboolean active; + gboolean is_writable; + gboolean lock_disabled; + + widget = GTK_WIDGET (gtk_builder_get_object (builder, "enable_checkbox")); + active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + if (active != enabled) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), enabled); + } + + widget = GTK_WIDGET (gtk_builder_get_object (builder, "lock_checkbox")); + config_get_lock (&is_writable); + if (is_writable) + { + gtk_widget_set_sensitive (widget, enabled); + } + lock_disabled = config_get_lock_disabled (); + ui_disable_lock(lock_disabled); +} + +static void +ui_set_delay (int delay) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (gtk_builder_get_object (builder, "activate_delay_hscale")); + gtk_range_set_value (GTK_RANGE (widget), delay); +} + +static void +key_changed_cb (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + gpointer data) +{ + const char *key; + MateConfValue *value; + + key = mateconf_entry_get_key (entry); + + if (! g_str_has_prefix (key, KEY_DIR) && ! g_str_has_prefix (key, MATE_LOCKDOWN_DIR)) + { + return; + } + + value = mateconf_entry_get_value (entry); + + if (strcmp (key, KEY_IDLE_ACTIVATION_ENABLED) == 0) + { + if (value->type == MATECONF_VALUE_BOOL) + { + gboolean enabled; + + enabled = mateconf_value_get_bool (value); + + ui_set_enabled (enabled); + } + else + { + invalid_type_warning (key); + } + } + else if (strcmp (key, KEY_LOCK) == 0) + { + if (value->type == MATECONF_VALUE_BOOL) + { + gboolean enabled; + + enabled = mateconf_value_get_bool (value); + + ui_set_lock (enabled); + } + else + { + invalid_type_warning (key); + } + } + else if (strcmp (key, KEY_LOCK_DISABLE) == 0) + { + if (value->type == MATECONF_VALUE_BOOL) + { + gboolean disabled; + + disabled = mateconf_value_get_bool (value); + + ui_disable_lock (disabled); + } + else + { + invalid_type_warning (key); + } + } + else if (strcmp (key, KEY_THEMES) == 0) + { + if (value->type == MATECONF_VALUE_LIST) + { + GtkWidget *treeview; + + treeview = GTK_WIDGET (gtk_builder_get_object (builder, "savers_treeview")); + setup_treeview_selection (treeview); + } + else + { + invalid_type_warning (key); + } + } + else if (strcmp (key, KEY_ACTIVATE_DELAY) == 0) + { + + if (value->type == MATECONF_VALUE_INT) + { + int delay; + + delay = mateconf_value_get_int (value); + ui_set_delay (delay); + } + else + { + invalid_type_warning (key); + } + + } + else + { + /*g_warning ("Config key not handled: %s", key);*/ + } +} + +static void +fullscreen_preview_previous_cb (GtkWidget *fullscreen_preview_window, + gpointer user_data) +{ + GtkWidget *treeview; + GtkTreeSelection *selection; + + treeview = GTK_WIDGET (gtk_builder_get_object (builder, "savers_treeview")); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + tree_selection_previous (selection); +} + +static void +fullscreen_preview_next_cb (GtkWidget *fullscreen_preview_window, + gpointer user_data) +{ + GtkWidget *treeview; + GtkTreeSelection *selection; + + treeview = GTK_WIDGET (gtk_builder_get_object (builder, "savers_treeview")); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + tree_selection_next (selection); +} + +static void +fullscreen_preview_cancelled_cb (GtkWidget *button, + gpointer user_data) +{ + + GtkWidget *fullscreen_preview_area; + GtkWidget *fullscreen_preview_window; + GtkWidget *preview_area; + GtkWidget *dialog; + + preview_area = GTK_WIDGET (gtk_builder_get_object (builder, "preview_area")); + gs_job_set_widget (job, preview_area); + + fullscreen_preview_area = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_area")); + preview_clear (fullscreen_preview_area); + + fullscreen_preview_window = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_window")); + gtk_widget_hide (fullscreen_preview_window); + + dialog = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_dialog")); + gtk_widget_show (dialog); + gtk_window_present (GTK_WINDOW (dialog)); +} + +static void +fullscreen_preview_start_cb (GtkWidget *widget, + gpointer user_data) +{ + GtkWidget *fullscreen_preview_area; + GtkWidget *fullscreen_preview_window; + GtkWidget *dialog; + + dialog = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_dialog")); + gtk_widget_hide (dialog); + + fullscreen_preview_window = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_window")); + + gtk_window_fullscreen (GTK_WINDOW (fullscreen_preview_window)); + gtk_window_set_keep_above (GTK_WINDOW (fullscreen_preview_window), TRUE); + + gtk_widget_show (fullscreen_preview_window); + gtk_widget_grab_focus (fullscreen_preview_window); + + fullscreen_preview_area = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_area")); + preview_clear (fullscreen_preview_area); + gs_job_set_widget (job, fullscreen_preview_area); +} + +static void +constrain_list_size (GtkWidget *widget, + GtkRequisition *requisition, + GtkWidget *to_size) +{ + GtkRequisition req; + int max_height; + + /* constrain height to be the tree height up to a max */ + max_height = (gdk_screen_get_height (gtk_widget_get_screen (widget))) / 4; + + gtk_widget_size_request (to_size, &req); + + requisition->height = MIN (req.height, max_height); +} + +static void +setup_list_size_constraint (GtkWidget *widget, + GtkWidget *to_size) +{ + g_signal_connect (widget, "size-request", + G_CALLBACK (constrain_list_size), to_size); +} + +static gboolean +check_is_root_user (void) +{ +#ifndef G_OS_WIN32 + uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ + gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ + +#ifdef HAVE_GETRESUID + if (getresuid (&ruid, &euid, &suid) != 0 || + getresgid (&rgid, &egid, &sgid) != 0) +#endif /* HAVE_GETRESUID */ + { + suid = ruid = getuid (); + sgid = rgid = getgid (); + euid = geteuid (); + egid = getegid (); + } + + if (ruid == 0) + { + return TRUE; + } + +#endif + return FALSE; +} + +static void +setup_for_root_user (void) +{ + GtkWidget *lock_checkbox; + GtkWidget *label; + + lock_checkbox = GTK_WIDGET (gtk_builder_get_object (builder, "lock_checkbox")); + label = GTK_WIDGET (gtk_builder_get_object (builder, "root_warning_label")); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lock_checkbox), FALSE); + gtk_widget_set_sensitive (lock_checkbox, FALSE); + + gtk_widget_show (label); +} + +static GdkVisual * +get_best_visual (void) +{ + char *command; + char *std_output; + int exit_status; + GError *error; + unsigned long v; + char c; + GdkVisual *visual; + gboolean res; + + visual = NULL; + + command = g_build_filename (LIBEXECDIR, "mate-screensaver-gl-helper", NULL); + + error = NULL; + res = g_spawn_command_line_sync (command, + &std_output, + NULL, + &exit_status, + &error); + + if (! res) + { + g_debug ("Could not run command '%s': %s", command, error->message); + g_error_free (error); + goto out; + } + + if (1 == sscanf (std_output, "0x%lx %c", &v, &c)) + { + if (v != 0) + { + VisualID visual_id; + + visual_id = (VisualID) v; + visual = gdkx_visual_get (visual_id); + + g_debug ("Found best visual for GL: 0x%x", + (unsigned int) visual_id); + } + } + +out: + g_free (std_output); + g_free (command); + + return visual; +} + +static GdkColormap * +get_best_colormap_for_screen (GdkScreen *screen) +{ + GdkColormap *colormap; + GdkVisual *visual; + + g_return_val_if_fail (screen != NULL, NULL); + + visual = get_best_visual (); + + colormap = NULL; + if (visual != NULL) + { + colormap = gdk_colormap_new (visual, FALSE); + } + + return colormap; +} + +static void +widget_set_best_colormap (GtkWidget *widget) +{ + GdkColormap *colormap; + + g_return_if_fail (widget != NULL); + + colormap = get_best_colormap_for_screen (gtk_widget_get_screen (widget)); + if (colormap != NULL) + { + gtk_widget_set_colormap (widget, colormap); + g_object_unref (colormap); + } +} + +static gboolean +setup_treeview_idle (gpointer data) +{ + GtkWidget *preview; + GtkWidget *treeview; + + preview = GTK_WIDGET (gtk_builder_get_object (builder, "preview_area")); + treeview = GTK_WIDGET (gtk_builder_get_object (builder, "savers_treeview")); + + setup_treeview (treeview, preview); + setup_treeview_selection (treeview); + + return FALSE; +} + +static gboolean +is_program_in_path (const char *program) +{ + char *tmp = g_find_program_in_path (program); + if (tmp != NULL) + { + g_free (tmp); + return TRUE; + } + else + { + return FALSE; + } +} + +static void +init_capplet (void) +{ + GtkWidget *dialog; + GtkWidget *preview; + GtkWidget *treeview; + GtkWidget *list_scroller; + GtkWidget *activate_delay_hscale; + GtkWidget *activate_delay_hbox; + GtkWidget *label; + GtkWidget *enabled_checkbox; + GtkWidget *lock_checkbox; + GtkWidget *root_warning_label; + GtkWidget *preview_button; + GtkWidget *gpm_button; + GtkWidget *fullscreen_preview_window; + GtkWidget *fullscreen_preview_previous; + GtkWidget *fullscreen_preview_next; + GtkWidget *fullscreen_preview_area; + GtkWidget *fullscreen_preview_close; + char *gtk_builder_file; + char *string; + gdouble activate_delay; + gboolean enabled; + gboolean is_writable; + MateConfClient *client; + GError *error=NULL; + + gtk_builder_file = g_build_filename (GTKBUILDERDIR, GTK_BUILDER_FILE, NULL); + builder = gtk_builder_new(); + if (!gtk_builder_add_from_file(builder, gtk_builder_file, &error)) + { + g_warning("Couldn't load builder file: %s", error->message); + g_error_free(error); + } + g_free (gtk_builder_file); + + if (builder == NULL) + { + + dialog = gtk_message_dialog_new (NULL, + 0, GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Could not load the main interface")); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("Please make sure that the screensaver is properly installed")); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), + GTK_RESPONSE_OK); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + exit (1); + } + + preview = GTK_WIDGET (gtk_builder_get_object (builder, "preview_area")); + dialog = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_dialog")); + treeview = GTK_WIDGET (gtk_builder_get_object (builder, "savers_treeview")); + list_scroller = GTK_WIDGET (gtk_builder_get_object (builder, "themes_scrolled_window")); + activate_delay_hscale = GTK_WIDGET (gtk_builder_get_object (builder, "activate_delay_hscale")); + activate_delay_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "activate_delay_hbox")); + enabled_checkbox = GTK_WIDGET (gtk_builder_get_object (builder, "enable_checkbox")); + lock_checkbox = GTK_WIDGET (gtk_builder_get_object (builder, "lock_checkbox")); + root_warning_label = GTK_WIDGET (gtk_builder_get_object (builder, "root_warning_label")); + preview_button = GTK_WIDGET (gtk_builder_get_object (builder, "preview_button")); + gpm_button = GTK_WIDGET (gtk_builder_get_object (builder, "gpm_button")); + fullscreen_preview_window = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_window")); + fullscreen_preview_area = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_area")); + fullscreen_preview_close = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_close")); + fullscreen_preview_previous = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_previous_button")); + fullscreen_preview_next = GTK_WIDGET (gtk_builder_get_object (builder, "fullscreen_preview_next_button")); + + label = GTK_WIDGET (gtk_builder_get_object (builder, "activate_delay_label")); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), activate_delay_hscale); + label = GTK_WIDGET (gtk_builder_get_object (builder, "savers_label")); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), treeview); + + gtk_widget_set_no_show_all (root_warning_label, TRUE); + widget_set_best_colormap (preview); + + if (! is_program_in_path (GPM_COMMAND)) + { + gtk_widget_set_no_show_all (gpm_button, TRUE); + gtk_widget_hide (gpm_button); + } + + activate_delay = config_get_activate_delay (&is_writable); + ui_set_delay (activate_delay); + if (! is_writable) + { + gtk_widget_set_sensitive (activate_delay_hbox, FALSE); + } + g_signal_connect (activate_delay_hscale, "format-value", + G_CALLBACK (format_value_callback_time), NULL); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lock_checkbox), config_get_lock (&is_writable)); + if (! is_writable) + { + gtk_widget_set_sensitive (lock_checkbox, FALSE); + } + g_signal_connect (lock_checkbox, "toggled", + G_CALLBACK (lock_checkbox_toggled), NULL); + + enabled = config_get_enabled (&is_writable); + ui_set_enabled (enabled); + if (! is_writable) + { + gtk_widget_set_sensitive (enabled_checkbox, FALSE); + } + g_signal_connect (enabled_checkbox, "toggled", + G_CALLBACK (enabled_checkbox_toggled), NULL); + + setup_list_size_constraint (list_scroller, treeview); + gtk_widget_set_size_request (preview, 480, 300); + gtk_window_set_icon_name (GTK_WINDOW (dialog), "preferences-desktop-screensaver"); + gtk_window_set_icon_name (GTK_WINDOW (fullscreen_preview_window), "screensaver"); + + gtk_drag_dest_set (dialog, GTK_DEST_DEFAULT_ALL, + drop_types, G_N_ELEMENTS (drop_types), + GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_MOVE); + + g_signal_connect (dialog, "drag-motion", + G_CALLBACK (drag_motion_cb), NULL); + g_signal_connect (dialog, "drag-leave", + G_CALLBACK (drag_leave_cb), NULL); + g_signal_connect (dialog, "drag-data-received", + G_CALLBACK (drag_data_received_cb), NULL); + + gtk_widget_show_all (dialog); + + /* Update list of themes if using random screensaver */ + client = mateconf_client_get_default (); + string = mateconf_client_get_string (client, KEY_MODE, NULL); + if (string != NULL) + { + int mode; + GSList *list; + + mateconf_string_to_enum (mode_enum_map, string, &mode); + g_free (string); + + if (mode == GS_MODE_RANDOM) + { + list = get_all_theme_ids (theme_manager); + mateconf_client_set_list (client, KEY_THEMES, MATECONF_VALUE_STRING, list, NULL); + + g_slist_foreach (list, (GFunc) g_free, NULL); + g_slist_free (list); + } + } + + mateconf_client_add_dir (client, KEY_DIR, + MATECONF_CLIENT_PRELOAD_ONELEVEL, + NULL); + mateconf_client_notify_add (client, + KEY_DIR, + key_changed_cb, + NULL, NULL, NULL); + mateconf_client_add_dir (client, MATE_LOCKDOWN_DIR, + MATECONF_CLIENT_PRELOAD_ONELEVEL, + NULL); + mateconf_client_notify_add (client, + MATE_LOCKDOWN_DIR, + key_changed_cb, + NULL, NULL, NULL); + + g_object_unref (client); + + preview_clear (preview); + gs_job_set_widget (job, preview); + + if (check_is_root_user ()) + { + setup_for_root_user (); + } + + g_signal_connect (activate_delay_hscale, "value-changed", + G_CALLBACK (activate_delay_value_changed_cb), NULL); + + g_signal_connect (dialog, "response", + G_CALLBACK (response_cb), NULL); + + g_signal_connect (preview_button, "clicked", + G_CALLBACK (fullscreen_preview_start_cb), + treeview); + + g_signal_connect (fullscreen_preview_close, "clicked", + G_CALLBACK (fullscreen_preview_cancelled_cb), NULL); + g_signal_connect (fullscreen_preview_previous, "clicked", + G_CALLBACK (fullscreen_preview_previous_cb), NULL); + g_signal_connect (fullscreen_preview_next, "clicked", + G_CALLBACK (fullscreen_preview_next_cb), NULL); + + g_idle_add ((GSourceFunc)setup_treeview_idle, NULL); +} + +int +main (int argc, + char **argv) +{ + +#ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR); +# ifdef HAVE_BIND_TEXTDOMAIN_CODESET + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +# endif + textdomain (GETTEXT_PACKAGE); +#endif + + gtk_init (&argc, &argv); + + job = gs_job_new (); + theme_manager = gs_theme_manager_new (); + + init_capplet (); + + gtk_main (); + + g_object_unref (theme_manager); + g_object_unref (job); + + return 0; +} -- cgit v1.2.1