diff --git a/gresources/nemo-desktop-preferences.glade b/gresources/nemo-desktop-preferences.glade
index f0e6acdcf..0d3442d56 100644
--- a/gresources/nemo-desktop-preferences.glade
+++ b/gresources/nemo-desktop-preferences.glade
@@ -1,37 +1,37 @@
-
+
diff --git a/gresources/nemo-style-application.css b/gresources/nemo-style-application.css
index ea7b95283..7f1a34bde 100644
--- a/gresources/nemo-style-application.css
+++ b/gresources/nemo-style-application.css
@@ -1,4 +1,5 @@
-/* Desktop text stuff */
+/* Desktop window structure — always applied regardless of theme.
+ * The desktop window must be transparent so the wallpaper shows through. */
.nemo-window.nemo-desktop-window notebook,
.nemo-window.nemo-desktop-window paned {
@@ -11,37 +12,17 @@
box-shadow: none;
}
-NemoDesktopWindow GtkPaned {
- background-color: transparent;
-}
-
.nemo-canvas-item {
border-radius: 3px;
}
+/* Custom widget property — controls nemo behavior, not appearance. */
.nemo-desktop {
-NemoIconContainer-activate-prelight-icon-label: true;
}
-.nemo-desktop.nemo-canvas-item {
- color: #eeeeee;
- text-shadow: 1px 1px alpha(black, 0.8);
-}
-
-.nemo-desktop.nemo-canvas-item:hover {
- background-color: alpha(black, 0.5);
- background-image: none;
- text-shadow: none;
-}
-
-.nemo-desktop.nemo-canvas-item:selected {
- background-color: alpha(@theme_selected_bg_color, 0.8);
- background-image: none;
- text-shadow: none;
- color: #f5f5f5;
-}
-
-/* EelEditableLabel (icon labels) */
+/* EelEditableLabel (inline rename entry on desktop).
+ * Always applied so the rename box stays legible over any wallpaper. */
.nemo-desktop.view .entry,
.nemo-desktop.view .entry:active,
.nemo-desktop.view .entry:focus,
diff --git a/gresources/nemo-style-desktop.css b/gresources/nemo-style-desktop.css
new file mode 100644
index 000000000..12658bedf
--- /dev/null
+++ b/gresources/nemo-style-desktop.css
@@ -0,0 +1,45 @@
+/* Desktop icon label text shadows.
+ *
+ * Nemo applies one of these classes (shadow-normal / shadow-darker /
+ * shadow-darkest) to the icon container based on the user's preference.
+ * If "Use GTK theme" is enabled and the current theme provides its own
+ * .nemo-desktop styling, this entire stylesheet is not loaded — the
+ * theme controls text appearance directly.
+ */
+
+/* Shadow variant: Normal (traditional nemo default) */
+.nemo-desktop.nemo-canvas-item.shadow-normal {
+ color: #eeeeee;
+ text-shadow: 1px 1px alpha(black, 0.8);
+}
+
+/* Shadow variant: Darker */
+.nemo-desktop.nemo-canvas-item.shadow-darker {
+ color: #eeeeee;
+ text-shadow: 1px 1px black;
+}
+
+/* Shadow variant: Darkest */
+.nemo-desktop.nemo-canvas-item.shadow-darkest {
+ color: #eeeeee;
+ text-shadow: 1px 1px black, 1px 0px alpha(black, 0.6), 0px 1px alpha(black, 0.6);
+}
+
+/* Hover for shadow modes */
+.nemo-desktop.nemo-canvas-item.shadow-normal:hover,
+.nemo-desktop.nemo-canvas-item.shadow-darker:hover,
+.nemo-desktop.nemo-canvas-item.shadow-darkest:hover {
+ background-color: alpha(black, 0.5);
+ background-image: none;
+ text-shadow: none;
+}
+
+/* Selected for shadow modes */
+.nemo-desktop.nemo-canvas-item.shadow-normal:selected,
+.nemo-desktop.nemo-canvas-item.shadow-darker:selected,
+.nemo-desktop.nemo-canvas-item.shadow-darkest:selected {
+ background-color: alpha(@theme_selected_bg_color, 0.8);
+ background-image: none;
+ text-shadow: none;
+ color: #f5f5f5;
+}
diff --git a/gresources/nemo.gresource.xml b/gresources/nemo.gresource.xml
index 7d0870e7f..2b4ee3d61 100644
--- a/gresources/nemo.gresource.xml
+++ b/gresources/nemo.gresource.xml
@@ -26,5 +26,6 @@
nemo-style-fallback.css
nemo-style-fallback-mandatory.css
nemo-style-application.css
+ nemo-style-desktop.css
diff --git a/libnemo-extension/nemo-desktop-preferences.c b/libnemo-extension/nemo-desktop-preferences.c
index 6b7352224..f3daf9d0f 100644
--- a/libnemo-extension/nemo-desktop-preferences.c
+++ b/libnemo-extension/nemo-desktop-preferences.c
@@ -3,12 +3,32 @@
#include
#include
#include
+#include
#include "nemo-desktop-preferences.h"
+#define NUM_SHADOW_OPTIONS 3
+
+static const gchar *shadow_options[NUM_SHADOW_OPTIONS] = {
+ "normal",
+ "darker",
+ "darkest",
+};
+
+static const gchar *preview_bg_css =
+ ".shadow-preview-bg {"
+ " background-image: linear-gradient(to bottom, #7ba4d4, #d4e6f7);"
+ "}";
+
typedef struct
{
GtkBuilder *builder;
GSettings *desktop_settings;
+ GtkCssProvider *desktop_css_provider;
+ GtkCssProvider *preview_bg_provider;
+ GtkWidget *shadow_radios[NUM_SHADOW_OPTIONS];
+ GtkWidget *shadow_labels[NUM_SHADOW_OPTIONS];
+ gulong shadow_setting_handler;
+ gulong font_changed_handler;
} NemoDesktopPreferencesPrivate;
struct _NemoDesktopPreferences
@@ -43,6 +63,141 @@ bind_builder_string_combo (GtkBuilder *builder,
"active-id", G_SETTINGS_BIND_DEFAULT);
}
+static void
+update_preview_fonts (NemoDesktopPreferencesPrivate *priv)
+{
+ gchar *font_str;
+ PangoFontDescription *font_desc;
+ gint i;
+
+ font_str = g_settings_get_string (priv->desktop_settings, "font");
+ font_desc = pango_font_description_from_string (font_str);
+ g_free (font_str);
+
+ for (i = 0; i < NUM_SHADOW_OPTIONS; i++) {
+ PangoAttrList *attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs, pango_attr_font_desc_new (font_desc));
+ gtk_label_set_attributes (GTK_LABEL (priv->shadow_labels[i]), attrs);
+ pango_attr_list_unref (attrs);
+ }
+
+ pango_font_description_free (font_desc);
+}
+
+static void
+on_shadow_button_toggled (GtkToggleButton *button, gpointer user_data)
+{
+ NemoDesktopPreferencesPrivate *priv = user_data;
+ const gchar *id;
+
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ id = g_object_get_data (G_OBJECT (button), "shadow-id");
+ g_settings_set_string (priv->desktop_settings, "desktop-text-shadow", id);
+}
+
+static void
+on_shadow_setting_changed (GSettings *settings,
+ const gchar *key,
+ gpointer user_data)
+{
+ NemoDesktopPreferences *preferences = NEMO_DESKTOP_PREFERENCES (user_data);
+ NemoDesktopPreferencesPrivate *priv = preferences->priv;
+ gchar *current;
+ gint i;
+
+ current = g_settings_get_string (priv->desktop_settings, "desktop-text-shadow");
+
+ for (i = 0; i < NUM_SHADOW_OPTIONS; i++) {
+ if (g_strcmp0 (current, shadow_options[i]) == 0) {
+ g_signal_handlers_block_by_func (priv->shadow_radios[i],
+ on_shadow_button_toggled, priv);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->shadow_radios[i]), TRUE);
+ g_signal_handlers_unblock_by_func (priv->shadow_radios[i],
+ on_shadow_button_toggled, priv);
+ break;
+ }
+ }
+
+ g_free (current);
+}
+
+static void
+on_desktop_font_changed (GSettings *settings,
+ const gchar *key,
+ gpointer user_data)
+{
+ NemoDesktopPreferences *preferences = NEMO_DESKTOP_PREFERENCES (user_data);
+ update_preview_fonts (preferences->priv);
+}
+
+static void
+add_provider_to_widget (GtkWidget *widget, GtkCssProvider *provider)
+{
+ gtk_style_context_add_provider (gtk_widget_get_style_context (widget),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+static void
+setup_shadow_preview_buttons (NemoDesktopPreferences *preferences)
+{
+ NemoDesktopPreferencesPrivate *priv = preferences->priv;
+ gchar *current;
+ gint i;
+
+ priv->desktop_css_provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_resource (priv->desktop_css_provider,
+ "/org/nemo/nemo-style-desktop.css");
+
+ priv->preview_bg_provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (priv->preview_bg_provider, preview_bg_css, -1, NULL);
+
+ current = g_settings_get_string (priv->desktop_settings, "desktop-text-shadow");
+
+ for (i = 0; i < NUM_SHADOW_OPTIONS; i++) {
+ gchar *name;
+
+ name = g_strdup_printf ("shadow_radio_%s", shadow_options[i]);
+ priv->shadow_radios[i] = GTK_WIDGET (gtk_builder_get_object (priv->builder, name));
+ g_free (name);
+
+ name = g_strdup_printf ("shadow_frame_%s", shadow_options[i]);
+ add_provider_to_widget (GTK_WIDGET (gtk_builder_get_object (priv->builder, name)),
+ priv->preview_bg_provider);
+ g_free (name);
+
+ name = g_strdup_printf ("shadow_label_%s", shadow_options[i]);
+ priv->shadow_labels[i] = GTK_WIDGET (gtk_builder_get_object (priv->builder, name));
+ g_free (name);
+
+ add_provider_to_widget (priv->shadow_labels[i], priv->desktop_css_provider);
+
+ g_object_set_data (G_OBJECT (priv->shadow_radios[i]), "shadow-id",
+ (gpointer) shadow_options[i]);
+
+ g_signal_connect (priv->shadow_radios[i], "toggled",
+ G_CALLBACK (on_shadow_button_toggled), priv);
+
+ if (g_strcmp0 (current, shadow_options[i]) == 0) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->shadow_radios[i]), TRUE);
+ }
+ }
+
+ g_free (current);
+
+ update_preview_fonts (priv);
+
+ priv->shadow_setting_handler =
+ g_signal_connect (priv->desktop_settings, "changed::desktop-text-shadow",
+ G_CALLBACK (on_shadow_setting_changed), preferences);
+
+ priv->font_changed_handler =
+ g_signal_connect (priv->desktop_settings, "changed::font",
+ G_CALLBACK (on_desktop_font_changed), preferences);
+}
+
static void
nemo_desktop_preferences_init (NemoDesktopPreferences *preferences)
{
@@ -96,6 +251,13 @@ nemo_desktop_preferences_init (NemoDesktopPreferences *preferences)
"orphan_switch",
"show-orphaned-desktop-icons");
+ bind_builder_bool (priv->builder,
+ priv->desktop_settings,
+ "use_theme_switch",
+ "desktop-text-shadow-use-theme");
+
+ setup_shadow_preview_buttons (preferences);
+
gtk_widget_show_all (GTK_WIDGET (preferences));
}
@@ -103,9 +265,23 @@ static void
nemo_desktop_preferences_dispose (GObject *object)
{
NemoDesktopPreferences *preferences = NEMO_DESKTOP_PREFERENCES (object);
+ NemoDesktopPreferencesPrivate *priv = preferences->priv;
+
+ if (priv->desktop_settings != NULL) {
+ if (priv->shadow_setting_handler > 0) {
+ g_signal_handler_disconnect (priv->desktop_settings, priv->shadow_setting_handler);
+ priv->shadow_setting_handler = 0;
+ }
+ if (priv->font_changed_handler > 0) {
+ g_signal_handler_disconnect (priv->desktop_settings, priv->font_changed_handler);
+ priv->font_changed_handler = 0;
+ }
+ }
- g_clear_object (&preferences->priv->builder);
- g_clear_object (&preferences->priv->desktop_settings);
+ g_clear_object (&priv->desktop_css_provider);
+ g_clear_object (&priv->preview_bg_provider);
+ g_clear_object (&priv->builder);
+ g_clear_object (&priv->desktop_settings);
G_OBJECT_CLASS (nemo_desktop_preferences_parent_class)->dispose (object);
}
diff --git a/libnemo-private/meson.build b/libnemo-private/meson.build
index 47ac9f868..19b4cc167 100644
--- a/libnemo-private/meson.build
+++ b/libnemo-private/meson.build
@@ -69,6 +69,7 @@ nemo_private_sources = [
'nemo-signaller.c',
'nemo-thumbnails.c',
'nemo-trash-monitor.c',
+ 'nemo-theme-utils.c',
'nemo-tree-view-drag-dest.c',
'nemo-ui-utilities.c',
'nemo-undo-manager.c',
diff --git a/libnemo-private/nemo-global-preferences.h b/libnemo-private/nemo-global-preferences.h
index 91f404854..8b593cf0f 100644
--- a/libnemo-private/nemo-global-preferences.h
+++ b/libnemo-private/nemo-global-preferences.h
@@ -226,6 +226,8 @@ typedef enum
#define NEMO_PREFERENCES_DESKTOP_VOLUMES_VISIBLE "volumes-visible"
#define NEMO_PREFERENCES_DESKTOP_NETWORK_VISIBLE "network-icon-visible"
#define NEMO_PREFERENCES_DESKTOP_BACKGROUND_FADE "background-fade"
+#define NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW "desktop-text-shadow"
+#define NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW_USE_THEME "desktop-text-shadow-use-theme"
#define NEMO_PREFERENCES_DESKTOP_IGNORED_DESKTOP_HANDLERS "ignored-desktop-handlers"
/* bulk rename utility */
diff --git a/libnemo-private/nemo-icon-container.c b/libnemo-private/nemo-icon-container.c
index e35283290..1903bf5cb 100644
--- a/libnemo-private/nemo-icon-container.c
+++ b/libnemo-private/nemo-icon-container.c
@@ -7152,6 +7152,38 @@ nemo_icon_container_get_is_desktop (NemoIconContainer *container)
return container->details->is_desktop;
}
+static const gchar *shadow_class_names[] = {
+ "shadow-normal",
+ "shadow-darker",
+ "shadow-darkest"
+};
+
+static void
+update_desktop_shadow_class (NemoIconContainer *container)
+{
+ GtkStyleContext *context;
+ gchar *setting, *class_name;
+ gint i;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (container));
+
+ for (i = 0; i < G_N_ELEMENTS (shadow_class_names); i++) {
+ gtk_style_context_remove_class (context, shadow_class_names[i]);
+ }
+
+ /* The class is always applied. When the user has opted into theme-driven
+ * styling and the theme supports it, nemo-theme-utils skips loading the
+ * shadow stylesheet, so the class simply matches no rules. */
+ setting = g_settings_get_string (nemo_desktop_preferences,
+ NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW);
+ class_name = g_strdup_printf ("shadow-%s", setting);
+ gtk_style_context_add_class (context, class_name);
+ g_free (class_name);
+ g_free (setting);
+
+ gtk_widget_queue_draw (GTK_WIDGET (container));
+}
+
void
nemo_icon_container_set_is_desktop (NemoIconContainer *container,
gboolean is_desktop)
@@ -7166,6 +7198,9 @@ nemo_icon_container_set_is_desktop (NemoIconContainer *container,
g_signal_handlers_disconnect_by_func (nemo_desktop_preferences,
text_ellipsis_limit_changed_container_callback,
container);
+ g_signal_handlers_disconnect_by_func (nemo_desktop_preferences,
+ update_desktop_shadow_class,
+ container);
if (is_desktop) {
GtkStyleContext *context;
@@ -7173,10 +7208,17 @@ nemo_icon_container_set_is_desktop (NemoIconContainer *container,
context = gtk_widget_get_style_context (GTK_WIDGET (container));
gtk_style_context_add_class (context, "nemo-desktop");
+ update_desktop_shadow_class (container);
+
g_signal_connect_swapped (nemo_desktop_preferences,
"changed::" NEMO_PREFERENCES_DESKTOP_TEXT_ELLIPSIS_LIMIT,
G_CALLBACK (text_ellipsis_limit_changed_container_callback),
container);
+
+ g_signal_connect_swapped (nemo_desktop_preferences,
+ "changed::" NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW,
+ G_CALLBACK (update_desktop_shadow_class),
+ container);
} else {
g_signal_connect_swapped (nemo_icon_view_preferences,
"changed::" NEMO_PREFERENCES_ICON_VIEW_TEXT_ELLIPSIS_LIMIT,
diff --git a/libnemo-private/nemo-theme-utils.c b/libnemo-private/nemo-theme-utils.c
new file mode 100644
index 000000000..916f91c85
--- /dev/null
+++ b/libnemo-private/nemo-theme-utils.c
@@ -0,0 +1,294 @@
+#include "nemo-theme-utils.h"
+#include "nemo-global-preferences.h"
+
+#include
+
+static GtkCssProvider *mandatory_css_provider = NULL;
+static GtkCssProvider *desktop_css_provider = NULL;
+static gboolean theme_has_desktop_support = FALSE;
+
+static gboolean
+css_provider_load_from_resource (GtkCssProvider *provider,
+ const char *resource_path,
+ GError **error)
+{
+ GBytes *data;
+ gboolean retval;
+
+ data = g_resources_lookup_data (resource_path, 0, error);
+ if (!data)
+ return FALSE;
+
+ retval = gtk_css_provider_load_from_data (provider,
+ g_bytes_get_data (data, NULL),
+ g_bytes_get_size (data),
+ error);
+ g_bytes_unref (data);
+
+ return retval;
+}
+
+static gchar *
+load_file_contents_from_resource (const char *resource_path,
+ GError **error)
+{
+ GBytes *data;
+ gchar *retval;
+
+ data = g_resources_lookup_data (resource_path, 0, error);
+
+ if (!data) {
+ return NULL;
+ }
+
+ retval = g_strdup ((gchar *) g_bytes_get_data (data, NULL));
+
+ g_bytes_unref (data);
+
+ return retval;
+}
+
+static void
+add_css_provider_at_priority (const gchar *rpath, guint priority)
+{
+ GtkCssProvider *provider;
+ GError *error = NULL;
+
+ provider = gtk_css_provider_new ();
+
+ if (!css_provider_load_from_resource (provider, rpath, &error))
+ {
+ g_warning ("Failed to load css file '%s': %s", rpath, error->message);
+ g_clear_error (&error);
+ goto out;
+ }
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ priority);
+
+out:
+ g_object_unref (provider);
+}
+
+static void
+add_fallback_mandatory_css_provider (const gchar *theme_name)
+{
+ GtkCssProvider *current_provider;
+ g_autofree gchar *css = NULL;
+ g_autofree gchar *init_fallback_css = NULL;
+ g_autofree gchar *final_fallback_css = NULL;
+ GError *error = NULL;
+
+ current_provider = gtk_css_provider_get_named (theme_name, NULL);
+
+ css = gtk_css_provider_to_string (current_provider);
+
+ if (!g_strstr_len (css, -1, "nemo")) {
+ g_warning ("The theme appears to have no nemo support. Adding some...");
+
+ init_fallback_css = load_file_contents_from_resource ("/org/nemo/nemo-style-fallback-mandatory.css",
+ &error);
+
+ if (!init_fallback_css) {
+ g_warning ("Failed to load fallback mandatory css file: %s", error->message);
+ g_clear_error (&error);
+
+ goto out;
+ }
+ } else {
+ goto out;
+ }
+
+ if (g_strstr_len (css, -1, "theme_selected_bg_color")) {
+ final_fallback_css = g_strdup (init_fallback_css);
+
+ goto apply;
+ }
+
+ /* Some themes don't prefix colors with theme_ - remove this from our fallback css */
+ if (g_strstr_len (css, -1, "@define-color selected_bg_color")) {
+ g_warning ("Replacing theme_selected_bg_color with selected_bg_color");
+ final_fallback_css = eel_str_replace_substring (init_fallback_css,
+ "@theme_",
+ "@");
+ } else {
+ /* If we can find neither, just bail out */
+ g_warning ("Theme lacks both theme_selected_bg_color and selected_bg_color - "
+ "cannot apply fallback CSS");
+ goto out;
+ }
+
+apply:
+ mandatory_css_provider = gtk_css_provider_new ();
+
+ gtk_css_provider_load_from_data (mandatory_css_provider,
+ final_fallback_css,
+ -1,
+ &error);
+
+ if (error) {
+ g_warning ("Failed to create a fallback provider: %s", error->message);
+ g_clear_error (&error);
+ g_clear_object (&mandatory_css_provider);
+ goto out;
+ }
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (mandatory_css_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+out:
+ ;
+}
+
+static const char *supported_theme_hints[] = {
+ "mint",
+ "arc",
+ "numix",
+ "matcha"
+};
+
+static gboolean
+is_known_supported_theme (const gchar *theme_name)
+{
+ gint i;
+ gchar *name;
+ gboolean ret;
+
+ name = g_utf8_casefold (theme_name, -1);
+ ret = FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (supported_theme_hints); i++) {
+ gchar *hint;
+
+ hint = g_utf8_casefold (supported_theme_hints[i], -1);
+
+ if (g_strstr_len (name, -1, hint)) {
+ ret = TRUE;
+ }
+
+ g_free (hint);
+
+ if (ret) {
+ break;
+ }
+ }
+
+ g_free (name);
+
+ return ret;
+}
+
+static void
+check_desktop_support (const gchar *theme_name)
+{
+ GtkCssProvider *provider;
+ gchar *css;
+
+ provider = gtk_css_provider_get_named (theme_name, NULL);
+ css = gtk_css_provider_to_string (provider);
+
+ theme_has_desktop_support = (g_strstr_len (css, -1, "nemo-desktop") != NULL);
+
+ g_free (css);
+}
+
+static void
+update_desktop_provider (void)
+{
+ gboolean use_theme;
+ gboolean should_load;
+
+ use_theme = g_settings_get_boolean (nemo_desktop_preferences,
+ NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW_USE_THEME);
+
+ /* Load our desktop CSS unless the user opted into the theme's own
+ * desktop styling AND the theme actually provides it. */
+ should_load = !(use_theme && theme_has_desktop_support);
+
+ if (should_load && desktop_css_provider == NULL) {
+ GtkCssProvider *provider;
+ GError *error = NULL;
+
+ provider = gtk_css_provider_new ();
+
+ if (!css_provider_load_from_resource (provider, "/org/nemo/nemo-style-desktop.css", &error)) {
+ g_warning ("Failed to load desktop css: %s", error->message);
+ g_clear_error (&error);
+ g_object_unref (provider);
+ return;
+ }
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ desktop_css_provider = provider;
+ } else if (!should_load && desktop_css_provider != NULL) {
+ gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (desktop_css_provider));
+ g_clear_object (&desktop_css_provider);
+ }
+}
+
+static void
+process_theme (GtkSettings *gtk_settings)
+{
+ gchar *theme_name;
+
+ if (mandatory_css_provider != NULL) {
+ gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (mandatory_css_provider));
+ g_clear_object (&mandatory_css_provider);
+ }
+
+ g_object_get (gtk_settings,
+ "gtk-theme-name", &theme_name,
+ NULL);
+
+ if (!is_known_supported_theme (theme_name)) {
+ g_warning ("Current gtk theme is not known to have nemo support (%s) - checking...", theme_name);
+ add_fallback_mandatory_css_provider (theme_name);
+ }
+
+ check_desktop_support (theme_name);
+ update_desktop_provider ();
+
+ gtk_style_context_reset_widgets (gdk_screen_get_default ());
+ g_free (theme_name);
+}
+
+static void
+on_use_theme_setting_changed (GSettings *settings, const gchar *key, gpointer user_data)
+{
+ update_desktop_provider ();
+ gtk_style_context_reset_widgets (gdk_screen_get_default ());
+}
+
+void
+nemo_theme_utils_init_styles (void)
+{
+ static gboolean initialized = FALSE;
+ GtkSettings *gtk_settings;
+
+ if (initialized)
+ return;
+
+ initialized = TRUE;
+
+ add_css_provider_at_priority ("/org/nemo/nemo-style-fallback.css",
+ GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
+
+ add_css_provider_at_priority ("/org/nemo/nemo-style-application.css",
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ gtk_settings = gtk_settings_get_default ();
+
+ g_signal_connect_swapped (gtk_settings, "notify::gtk-theme-name",
+ G_CALLBACK (process_theme), gtk_settings);
+
+ g_signal_connect (nemo_desktop_preferences,
+ "changed::" NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW_USE_THEME,
+ G_CALLBACK (on_use_theme_setting_changed), NULL);
+
+ process_theme (gtk_settings);
+}
diff --git a/libnemo-private/nemo-theme-utils.h b/libnemo-private/nemo-theme-utils.h
new file mode 100644
index 000000000..d74958d35
--- /dev/null
+++ b/libnemo-private/nemo-theme-utils.h
@@ -0,0 +1,8 @@
+#ifndef NEMO_THEME_UTILS_H
+#define NEMO_THEME_UTILS_H
+
+#include
+
+void nemo_theme_utils_init_styles (void);
+
+#endif /* NEMO_THEME_UTILS_H */
diff --git a/libnemo-private/org.nemo.gschema.xml b/libnemo-private/org.nemo.gschema.xml
index abc2814d4..49d01653b 100644
--- a/libnemo-private/org.nemo.gschema.xml
+++ b/libnemo-private/org.nemo.gschema.xml
@@ -626,6 +626,21 @@
Fade the background on change
If set to true, then Nemo will use a fade effect to change the desktop background.
+
+
+
+
+
+
+ 'normal'
+ Desktop icon text shadow level
+ Controls the text shadow for desktop icon labels. Values: "normal", "darker", "darkest".
+
+
+ false
+ Use GTK theme for desktop icon text styling
+ If true and the current GTK theme provides desktop icon styling, use the theme instead of the built-in shadow setting.
+
diff --git a/src/nemo-application.c b/src/nemo-application.c
index 062d105f7..4bede796f 100644
--- a/src/nemo-application.c
+++ b/src/nemo-application.c
@@ -58,6 +58,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -76,7 +77,6 @@
#include
#include
#include
-#include
#include
#define GNOME_DESKTOP_USE_UNSTABLE_API
@@ -100,209 +100,6 @@ static NemoApplication *singleton = NULL;
/* The saving of the accelerator map was requested */
static gboolean save_of_accel_map_requested = FALSE;
-static GtkCssProvider *mandatory_css_provider = NULL;
-
-static gboolean
-css_provider_load_from_resource (GtkCssProvider *provider,
- const char *resource_path,
- GError **error)
-{
- GBytes *data;
- gboolean retval;
-
- data = g_resources_lookup_data (resource_path, 0, error);
- if (!data)
- return FALSE;
-
- retval = gtk_css_provider_load_from_data (provider,
- g_bytes_get_data (data, NULL),
- g_bytes_get_size (data),
- error);
- g_bytes_unref (data);
-
- return retval;
-}
-
-static gchar *
-load_file_contents_from_resource (const char *resource_path,
- GError **error)
-{
- GBytes *data;
- gchar *retval;
-
- data = NULL;
-
- data = g_resources_lookup_data (resource_path, 0, error);
-
- if (!data) {
- return FALSE;
- }
-
- retval = g_strdup ((gchar *) g_bytes_get_data (data, NULL));
-
- g_bytes_unref (data);
-
- return retval;
-}
-
-static void
-add_css_provider_at_priority (const gchar *rpath, guint priority)
-{
- GtkCssProvider *provider;
- GError *error = NULL;
-
- provider = gtk_css_provider_new ();
-
- if (!css_provider_load_from_resource (provider, rpath, &error))
- {
- g_warning ("Failed to load fallback css file: %s", error->message);
- if (error->message != NULL)
- g_error_free (error);
- goto out;
- }
-
- gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
- GTK_STYLE_PROVIDER (provider),
- priority);
-
-out:
- g_object_unref (provider);
-}
-
-static void
-add_fallback_mandatory_css_provider (const gchar *theme_name)
-{
- GtkCssProvider *current_provider;
- gchar *css, *init_fallback_css, *final_fallback_css;
- GError *error = NULL;
-
- current_provider = gtk_css_provider_get_named (theme_name, NULL);
-
- css = gtk_css_provider_to_string (current_provider);
-
- init_fallback_css = NULL;
-
- if (!g_strstr_len (css, -1, "nemo")) {
- g_warning ("The theme appears to have no nemo support. Adding some...");
-
- init_fallback_css = load_file_contents_from_resource ("/org/nemo/nemo-style-fallback-mandatory.css",
- &error);
-
- if (!init_fallback_css) {
- g_warning ("Failed to load fallback mandatory css file: %s", error->message);
- g_clear_error (&error);
-
- goto out;
- }
- } else {
- goto out;
- }
-
- final_fallback_css = NULL;
-
- /* Our fallback uses @theme_ prefixed names for colors. If the active theme does also, skip
- * to apply */
- if (g_strstr_len (css, -1, "theme_selected_bg_color")) {
- final_fallback_css = g_strdup (init_fallback_css);
-
- goto apply;
- }
-
- /* Some themes don't prefix colors with theme_ - remove this from our fallback css */
- if (g_strstr_len (css, -1, "@define-color selected_bg_color")) {
- g_warning ("Replacing theme_selected_bg_color with selected_bg_color");
- final_fallback_css = eel_str_replace_substring (init_fallback_css,
- "@theme_",
- "@");
- } else {
- /* If we can find neither, just bail out */
- goto out;
- }
-
-apply:
- g_free (init_fallback_css);
-
- mandatory_css_provider = gtk_css_provider_new ();
-
- gtk_css_provider_load_from_data (mandatory_css_provider,
- final_fallback_css,
- -1,
- &error);
-
- if (error) {
- g_warning ("Failed to create a fallback provider: %s", error->message);
- g_clear_error (&error);
- goto out;
- }
-
- gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
- GTK_STYLE_PROVIDER (mandatory_css_provider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-out:
- g_free (css);
-}
-
-static const char *supported_theme_hints[] = {
- "mint",
- "arc",
- "numix",
- "matcha"
-};
-
-static gboolean
-is_known_supported_theme (const gchar *theme_name)
-{
- gint i;
- gchar *name;
- gboolean ret;
-
- name = g_utf8_casefold (theme_name, -1);
- ret = FALSE;
-
- for (i = 0; i < G_N_ELEMENTS (supported_theme_hints); i++) {
- gchar *hint;
-
- hint = g_utf8_casefold (supported_theme_hints[i], -1);
-
- if (g_strstr_len (name, -1, hint)) {
- ret = TRUE;
- }
-
- g_free (hint);
-
- if (ret) {
- break;
- }
- }
-
- g_free (name);
-
- return ret;
-}
-
-static void
-process_system_theme (GtkSettings *gtk_settings)
-{
- gchar *theme_name;
-
- if (mandatory_css_provider != NULL) {
- gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (mandatory_css_provider));
- g_clear_object (&mandatory_css_provider);
- }
-
- g_object_get (gtk_settings,
- "gtk-theme-name", &theme_name,
- NULL);
-
- if (!is_known_supported_theme (theme_name)) {
- g_warning ("Current gtk theme is not known to have nemo support (%s) - checking...", theme_name);
- add_fallback_mandatory_css_provider (theme_name);
- }
-
- gtk_style_context_reset_widgets (gdk_screen_get_default ());
- g_free (theme_name);
-}
-
static void
init_icons_and_styles (void)
{
@@ -314,20 +111,7 @@ init_icons_and_styles (void)
NEMO_STATUSBAR_ICON_SIZE,
NEMO_STATUSBAR_ICON_SIZE);
- add_css_provider_at_priority ("/org/nemo/nemo-style-fallback.css",
- GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
-
- add_css_provider_at_priority ("/org/nemo/nemo-style-application.css",
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-
- GtkSettings *gtk_settings = gtk_settings_get_default ();
- /* We create our own 'runtime theme' when we encounter one that doesn't
- * include nemo support. We must listen for the theme changing so this
- * customization can be removed (then re-applied only if necessary for the
- * new theme). */
- g_signal_connect_swapped (gtk_settings, "notify::gtk-theme-name", G_CALLBACK (process_system_theme), gtk_settings);
-
- process_system_theme (gtk_settings);
+ nemo_theme_utils_init_styles ();
}
static gboolean
@@ -631,7 +415,6 @@ nemo_application_quit_mainloop (GApplication *app)
nemo_icon_info_clear_caches ();
save_accel_map (NULL);
g_object_unref (NEMO_APPLICATION (app)->undo_manager);
- g_clear_object (&mandatory_css_provider);
nemo_application_notify_unmount_done (NEMO_APPLICATION (app), NULL);