GCC Code Coverage Report


Directory: ./
File: panels/background/cc-background-panel.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 173 0.0%
Functions: 0 21 0.0%
Branches: 0 81 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (C) 2010 Intel, Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * Author: Thomas Wood <thomas.wood@intel.com>
18 *
19 */
20
21 #include <config.h>
22
23 #include <string.h>
24 #include <glib.h>
25 #include <glib/gi18n-lib.h>
26 #include <glib/gstdio.h>
27
28 #include <gdesktop-enums.h>
29
30 #include "cc-background-panel.h"
31
32 #include "cc-background-chooser.h"
33 #include "cc-background-item.h"
34 #include "cc-background-preview.h"
35 #include "cc-background-resources.h"
36
37 #define WP_PATH_ID "org.gnome.desktop.background"
38 #define WP_LOCK_PATH_ID "org.gnome.desktop.screensaver"
39 #define WP_URI_KEY "picture-uri"
40 #define WP_URI_DARK_KEY "picture-uri-dark"
41 #define WP_OPTIONS_KEY "picture-options"
42 #define WP_SHADING_KEY "color-shading-type"
43 #define WP_PCOLOR_KEY "primary-color"
44 #define WP_SCOLOR_KEY "secondary-color"
45
46 #define INTERFACE_PATH_ID "org.gnome.desktop.interface"
47 #define INTERFACE_COLOR_SCHEME_KEY "color-scheme"
48
49 struct _CcBackgroundPanel
50 {
51 CcPanel parent_instance;
52
53 GDBusConnection *connection;
54
55 GSettings *settings;
56 GSettings *lock_settings;
57 GSettings *interface_settings;
58
59 GDBusProxy *proxy;
60
61 CcBackgroundItem *current_background;
62
63 CcBackgroundChooser *background_chooser;
64 CcBackgroundPreview *default_preview;
65 CcBackgroundPreview *dark_preview;
66 GtkToggleButton *default_toggle;
67 GtkToggleButton *dark_toggle;
68 };
69
70 CC_PANEL_REGISTER (CcBackgroundPanel, cc_background_panel)
71
72 static void on_settings_changed (CcBackgroundPanel *self);
73
74 static void
75 load_custom_css (CcBackgroundPanel *self)
76 {
77 g_autoptr(GtkCssProvider) provider = NULL;
78
79 provider = gtk_css_provider_new ();
80 gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/background/preview.css");
81 gtk_style_context_add_provider_for_display (gdk_display_get_default (),
82 GTK_STYLE_PROVIDER (provider),
83 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
84 }
85
86 static void
87 reload_color_scheme_toggles (CcBackgroundPanel *self)
88 {
89 GDesktopColorScheme scheme;
90
91 scheme = g_settings_get_enum (self->interface_settings, INTERFACE_COLOR_SCHEME_KEY);
92
93 if (scheme == G_DESKTOP_COLOR_SCHEME_DEFAULT)
94 {
95 gtk_toggle_button_set_active (self->default_toggle, TRUE);
96 }
97 else if (scheme == G_DESKTOP_COLOR_SCHEME_PREFER_DARK)
98 {
99 gtk_toggle_button_set_active (self->dark_toggle, TRUE);
100 }
101 else
102 {
103 gtk_toggle_button_set_active (self->default_toggle, FALSE);
104 gtk_toggle_button_set_active (self->dark_toggle, FALSE);
105 }
106 }
107
108 static void
109 transition_screen (CcBackgroundPanel *self)
110 {
111 g_autoptr (GError) error = NULL;
112
113 if (!self->proxy)
114 return;
115
116 g_dbus_proxy_call_sync (self->proxy,
117 "ScreenTransition",
118 NULL,
119 G_DBUS_CALL_FLAGS_NONE,
120 -1,
121 NULL,
122 &error);
123
124 if (error)
125 g_warning ("Couldn't transition screen: %s", error->message);
126 }
127
128 static void
129 set_color_scheme (CcBackgroundPanel *self,
130 GDesktopColorScheme color_scheme)
131 {
132 GDesktopColorScheme scheme;
133
134 scheme = g_settings_get_enum (self->interface_settings,
135 INTERFACE_COLOR_SCHEME_KEY);
136
137 /* We have to check the equality manually to avoid starting an unnecessary
138 * screen transition */
139 if (color_scheme == scheme)
140 return;
141
142 transition_screen (self);
143
144 g_settings_set_enum (self->interface_settings,
145 INTERFACE_COLOR_SCHEME_KEY,
146 color_scheme);
147 }
148
149 /* Color schemes */
150
151 static void
152 on_color_scheme_toggle_active_cb (CcBackgroundPanel *self)
153 {
154 if (gtk_toggle_button_get_active (self->default_toggle))
155 set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_DEFAULT);
156 else if (gtk_toggle_button_get_active (self->dark_toggle))
157 set_color_scheme (self, G_DESKTOP_COLOR_SCHEME_PREFER_DARK);
158 }
159
160 static void
161 got_transition_proxy_cb (GObject *source_object,
162 GAsyncResult *res,
163 gpointer data)
164 {
165 g_autoptr(GError) error = NULL;
166 CcBackgroundPanel *self = data;
167
168 self->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
169
170 if (self->proxy == NULL)
171 {
172 g_warning ("Error creating proxy: %s", error->message);
173 return;
174 }
175 }
176
177 /* Background */
178
179 static void
180 update_preview (CcBackgroundPanel *self)
181 {
182 CcBackgroundItem *current_background;
183
184 current_background = self->current_background;
185 cc_background_preview_set_item (self->default_preview, current_background);
186 cc_background_preview_set_item (self->dark_preview, current_background);
187 }
188
189 static void
190 reload_current_bg (CcBackgroundPanel *self)
191 {
192 CcBackgroundItem *configured;
193 GSettings *settings = NULL;
194 g_autofree gchar *uri = NULL;
195 g_autofree gchar *dark_uri = NULL;
196 g_autofree gchar *pcolor = NULL;
197 g_autofree gchar *scolor = NULL;
198
199 /* initalise the current background information from settings */
200 settings = self->settings;
201 uri = g_settings_get_string (settings, WP_URI_KEY);
202 if (uri && *uri == '\0')
203 g_clear_pointer (&uri, g_free);
204
205
206 configured = cc_background_item_new (uri);
207
208 dark_uri = g_settings_get_string (settings, WP_URI_DARK_KEY);
209 pcolor = g_settings_get_string (settings, WP_PCOLOR_KEY);
210 scolor = g_settings_get_string (settings, WP_SCOLOR_KEY);
211 g_object_set (G_OBJECT (configured),
212 "name", _("Current background"),
213 "uri-dark", dark_uri,
214 "placement", g_settings_get_enum (settings, WP_OPTIONS_KEY),
215 "shading", g_settings_get_enum (settings, WP_SHADING_KEY),
216 "primary-color", pcolor,
217 "secondary-color", scolor,
218 NULL);
219
220 g_clear_object (&self->current_background);
221 self->current_background = configured;
222 cc_background_item_load (configured, NULL);
223
224 cc_background_chooser_set_active_item (self->background_chooser, configured);
225 }
226
227 static void
228 reset_settings_if_defaults (CcBackgroundPanel *self,
229 GSettings *settings,
230 gboolean check_dark)
231 {
232 gsize i;
233 const char *keys[] = {
234 WP_URI_KEY, /* this key needs to be first */
235 WP_URI_DARK_KEY,
236 WP_OPTIONS_KEY,
237 WP_SHADING_KEY,
238 WP_PCOLOR_KEY,
239 WP_SCOLOR_KEY,
240 NULL
241 };
242
243 for (i = 0; keys[i] != NULL; i++)
244 {
245 g_autoptr (GVariant) default_value = NULL;
246 g_autoptr (GVariant) user_value = NULL;
247 gboolean setting_is_default;
248
249 if (!check_dark && g_str_equal (keys[i], WP_URI_DARK_KEY))
250 continue;
251
252 default_value = g_settings_get_default_value (settings, keys[i]);
253 user_value = g_settings_get_value (settings, keys[i]);
254
255 setting_is_default = g_variant_equal (default_value, user_value);
256
257 /* As a courtesy to distros that are a little lackadaisical about making sure
258 * schema defaults match the settings in the background item with the default
259 * picture, we only look at the URI to determine if we shouldn't clean out dconf.
260 *
261 * In otherwords, we still clean out the picture-uri key from dconf when a user
262 * selects the default background in control-center, even if after selecting it
263 * e.g., primary-color still mismatches with schema defaults.
264 */
265 if (g_str_equal (keys[i], WP_URI_KEY) && !setting_is_default)
266 return;
267
268 if (setting_is_default)
269 g_settings_reset (settings, keys[i]);
270 }
271
272 g_settings_apply (settings);
273 }
274
275 static void
276 set_background (CcBackgroundPanel *self,
277 GSettings *settings,
278 CcBackgroundItem *item,
279 gboolean set_dark)
280 {
281 GDesktopBackgroundStyle style;
282 CcBackgroundItemFlags flags;
283 g_autofree gchar *filename = NULL;
284 const char *uri;
285
286 if (item == NULL)
287 return;
288
289 uri = cc_background_item_get_uri (item);
290 flags = cc_background_item_get_flags (item);
291
292 g_settings_set_string (settings, WP_URI_KEY, uri);
293
294 if (set_dark)
295 {
296 const char *uri_dark;
297
298 uri_dark = cc_background_item_get_uri_dark (item);
299
300 if (uri_dark && uri_dark[0])
301 g_settings_set_string (settings, WP_URI_DARK_KEY, uri_dark);
302 else
303 g_settings_set_string (settings, WP_URI_DARK_KEY, uri);
304 }
305
306 /* Also set the placement if we have a URI and the previous value was none */
307 if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
308 {
309 g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
310 }
311 else if (uri != NULL)
312 {
313 style = g_settings_get_enum (settings, WP_OPTIONS_KEY);
314 if (style == G_DESKTOP_BACKGROUND_STYLE_NONE)
315 g_settings_set_enum (settings, WP_OPTIONS_KEY, cc_background_item_get_placement (item));
316 }
317
318 if (flags & CC_BACKGROUND_ITEM_HAS_SHADING)
319 g_settings_set_enum (settings, WP_SHADING_KEY, cc_background_item_get_shading (item));
320
321 g_settings_set_string (settings, WP_PCOLOR_KEY, cc_background_item_get_pcolor (item));
322 g_settings_set_string (settings, WP_SCOLOR_KEY, cc_background_item_get_scolor (item));
323
324 /* Apply all changes */
325 g_settings_apply (settings);
326
327 /* Clean out dconf if the user went back to distro defaults */
328 reset_settings_if_defaults (self, settings, set_dark);
329 }
330
331 static void
332 on_chooser_background_chosen_cb (CcBackgroundPanel *self,
333 CcBackgroundItem *item)
334 {
335 g_signal_handlers_block_by_func (self->settings, on_settings_changed, self);
336
337 set_background (self, self->settings, item, TRUE);
338 set_background (self, self->lock_settings, item, FALSE);
339
340 on_settings_changed (self);
341
342 g_signal_handlers_unblock_by_func (self->settings, on_settings_changed, self);
343 }
344
345 static void
346 on_add_picture_button_clicked_cb (CcBackgroundPanel *self)
347 {
348 cc_background_chooser_select_file (self->background_chooser);
349 }
350
351 static const char *
352 cc_background_panel_get_help_uri (CcPanel *panel)
353 {
354 return "help:gnome-help/look-background";
355 }
356
357 static void
358 cc_background_panel_dispose (GObject *object)
359 {
360 CcBackgroundPanel *self = CC_BACKGROUND_PANEL (object);
361
362 g_clear_object (&self->settings);
363 g_clear_object (&self->lock_settings);
364 g_clear_object (&self->interface_settings);
365 g_clear_object (&self->proxy);
366
367 G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
368 }
369
370 static void
371 cc_background_panel_finalize (GObject *object)
372 {
373 CcBackgroundPanel *self = CC_BACKGROUND_PANEL (object);
374
375 g_clear_object (&self->current_background);
376
377 G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object);
378 }
379
380 static void
381 cc_background_panel_class_init (CcBackgroundPanelClass *klass)
382 {
383 GObjectClass *object_class = G_OBJECT_CLASS (klass);
384 CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
385 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
386
387 g_type_ensure (CC_TYPE_BACKGROUND_CHOOSER);
388 g_type_ensure (CC_TYPE_BACKGROUND_PREVIEW);
389
390 panel_class->get_help_uri = cc_background_panel_get_help_uri;
391
392 object_class->dispose = cc_background_panel_dispose;
393 object_class->finalize = cc_background_panel_finalize;
394
395 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-panel.ui");
396
397 gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, background_chooser);
398 gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_preview);
399 gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_preview);
400 gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, default_toggle);
401 gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, dark_toggle);
402
403 gtk_widget_class_bind_template_callback (widget_class, on_color_scheme_toggle_active_cb);
404 gtk_widget_class_bind_template_callback (widget_class, on_chooser_background_chosen_cb);
405 gtk_widget_class_bind_template_callback (widget_class, on_add_picture_button_clicked_cb);
406 }
407
408 static void
409 on_settings_changed (CcBackgroundPanel *self)
410 {
411 reload_current_bg (self);
412 update_preview (self);
413 }
414
415 static void
416 cc_background_panel_init (CcBackgroundPanel *self)
417 {
418 g_resources_register (cc_background_get_resource ());
419
420 gtk_widget_init_template (GTK_WIDGET (self));
421
422 self->connection = g_application_get_dbus_connection (g_application_get_default ());
423
424 self->settings = g_settings_new (WP_PATH_ID);
425 g_settings_delay (self->settings);
426
427 self->lock_settings = g_settings_new (WP_LOCK_PATH_ID);
428 g_settings_delay (self->lock_settings);
429
430 self->interface_settings = g_settings_new (INTERFACE_PATH_ID);
431
432 /* Load the background */
433 reload_current_bg (self);
434 update_preview (self);
435
436 /* Background settings */
437 g_signal_connect_object (self->settings, "changed", G_CALLBACK (on_settings_changed), self, G_CONNECT_SWAPPED);
438
439 /* Interface settings */
440 reload_color_scheme_toggles (self);
441
442 g_signal_connect_object (self->interface_settings,
443 "changed::" INTERFACE_COLOR_SCHEME_KEY,
444 G_CALLBACK (reload_color_scheme_toggles),
445 self,
446 G_CONNECT_SWAPPED);
447
448 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
449 G_DBUS_PROXY_FLAGS_NONE,
450 NULL,
451 "org.gnome.Shell",
452 "/org/gnome/Shell",
453 "org.gnome.Shell",
454 NULL,
455 got_transition_proxy_cb,
456 self);
457
458 load_custom_css (self);
459 }
460