Skip to content

Commit d7be9b5

Browse files
committed
nemo-desktop: Allow adjustment to label shadow.
Add two settings: - desktop-text-shadow: Three levels of shadow (normal, darker, darkest) - normal being the traditional amount. - desktop-text-shadow-use-theme: If true, and if the theme supports it, allow the GTK theme to control desktop style, including text shadow. Nemo has always checked for theme support at startup and during theme changes, to ensure custom widgets/features worked correctly for users (such as inactive-pane shading). We add another check for 'nemo-desktop' there. If the theme lacks any support, nemo provides it like before, using the shadow-level setting.
1 parent ea52d62 commit d7be9b5

9 files changed

Lines changed: 700 additions & 118 deletions

gresources/nemo-desktop-preferences.glade

Lines changed: 345 additions & 92 deletions
Large diffs are not rendered by default.

gresources/nemo-style-application.css

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
/* Desktop text stuff */
1+
/* Desktop window structure — always applied regardless of theme.
2+
* The desktop window must be transparent so the wallpaper shows through. */
23

34
.nemo-window.nemo-desktop-window notebook,
45
.nemo-window.nemo-desktop-window paned {
@@ -11,37 +12,17 @@
1112
box-shadow: none;
1213
}
1314

14-
NemoDesktopWindow GtkPaned {
15-
background-color: transparent;
16-
}
17-
1815
.nemo-canvas-item {
1916
border-radius: 3px;
2017
}
2118

19+
/* Custom widget property — controls nemo behavior, not appearance. */
2220
.nemo-desktop {
2321
-NemoIconContainer-activate-prelight-icon-label: true;
2422
}
2523

26-
.nemo-desktop.nemo-canvas-item {
27-
color: #eeeeee;
28-
text-shadow: 1px 1px alpha(black, 0.8);
29-
}
30-
31-
.nemo-desktop.nemo-canvas-item:hover {
32-
background-color: alpha(black, 0.5);
33-
background-image: none;
34-
text-shadow: none;
35-
}
36-
37-
.nemo-desktop.nemo-canvas-item:selected {
38-
background-color: alpha(@theme_selected_bg_color, 0.8);
39-
background-image: none;
40-
text-shadow: none;
41-
color: #f5f5f5;
42-
}
43-
44-
/* EelEditableLabel (icon labels) */
24+
/* EelEditableLabel (inline rename entry on desktop).
25+
* Always applied so the rename box stays legible over any wallpaper. */
4526
.nemo-desktop.view .entry,
4627
.nemo-desktop.view .entry:active,
4728
.nemo-desktop.view .entry:focus,

gresources/nemo-style-desktop.css

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* Desktop icon label text shadows.
2+
*
3+
* Nemo applies one of these classes (shadow-normal / shadow-darker /
4+
* shadow-darkest) to the icon container based on the user's preference.
5+
* If "Use GTK theme" is enabled and the current theme provides its own
6+
* .nemo-desktop styling, this entire stylesheet is not loaded — the
7+
* theme controls text appearance directly.
8+
*/
9+
10+
/* Shadow variant: Normal (traditional nemo default) */
11+
.nemo-desktop.nemo-canvas-item.shadow-normal {
12+
color: #eeeeee;
13+
text-shadow: 1px 1px alpha(black, 0.8);
14+
}
15+
16+
/* Shadow variant: Darker */
17+
.nemo-desktop.nemo-canvas-item.shadow-darker {
18+
color: #eeeeee;
19+
text-shadow: 1px 1px black;
20+
}
21+
22+
/* Shadow variant: Darkest */
23+
.nemo-desktop.nemo-canvas-item.shadow-darkest {
24+
color: #eeeeee;
25+
text-shadow: 1px 1px black, 1px 0px alpha(black, 0.6), 0px 1px alpha(black, 0.6);
26+
}
27+
28+
/* Hover for shadow modes */
29+
.nemo-desktop.nemo-canvas-item.shadow-normal:hover,
30+
.nemo-desktop.nemo-canvas-item.shadow-darker:hover,
31+
.nemo-desktop.nemo-canvas-item.shadow-darkest:hover {
32+
background-color: alpha(black, 0.5);
33+
background-image: none;
34+
text-shadow: none;
35+
}
36+
37+
/* Selected for shadow modes */
38+
.nemo-desktop.nemo-canvas-item.shadow-normal:selected,
39+
.nemo-desktop.nemo-canvas-item.shadow-darker:selected,
40+
.nemo-desktop.nemo-canvas-item.shadow-darkest:selected {
41+
background-color: alpha(@theme_selected_bg_color, 0.8);
42+
background-image: none;
43+
text-shadow: none;
44+
color: #f5f5f5;
45+
}

