/* * Copyright (C) 2010 Intel, Inc * * 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, see . * * Author: Thomas Wood * */ #include #include #include #include #include #include #include "cc-background-panel.h" #include "cc-background-chooser.h" #include "cc-background-item.h" #include "cc-background-preview.h" #include "cc-background-resources.h" #include "cc-background-xml.h" #define WP_PATH_ID "org.gnome.desktop.background" #define WP_LOCK_PATH_ID "org.gnome.desktop.screensaver" #define WP_URI_KEY "picture-uri" #define WP_URI_DARK_KEY "picture-uri-dark" #define WP_OPTIONS_KEY "picture-options" #define WP_SHADING_KEY "color-shading-type" #define WP_PCOLOR_KEY "primary-color" #define WP_SCOLOR_KEY "secondary-color" #define INTERFACE_PATH_ID "org.gnome.desktop.interface" #define INTERFACE_COLOR_SCHEME_KEY "color-scheme" struct _CcBackgroundPanel { CcPanel parent_instance; GDBusConnection *connection; GSettings *settings; GSettings *lock_settings; GSettings *interface_settings; GnomeDesktopThumbnailFactory *thumb_factory; GDBusProxy *proxy; CcBackgroundItem *current_background; CcBackgroundChooser *background_chooser; CcBackgroundPreview *default_preview; CcBackgroundPreview *dark_preview; GtkToggleButton *default_toggle; GtkToggleButton *dark_toggle; }; CC_PANEL_REGISTER (CcBackgroundPanel, cc_background_panel) static void load_custom_css (CcBackgroundPanel *self) { g_autoptr(GtkCssProvider) provider = NULL; provider = gtk_css_provider_new (); gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/background/preview.css"); gtk_style_context_add_provider_for_display (gdk_display_get_default (), GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } static void reload_color_scheme_toggles (CcBackgroundPanel *self) { GDesktopColorScheme scheme; scheme = g_settings_get_enum (self->interface_settings, INTERFACE_COLOR_SCHEME_KEY); if (scheme == G_DESKTOP_COLOR_SCHEME_DEFAULT) { gtk_toggle_button_set_active (self->default_toggle, TRUE); } else if (scheme == G_DESKTOP_COLOR_SCHEME_PREFER_DARK) { gtk_toggle_button_set_active (self->dark_toggle, TRUE); } else { gtk_toggle_button_set_active (self->default_toggle, FALSE); gtk_toggle_button_set_active (self->dark_toggle, FALSE); } } static void transition_screen (CcBackgroundPanel *self) { g_autoptr (GError) error = NULL; if (!self->proxy) return; g_dbus_proxy_call_sync (self->proxy, "ScreenTransition", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error) g_warning ("Couldn't transition screen: %s", error->message); } static void set_color_scheme (CcBackgroundPanel *self, GDesktopColorScheme color_scheme) { GDesktopColorScheme scheme; scheme = g_settings_get_enum (self->interface_settings, INTERFACE_COLOR_SCHEME_KEY); /* We have to check the equality manually to avoid starting an unnecessary * screen transition */ if (color_scheme == scheme) return; transition_screen (self); g_settings_set_enum (self->interface_settings, INTERFACE_COLOR_SCHEME_KEY, color_scheme); } /* Color schemes */ static void on_color_scheme_toggle_active_cb (CcBackgroundPanel *self) { if (gtk_toggle_button_get_active (self->default_toggle)) set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_DEFAULT); else if (gtk_toggle_button_get_active (self->dark_toggle)) set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_PREFER_DARK); } static void got_transition_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer data) { g_autoptr(GError) error = NULL; CcBackgroundPanel *self = data; self->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (self->proxy == NULL) { g_warning ("Error creating proxy: %s", error->message); return; } } /* Background */ static void update_preview (CcBackgroundPanel *panel) { CcBackgroundItem *current_background; current_background = panel->current_background; cc_background_preview_set_item (panel->default_preview, current_background); cc_background_preview_set_item (panel->dark_preview, current_background); } static gchar * get_save_path (void) { return g_build_filename (g_get_user_config_dir (), "gnome-control-center", "backgrounds", "last-edited.xml", NULL); } static void reload_current_bg (CcBackgroundPanel *panel) { g_autoptr(CcBackgroundItem) saved = NULL; CcBackgroundItem *configured; GSettings *settings = NULL; g_autofree gchar *uri = NULL; g_autofree gchar *dark_uri = NULL; g_autofree gchar *pcolor = NULL; g_autofree gchar *scolor = NULL; /* Load the saved configuration */ uri = get_save_path (); saved = cc_background_xml_get_item (uri); /* initalise the current background information from settings */ settings = panel->settings; uri = g_settings_get_string (settings, WP_URI_KEY); if (uri && *uri == '\0') g_clear_pointer (&uri, g_free); configured = cc_background_item_new (uri); dark_uri = g_settings_get_string (settings, WP_URI_DARK_KEY); pcolor = g_settings_get_string (settings, WP_PCOLOR_KEY); scolor = g_settings_get_string (settings, WP_SCOLOR_KEY); g_object_set (G_OBJECT (configured), "name", _("Current background"), "uri-dark", dark_uri, "placement", g_settings_get_enum (settings, WP_OPTIONS_KEY), "shading", g_settings_get_enum (settings, WP_SHADING_KEY), "primary-color", pcolor, "secondary-color", scolor, NULL); if (saved != NULL && cc_background_item_compare (saved, configured)) { CcBackgroundItemFlags flags; flags = cc_background_item_get_flags (saved); /* Special case for colours */ if (cc_background_item_get_placement (saved) == G_DESKTOP_BACKGROUND_STYLE_NONE) flags &=~ (CC_BACKGROUND_ITEM_HAS_PCOLOR | CC_BACKGROUND_ITEM_HAS_SCOLOR); g_object_set (G_OBJECT (configured), "name", cc_background_item_get_name (saved), "flags", flags, "source-url", cc_background_item_get_source_url (saved), "source-xml", cc_background_item_get_source_xml (saved), NULL); } g_clear_object (&panel->current_background); panel->current_background = configured; cc_background_item_load (configured, NULL); } static gboolean create_save_dir (void) { g_autofree char *path = NULL; path = g_build_filename (g_get_user_config_dir (), "gnome-control-center", "backgrounds", NULL); if (g_mkdir_with_parents (path, USER_DIR_MODE) < 0) { g_warning ("Failed to create directory '%s'", path); return FALSE; } return TRUE; } static void set_background (CcBackgroundPanel *panel, GSettings *settings, CcBackgroundItem *item, gboolean set_dark) { GDesktopBackgroundStyle style; CcBackgroundItemFlags flags; g_autofree gchar *filename = NULL; const char *uri; if (item == NULL) return; uri = cc_background_item_get_uri (item); flags = cc_background_item_get_flags (item); g_settings_set_string (settings, WP_URI_KEY, uri); if (set_dark) { const char *uri_dark; uri_dark = cc_background_item_get_uri_dark (item); if (uri_dark && uri_dark[0]) g_settings_set_string (settings, WP_URI_DARK_KEY, uri_dark); else g_settings_set_string (settings, WP_URI_DARK_KEY, uri); } /* Also set the placement if we have a URI and the previous value was none */ if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT) { g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item)); } else if (uri != NULL) { style = g_settings_get_enum (settings, WP_OPTIONS_KEY); if (style == G_DESKTOP_BACKGROUND_STYLE_NONE) g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item)); } if (flags & CC_BACKGROUND_ITEM_HAS_SHADING) g_settings_set_enum (settings, WP_SHADING_KEY, cc_background_item_get_shading (item)); g_settings_set_string (settings, WP_PCOLOR_KEY, cc_background_item_get_pcolor (item)); g_settings_set_string (settings, WP_SCOLOR_KEY, cc_background_item_get_scolor (item)); /* Apply all changes */ g_settings_apply (settings); /* Save the source XML if there is one */ filename = get_save_path (); if (create_save_dir ()) cc_background_xml_save (panel->current_background, filename); } static void on_chooser_background_chosen_cb (CcBackgroundPanel *self, CcBackgroundItem *item) { set_background (self, self->settings, item, TRUE); set_background (self, self->lock_settings, item, FALSE); } static void on_add_picture_button_clicked_cb (CcBackgroundPanel *self) { cc_background_chooser_select_file (self->background_chooser); } static const char * cc_background_panel_get_help_uri (CcPanel *panel) { return "help:gnome-help/look-background"; } static void cc_background_panel_dispose (GObject *object) { CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object); g_clear_object (&panel->settings); g_clear_object (&panel->lock_settings); g_clear_object (&panel->interface_settings); g_clear_object (&panel->thumb_factory); g_clear_object (&panel->proxy); G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object); } static void cc_background_panel_finalize (GObject *object) { CcBackgroundPanel *panel = CC_BACKGROUND_PANEL (object); g_clear_object (&panel->current_background); G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object); } static void cc_background_panel_class_init (CcBackgroundPanelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); CcPanelClass *panel_class = CC_PANEL_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_ensure (CC_TYPE_BACKGROUND_CHOOSER); g_type_ensure (CC_TYPE_BACKGROUND_PREVIEW); panel_class->get_help_uri = cc_background_panel_get_help_uri; object_class->dispose = cc_background_panel_dispose; object_class->finalize = cc_background_panel_finalize; gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-panel.ui"); gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, background_chooser); gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_preview); gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_preview); gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_toggle); gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_toggle); gtk_widget_class_bind_template_callback (widget_class, on_color_scheme_toggle_active_cb); gtk_widget_class_bind_template_callback (widget_class, on_chooser_background_chosen_cb); gtk_widget_class_bind_template_callback (widget_class, on_add_picture_button_clicked_cb); } static void on_settings_changed (CcBackgroundPanel *panel) { reload_current_bg (panel); update_preview (panel); } static void cc_background_panel_init (CcBackgroundPanel *panel) { g_resources_register (cc_background_get_resource ()); gtk_widget_init_template (GTK_WIDGET (panel)); panel->connection = g_application_get_dbus_connection (g_application_get_default ()); panel->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE); panel->settings = g_settings_new (WP_PATH_ID); g_settings_delay (panel->settings); panel->lock_settings = g_settings_new (WP_LOCK_PATH_ID); g_settings_delay (panel->lock_settings); panel->interface_settings = g_settings_new (INTERFACE_PATH_ID); /* Load the background */ reload_current_bg (panel); update_preview (panel); /* Background settings */ g_signal_connect_object (panel->settings, "changed", G_CALLBACK (on_settings_changed), panel, G_CONNECT_SWAPPED); /* Interface settings */ reload_color_scheme_toggles (panel); g_signal_connect_object (panel->interface_settings, "changed::" INTERFACE_COLOR_SCHEME_KEY, G_CALLBACK (reload_color_scheme_toggles), panel, G_CONNECT_SWAPPED); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.gnome.Shell", "/org/gnome/Shell", "org.gnome.Shell", NULL, got_transition_proxy_cb, panel); load_custom_css (panel); }