The checkmark indicating the active background based on GtkFlowBox selection does not work when changing the selection with the arrow keys. Moreover, it is not set when the panel opens. We fix this by sending the active CcBackgroundItem to the chooser, so that it can add an "active-item" CSS class to the true active item. Fixes #1756 #2505
451 lines
14 KiB
C
451 lines
14 KiB
C
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Thomas Wood <thomas.wood@intel.com>
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <string.h>
|
|
#include <glib.h>
|
|
#include <glib/gi18n-lib.h>
|
|
#include <glib/gstdio.h>
|
|
|
|
#include <gdesktop-enums.h>
|
|
|
|
#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"
|
|
|
|
#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;
|
|
|
|
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 *self)
|
|
{
|
|
CcBackgroundItem *current_background;
|
|
|
|
current_background = self->current_background;
|
|
cc_background_preview_set_item (self->default_preview, current_background);
|
|
cc_background_preview_set_item (self->dark_preview, current_background);
|
|
}
|
|
|
|
static void
|
|
reload_current_bg (CcBackgroundPanel *self)
|
|
{
|
|
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;
|
|
|
|
/* initalise the current background information from settings */
|
|
settings = self->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);
|
|
|
|
g_clear_object (&self->current_background);
|
|
self->current_background = configured;
|
|
cc_background_item_load (configured, NULL);
|
|
|
|
cc_background_chooser_set_active_item (self->background_chooser, configured);
|
|
}
|
|
|
|
static void
|
|
reset_settings_if_defaults (CcBackgroundPanel *self,
|
|
GSettings *settings,
|
|
gboolean check_dark)
|
|
{
|
|
gsize i;
|
|
const char *keys[] = {
|
|
WP_URI_KEY, /* this key needs to be first */
|
|
WP_URI_DARK_KEY,
|
|
WP_OPTIONS_KEY,
|
|
WP_SHADING_KEY,
|
|
WP_PCOLOR_KEY,
|
|
WP_SCOLOR_KEY,
|
|
NULL
|
|
};
|
|
|
|
for (i = 0; keys[i] != NULL; i++)
|
|
{
|
|
g_autoptr (GVariant) default_value = NULL;
|
|
g_autoptr (GVariant) user_value = NULL;
|
|
gboolean setting_is_default;
|
|
|
|
if (!check_dark && g_str_equal (keys[i], WP_URI_DARK_KEY))
|
|
continue;
|
|
|
|
default_value = g_settings_get_default_value (settings, keys[i]);
|
|
user_value = g_settings_get_value (settings, keys[i]);
|
|
|
|
setting_is_default = g_variant_equal (default_value, user_value);
|
|
|
|
/* As a courtesy to distros that are a little lackadaisical about making sure
|
|
* schema defaults match the settings in the background item with the default
|
|
* picture, we only look at the URI to determine if we shouldn't clean out dconf.
|
|
*
|
|
* In otherwords, we still clean out the picture-uri key from dconf when a user
|
|
* selects the default background in control-center, even if after selecting it
|
|
* e.g., primary-color still mismatches with schema defaults.
|
|
*/
|
|
if (g_str_equal (keys[i], WP_URI_KEY) && !setting_is_default)
|
|
return;
|
|
|
|
if (setting_is_default)
|
|
g_settings_reset (settings, keys[i]);
|
|
}
|
|
|
|
g_settings_apply (settings);
|
|
}
|
|
|
|
static void
|
|
set_background (CcBackgroundPanel *self,
|
|
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);
|
|
|
|
/* Clean out dconf if the user went back to distro defaults */
|
|
reset_settings_if_defaults (self, settings, set_dark);
|
|
}
|
|
|
|
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 *self = CC_BACKGROUND_PANEL (object);
|
|
|
|
g_clear_object (&self->settings);
|
|
g_clear_object (&self->lock_settings);
|
|
g_clear_object (&self->interface_settings);
|
|
g_clear_object (&self->proxy);
|
|
|
|
G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
cc_background_panel_finalize (GObject *object)
|
|
{
|
|
CcBackgroundPanel *self = CC_BACKGROUND_PANEL (object);
|
|
|
|
g_clear_object (&self->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 *self)
|
|
{
|
|
reload_current_bg (self);
|
|
update_preview (self);
|
|
}
|
|
|
|
static void
|
|
cc_background_panel_init (CcBackgroundPanel *self)
|
|
{
|
|
g_resources_register (cc_background_get_resource ());
|
|
|
|
gtk_widget_init_template (GTK_WIDGET (self));
|
|
|
|
self->connection = g_application_get_dbus_connection (g_application_get_default ());
|
|
|
|
self->settings = g_settings_new (WP_PATH_ID);
|
|
g_settings_delay (self->settings);
|
|
|
|
self->lock_settings = g_settings_new (WP_LOCK_PATH_ID);
|
|
g_settings_delay (self->lock_settings);
|
|
|
|
self->interface_settings = g_settings_new (INTERFACE_PATH_ID);
|
|
|
|
/* Load the background */
|
|
reload_current_bg (self);
|
|
update_preview (self);
|
|
|
|
/* Background settings */
|
|
g_signal_connect_object (self->settings, "changed", G_CALLBACK (on_settings_changed), self, G_CONNECT_SWAPPED);
|
|
|
|
/* Interface settings */
|
|
reload_color_scheme_toggles (self);
|
|
|
|
g_signal_connect_object (self->interface_settings,
|
|
"changed::" INTERFACE_COLOR_SCHEME_KEY,
|
|
G_CALLBACK (reload_color_scheme_toggles),
|
|
self,
|
|
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,
|
|
self);
|
|
|
|
load_custom_css (self);
|
|
}
|