gresources/nemo.gresource.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@
2626
<file>nemo-style-fallback.css</file>
2727
<file>nemo-style-fallback-mandatory.css</file>
2828
<file>nemo-style-application.css</file>
29+
<file>nemo-style-desktop.css</file>
2930
</gresource>
3031
</gresources>

libnemo-extension/nemo-desktop-preferences.c

Lines changed: 178 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,32 @@
33
#include <gtk/gtk.h>
44
#include <gdk/gdk.h>
55
#include <math.h>
6+
#include <glib/gi18n.h>
67
#include "nemo-desktop-preferences.h"
78

9+
#define NUM_SHADOW_OPTIONS 3
10+
11+
static const gchar *shadow_options[NUM_SHADOW_OPTIONS] = {
12+
"normal",
13+
"darker",
14+
"darkest",
15+
};
16+
17+
static const gchar *preview_bg_css =
18+
".shadow-preview-bg {"
19+
" background-image: linear-gradient(to bottom, #7ba4d4, #d4e6f7);"
20+
"}";
21+
822
typedef struct
923
{
1024
GtkBuilder *builder;
1125
GSettings *desktop_settings;
26+
GtkCssProvider *desktop_css_provider;
27+
GtkCssProvider *preview_bg_provider;
28+
GtkWidget *shadow_radios[NUM_SHADOW_OPTIONS];
29+
GtkWidget *shadow_labels[NUM_SHADOW_OPTIONS];
30+
gulong shadow_setting_handler;
31+
gulong font_changed_handler;
1232
} NemoDesktopPreferencesPrivate;
1333

1434
struct _NemoDesktopPreferences
@@ -43,6 +63,141 @@ bind_builder_string_combo (GtkBuilder *builder,
4363
"active-id", G_SETTINGS_BIND_DEFAULT);
4464
}
4565

66+
static void
67+
update_preview_fonts (NemoDesktopPreferencesPrivate *priv)
68+
{
69+
gchar *font_str;
70+
PangoFontDescription *font_desc;
71+
gint i;
72+
73+
font_str = g_settings_get_string (priv->desktop_settings, "font");
74+
font_desc = pango_font_description_from_string (font_str);
75+
g_free (font_str);
76+
77+
for (i = 0; i < NUM_SHADOW_OPTIONS; i++) {
78+
PangoAttrList *attrs = pango_attr_list_new ();
79+
pango_attr_list_insert (attrs, pango_attr_font_desc_new (font_desc));
80+
gtk_label_set_attributes (GTK_LABEL (priv->shadow_labels[i]), attrs);
81+
pango_attr_list_unref (attrs);
82+
}
83+
84+
pango_font_description_free (font_desc);
85+
}
86+
87+
static void
88+
on_shadow_button_toggled (GtkToggleButton *button, gpointer user_data)
89+
{
90+
NemoDesktopPreferencesPrivate *priv = user_data;
91+
const gchar *id;
92+
93+
if (!gtk_toggle_button_get_active (button))
94+
return;
95+
96+
id = g_object_get_data (G_OBJECT (button), "shadow-id");
97+
g_settings_set_string (priv->desktop_settings, "desktop-text-shadow", id);
98+
}
99+
100+
static void
101+
on_shadow_setting_changed (GSettings *settings,
102+
const gchar *key,
103+
gpointer user_data)
104+
{
105+
NemoDesktopPreferences *preferences = NEMO_DESKTOP_PREFERENCES (user_data);
106+
NemoDesktopPreferencesPrivate *priv = preferences->priv;
107+
gchar *current;
108+
gint i;
109+
110+
current = g_settings_get_string (priv->desktop_settings, "desktop-text-shadow");
111+
112+
for (i = 0; i < NUM_SHADOW_OPTIONS; i++) {
113+
if (g_strcmp0 (current, shadow_options[i]) == 0) {
114+
g_signal_handlers_block_by_func (priv->shadow_radios[i],
115+
on_shadow_button_toggled, priv);
116+
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->shadow_radios[i]), TRUE);
117+
g_signal_handlers_unblock_by_func (priv->shadow_radios[i],
118+
on_shadow_button_toggled, priv);
119+
break;
120+
}
121+
}
122+
123+
g_free (current);
124+
}
125+
126+
static void
127+
on_desktop_font_changed (GSettings *settings,
128+
const gchar *key,
129+
gpointer user_data)
130+
{
131+
NemoDesktopPreferences *preferences = NEMO_DESKTOP_PREFERENCES (user_data);
132+
update_preview_fonts (preferences->priv);
133+
}
134+
135+
static void
136+
add_provider_to_widget (GtkWidget *widget, GtkCssProvider *provider)
137+
{
138+
gtk_style_context_add_provider (gtk_widget_get_style_context (widget),
139+
GTK_STYLE_PROVIDER (provider),
140+
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
141+
}
142+
143+
static void
144+
setup_shadow_preview_buttons (NemoDesktopPreferences *preferences)
145+
{
146+
NemoDesktopPreferencesPrivate *priv = preferences->priv;
147+
gchar *current;
148+
gint i;
149+
150+
priv->desktop_css_provider = gtk_css_provider_new ();
151+
gtk_css_provider_load_from_resource (priv->desktop_css_provider,
152+
"/org/nemo/nemo-style-desktop.css");
153+
154+
priv->preview_bg_provider = gtk_css_provider_new ();
155+
gtk_css_provider_load_from_data (priv->preview_bg_provider, preview_bg_css, -1, NULL);
156+
157+
current = g_settings_get_string (priv->desktop_settings, "desktop-text-shadow");
158+
159+
for (i = 0; i < NUM_SHADOW_OPTIONS; i++) {
160+
gchar *name;
161+
162+
name = g_strdup_printf ("shadow_radio_%s", shadow_options[i]);
163+
priv->shadow_radios[i] = GTK_WIDGET (gtk_builder_get_object (priv->builder, name));
164+
g_free (name);
165+
166+
name = g_strdup_printf ("shadow_frame_%s", shadow_options[i]);
167+
add_provider_to_widget (GTK_WIDGET (gtk_builder_get_object (priv->builder, name)),
168+
priv->preview_bg_provider);
169+
g_free (name);
170+
171+
name = g_strdup_printf ("shadow_label_%s", shadow_options[i]);
172+
priv->shadow_labels[i] = GTK_WIDGET (gtk_builder_get_object (priv->builder, name));
173+
g_free (name);
174+
175+
add_provider_to_widget (priv->shadow_labels[i], priv->desktop_css_provider);
176+
177+
g_object_set_data (G_OBJECT (priv->shadow_radios[i]), "shadow-id",
178+
(gpointer) shadow_options[i]);
179+
180+
g_signal_connect (priv->shadow_radios[i], "toggled",
181+
G_CALLBACK (on_shadow_button_toggled), priv);
182+
183+
if (g_strcmp0 (current, shadow_options[i]) == 0) {
184+
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->shadow_radios[i]), TRUE);
185+
}
186+
}
187+
188+
g_free (current);
189+
190+
update_preview_fonts (priv);
191+
192+
priv->shadow_setting_handler =
193+
g_signal_connect (priv->desktop_settings, "changed::desktop-text-shadow",
194+
G_CALLBACK (on_shadow_setting_changed), preferences);
195+
196+
priv->font_changed_handler =
197+
g_signal_connect (priv->desktop_settings, "changed::font",
198+
G_CALLBACK (on_desktop_font_changed), preferences);
199+
}
200+
46201
static void
47202
nemo_desktop_preferences_init (NemoDesktopPreferences *preferences)
48203
{
@@ -96,16 +251,37 @@ nemo_desktop_preferences_init (NemoDesktopPreferences *preferences)
96251
"orphan_switch",
97252
"show-orphaned-desktop-icons");
98253

254+
bind_builder_bool (priv->builder,
255+
priv->desktop_settings,
256+
"use_theme_switch",
257+
"desktop-text-shadow-use-theme");
258+
259+
setup_shadow_preview_buttons (preferences);
260+
99261
gtk_widget_show_all (GTK_WIDGET (preferences));
100262
}
101263

102264
static void
103265
nemo_desktop_preferences_dispose (GObject *object)
104266
{
105267
NemoDesktopPreferences *preferences = NEMO_DESKTOP_PREFERENCES (object);
268+
NemoDesktopPreferencesPrivate *priv = preferences->priv;
269+
270+
if (priv->desktop_settings != NULL) {
271+
if (priv->shadow_setting_handler > 0) {
272+
g_signal_handler_disconnect (priv->desktop_settings, priv->shadow_setting_handler);
273+
priv->shadow_setting_handler = 0;
274+
}
275+
if (priv->font_changed_handler > 0) {
276+
g_signal_handler_disconnect (priv->desktop_settings, priv->font_changed_handler);
277+
priv->font_changed_handler = 0;
278+
}
279+
}
106280

107-
g_clear_object (&preferences->priv->builder);
108-
g_clear_object (&preferences->priv->desktop_settings);
281+
g_clear_object (&priv->desktop_css_provider);
282+
g_clear_object (&priv->preview_bg_provider);
283+
g_clear_object (&priv->builder);
284+
g_clear_object (&priv->desktop_settings);
109285

110286
G_OBJECT_CLASS (nemo_desktop_preferences_parent_class)->dispose (object);
111287
}

libnemo-private/nemo-global-preferences.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ typedef enum
226226
#define NEMO_PREFERENCES_DESKTOP_VOLUMES_VISIBLE "volumes-visible"
227227
#define NEMO_PREFERENCES_DESKTOP_NETWORK_VISIBLE "network-icon-visible"
228228
#define NEMO_PREFERENCES_DESKTOP_BACKGROUND_FADE "background-fade"
229+
#define NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW "desktop-text-shadow"
230+
#define NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW_USE_THEME "desktop-text-shadow-use-theme"
229231
#define NEMO_PREFERENCES_DESKTOP_IGNORED_DESKTOP_HANDLERS "ignored-desktop-handlers"
230232

231233
/* bulk rename utility */

libnemo-private/nemo-icon-container.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7152,6 +7152,38 @@ nemo_icon_container_get_is_desktop (NemoIconContainer *container)
71527152
return container->details->is_desktop;
71537153
}
71547154

7155+
static const gchar *shadow_class_names[] = {
7156+
"shadow-normal",
7157+
"shadow-darker",
7158+
"shadow-darkest"
7159+
};
7160+
7161+
static void
7162+
update_desktop_shadow_class (NemoIconContainer *container)
7163+
{
7164+
GtkStyleContext *context;
7165+
gchar *setting, *class_name;
7166+
gint i;
7167+
7168+
context = gtk_widget_get_style_context (GTK_WIDGET (container));
7169+
7170+
for (i = 0; i < G_N_ELEMENTS (shadow_class_names); i++) {
7171+
gtk_style_context_remove_class (context, shadow_class_names[i]);
7172+
}
7173+
7174+
/* The class is always applied. When the user has opted into theme-driven
7175+
* styling and the theme supports it, nemo-theme-utils skips loading the
7176+
* shadow stylesheet, so the class simply matches no rules. */
7177+
setting = g_settings_get_string (nemo_desktop_preferences,
7178+
NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW);
7179+
class_name = g_strdup_printf ("shadow-%s", setting);
7180+
gtk_style_context_add_class (context, class_name);
7181+
g_free (class_name);
7182+
g_free (setting);
7183+
7184+
gtk_widget_queue_draw (GTK_WIDGET (container));
7185+
}
7186+
71557187
void
71567188
nemo_icon_container_set_is_desktop (NemoIconContainer *container,
71577189
gboolean is_desktop)
@@ -7166,17 +7198,27 @@ nemo_icon_container_set_is_desktop (NemoIconContainer *container,
71667198
g_signal_handlers_disconnect_by_func (nemo_desktop_preferences,
71677199
text_ellipsis_limit_changed_container_callback,
71687200
container);
7201+
g_signal_handlers_disconnect_by_func (nemo_desktop_preferences,
7202+
update_desktop_shadow_class,
7203+
container);
71697204

71707205
if (is_desktop) {
71717206
GtkStyleContext *context;
71727207

71737208
context = gtk_widget_get_style_context (GTK_WIDGET (container));
71747209
gtk_style_context_add_class (context, "nemo-desktop");
71757210

7211+
update_desktop_shadow_class (container);
7212+
71767213
g_signal_connect_swapped (nemo_desktop_preferences,
71777214
"changed::" NEMO_PREFERENCES_DESKTOP_TEXT_ELLIPSIS_LIMIT,
71787215
G_CALLBACK (text_ellipsis_limit_changed_container_callback),
71797216
container);
7217+
7218+
g_signal_connect_swapped (nemo_desktop_preferences,
7219+
"changed::" NEMO_PREFERENCES_DESKTOP_TEXT_SHADOW,
7220+
G_CALLBACK (update_desktop_shadow_class),
7221+
container);
71807222
} else {
71817223
g_signal_connect_swapped (nemo_icon_view_preferences,
71827224
"changed::" NEMO_PREFERENCES_ICON_VIEW_TEXT_ELLIPSIS_LIMIT,

0 commit comments

Comments
 (0)