1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2000 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library 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 GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.Free
16 */
17
18
19 #include "config.h"
20
21 #include <string.h>
22
23 #include "gtksettings.h"
24
25 #include "gtkmodules.h"
26 #include "gtkmodulesprivate.h"
27 #include "gtksettingsprivate.h"
28 #include "gtkintl.h"
29 #include "gtkwidget.h"
30 #include "gtkprivate.h"
31 #include "gtkcssproviderprivate.h"
32 #include "gtkstyleproviderprivate.h"
33 #include "gtktypebuiltins.h"
34 #include "gtkversion.h"
35 #include "gtkscrolledwindow.h"
36
37 #ifdef GDK_WINDOWING_X11
38 #include "x11/gdkx.h"
39 #include <pango/pangofc-fontmap.h>
40 #endif
41
42 #ifdef GDK_WINDOWING_WAYLAND
43 #include "wayland/gdkwayland.h"
44 #include <pango/pangofc-fontmap.h>
45 #endif
46
47 #ifdef GDK_WINDOWING_BROADWAY
48 #include "broadway/gdkbroadway.h"
49 #endif
50
51 #ifdef GDK_WINDOWING_QUARTZ
52 #include "quartz/gdkquartz.h"
53 #endif
54
55 #ifdef GDK_WINDOWING_WIN32
56 #include "win32/gdkwin32.h"
57 #endif
58
59 #include "deprecated/gtkrc.h"
60
61 #ifdef GDK_WINDOWING_QUARTZ
62 #define PRINT_PREVIEW_COMMAND "open -b com.apple.Preview %f"
63 #else
64 #define PRINT_PREVIEW_COMMAND "evince --unlink-tempfile --preview --print-settings %s %f"
65 #endif
66
67 /**
68 * SECTION:gtksettings
69 * @Short_description: Sharing settings between applications
70 * @Title: Settings
71 *
72 * GtkSettings provide a mechanism to share global settings between
73 * applications.
74 *
75 * On the X window system, this sharing is realized by an
76 * [XSettings](http://www.freedesktop.org/wiki/Specifications/xsettings-spec)
77 * manager that is usually part of the desktop environment, along with
78 * utilities that let the user change these settings. In the absence of
79 * an Xsettings manager, GTK+ reads default values for settings from
80 * `settings.ini` files in
81 * `/etc/gtk-3.0`, `$XDG_CONFIG_DIRS/gtk-3.0`
82 * and `$XDG_CONFIG_HOME/gtk-3.0`.
83 * These files must be valid key files (see #GKeyFile), and have
84 * a section called Settings. Themes can also provide default values
85 * for settings by installing a `settings.ini` file
86 * next to their `gtk.css` file.
87 *
88 * Applications can override system-wide settings by setting the property
89 * of the GtkSettings object with g_object_set(). This should be restricted
90 * to special cases though; GtkSettings are not meant as an application
91 * configuration facility. When doing so, you need to be aware that settings
92 * that are specific to individual widgets may not be available before the
93 * widget type has been realized at least once. The following example
94 * demonstrates a way to do this:
95 * |[<!-- language="C" -->
96 * gtk_init (&argc, &argv);
97 *
98 * // make sure the type is realized
99 * g_type_class_unref (g_type_class_ref (GTK_TYPE_IMAGE_MENU_ITEM));
100 *
101 * g_object_set (gtk_settings_get_default (), "gtk-enable-animations", FALSE, NULL);
102 * ]|
103 *
104 * There is one GtkSettings instance per screen. It can be obtained with
105 * gtk_settings_get_for_screen(), but in many cases, it is more convenient
106 * to use gtk_widget_get_settings(). gtk_settings_get_default() returns the
107 * GtkSettings instance for the default screen.
108 */
109
110
111 #define DEFAULT_TIMEOUT_INITIAL 500
112 #define DEFAULT_TIMEOUT_REPEAT 50
113 #define DEFAULT_TIMEOUT_EXPAND 500
114
115 typedef struct _GtkSettingsPropertyValue GtkSettingsPropertyValue;
116 typedef struct _GtkSettingsValuePrivate GtkSettingsValuePrivate;
117
118 struct _GtkSettingsPrivate
119 {
120 GData *queued_settings; /* of type GtkSettingsValue* */
121 GtkSettingsPropertyValue *property_values;
122 GdkScreen *screen;
123 GSList *style_cascades;
124 GtkCssProvider *theme_provider;
125 GtkCssProvider *key_theme_provider;
126 gint font_size;
127 gboolean font_size_absolute;
128 gchar *font_family;
129 };
130
131 struct _GtkSettingsValuePrivate
132 {
133 GtkSettingsValue public;
134 GtkSettingsSource source;
135 };
136
137 struct _GtkSettingsPropertyValue
138 {
139 GValue value;
140 GtkSettingsSource source;
141 };
142
143 enum {
144 PROP_0,
145 PROP_DOUBLE_CLICK_TIME,
146 PROP_DOUBLE_CLICK_DISTANCE,
147 PROP_CURSOR_BLINK,
148 PROP_CURSOR_BLINK_TIME,
149 PROP_CURSOR_BLINK_TIMEOUT,
150 PROP_SPLIT_CURSOR,
151 PROP_CURSOR_ASPECT_RATIO,
152 PROP_THEME_NAME,
153 PROP_ICON_THEME_NAME,
154 PROP_FALLBACK_ICON_THEME,
155 PROP_KEY_THEME_NAME,
156 PROP_MENU_BAR_ACCEL,
157 PROP_DND_DRAG_THRESHOLD,
158 PROP_FONT_NAME,
159 PROP_ICON_SIZES,
160 PROP_MODULES,
161 PROP_XFT_ANTIALIAS,
162 PROP_XFT_HINTING,
163 PROP_XFT_HINTSTYLE,
164 PROP_XFT_RGBA,
165 PROP_XFT_DPI,
166 PROP_CURSOR_THEME_NAME,
167 PROP_CURSOR_THEME_SIZE,
168 PROP_ALTERNATIVE_BUTTON_ORDER,
169 PROP_ALTERNATIVE_SORT_ARROWS,
170 PROP_SHOW_INPUT_METHOD_MENU,
171 PROP_SHOW_UNICODE_MENU,
172 PROP_TIMEOUT_INITIAL,
173 PROP_TIMEOUT_REPEAT,
174 PROP_TIMEOUT_EXPAND,
175 PROP_COLOR_SCHEME,
176 PROP_ENABLE_ANIMATIONS,
177 PROP_TOUCHSCREEN_MODE,
178 PROP_TOOLTIP_TIMEOUT,
179 PROP_TOOLTIP_BROWSE_TIMEOUT,
180 PROP_TOOLTIP_BROWSE_MODE_TIMEOUT,
181 PROP_KEYNAV_CURSOR_ONLY,
182 PROP_KEYNAV_WRAP_AROUND,
183 PROP_ERROR_BELL,
184 PROP_COLOR_HASH,
185 PROP_FILE_CHOOSER_BACKEND,
186 PROP_PRINT_BACKENDS,
187 PROP_PRINT_PREVIEW_COMMAND,
188 PROP_ENABLE_MNEMONICS,
189 PROP_ENABLE_ACCELS,
190 PROP_RECENT_FILES_LIMIT,
191 PROP_IM_MODULE,
192 PROP_RECENT_FILES_MAX_AGE,
193 PROP_FONTCONFIG_TIMESTAMP,
194 PROP_SOUND_THEME_NAME,
195 PROP_ENABLE_INPUT_FEEDBACK_SOUNDS,
196 PROP_ENABLE_EVENT_SOUNDS,
197 PROP_ENABLE_TOOLTIPS,
198 PROP_TOOLBAR_STYLE,
199 PROP_TOOLBAR_ICON_SIZE,
200 PROP_AUTO_MNEMONICS,
201 PROP_PRIMARY_BUTTON_WARPS_SLIDER,
202 PROP_VISIBLE_FOCUS,
203 PROP_APPLICATION_PREFER_DARK_THEME,
204 PROP_BUTTON_IMAGES,
205 PROP_ENTRY_SELECT_ON_FOCUS,
206 PROP_ENTRY_PASSWORD_HINT_TIMEOUT,
207 PROP_MENU_IMAGES,
208 PROP_MENU_BAR_POPUP_DELAY,
209 PROP_SCROLLED_WINDOW_PLACEMENT,
210 PROP_CAN_CHANGE_ACCELS,
211 PROP_MENU_POPUP_DELAY,
212 PROP_MENU_POPDOWN_DELAY,
213 PROP_LABEL_SELECT_ON_FOCUS,
214 PROP_COLOR_PALETTE,
215 PROP_IM_PREEDIT_STYLE,
216 PROP_IM_STATUS_STYLE,
217 PROP_SHELL_SHOWS_APP_MENU,
218 PROP_SHELL_SHOWS_MENUBAR,
219 PROP_SHELL_SHOWS_DESKTOP,
220 PROP_DECORATION_LAYOUT,
221 PROP_TITLEBAR_DOUBLE_CLICK,
222 PROP_TITLEBAR_MIDDLE_CLICK,
223 PROP_TITLEBAR_RIGHT_CLICK,
224 PROP_DIALOGS_USE_HEADER,
225 PROP_ENABLE_PRIMARY_PASTE,
226 PROP_RECENT_FILES_ENABLED,
227 PROP_LONG_PRESS_TIME,
228 PROP_KEYNAV_USE_CARET,
229 PROP_OVERLAY_SCROLLING
230 };
231
232 /* --- prototypes --- */
233 static void gtk_settings_provider_iface_init (GtkStyleProviderIface *iface);
234 static void gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface);
235
236 static void gtk_settings_finalize (GObject *object);
237 static void gtk_settings_get_property (GObject *object,
238 guint property_id,
239 GValue *value,
240 GParamSpec *pspec);
241 static void gtk_settings_set_property (GObject *object,
242 guint property_id,
243 const GValue *value,
244 GParamSpec *pspec);
245 static void gtk_settings_notify (GObject *object,
246 GParamSpec *pspec);
247 static guint settings_install_property_parser (GtkSettingsClass *class,
248 GParamSpec *pspec,
249 GtkRcPropertyParser parser);
250 static void settings_update_double_click (GtkSettings *settings);
251 static void settings_update_modules (GtkSettings *settings);
252
253 static void settings_update_cursor_theme (GtkSettings *settings);
254 static void settings_update_resolution (GtkSettings *settings);
255 static void settings_update_font_options (GtkSettings *settings);
256 static void settings_update_font_values (GtkSettings *settings);
257 static gboolean settings_update_fontconfig (GtkSettings *settings);
258 static void settings_update_theme (GtkSettings *settings);
259 static void settings_update_key_theme (GtkSettings *settings);
260 static gboolean settings_update_xsetting (GtkSettings *settings,
261 GParamSpec *pspec,
262 gboolean force);
263 static void settings_update_xsettings (GtkSettings *settings);
264
265 static void gtk_settings_load_from_key_file (GtkSettings *settings,
266 const gchar *path,
267 GtkSettingsSource source);
268 static void settings_update_provider (GdkScreen *screen,
269 GtkCssProvider **old,
270 GtkCssProvider *new);
271
272 /* the default palette for GtkColorSelelection */
273 static const gchar default_color_palette[] =
274 "black:white:gray50:red:purple:blue:light blue:green:yellow:orange:"
275 "lavender:brown:goldenrod4:dodger blue:pink:light green:gray10:gray30:gray75:gray90";
276
277 /* --- variables --- */
278 static GQuark quark_property_parser = 0;
279 static GQuark quark_gtk_settings = 0;
280 static GSList *object_list = NULL;
281 static guint class_n_properties = 0;
282
283 typedef struct {
284 GdkDisplay *display;
285 GtkSettings *settings;
286 } DisplaySettings;
287
288 static GArray *display_settings;
289
290
291 G_DEFINE_TYPE_EXTENDED (GtkSettings, gtk_settings, G_TYPE_OBJECT, 0,
292 G_ADD_PRIVATE (GtkSettings)
293 G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
294 gtk_settings_provider_iface_init)
295 G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE,
296 gtk_settings_provider_private_init));
297
298 /* --- functions --- */
299 static void
gtk_settings_init(GtkSettings * settings)300 gtk_settings_init (GtkSettings *settings)
301 {
302 GtkSettingsPrivate *priv;
303 GParamSpec **pspecs, **p;
304 guint i = 0;
305 gchar *path;
306 const gchar * const *config_dirs;
307
308 priv = gtk_settings_get_instance_private (settings);
309 settings->priv = priv;
310
311 g_datalist_init (&priv->queued_settings);
312 object_list = g_slist_prepend (object_list, settings);
313
314 priv->style_cascades = g_slist_prepend (NULL, _gtk_style_cascade_new ());
315 priv->theme_provider = gtk_css_provider_new ();
316
317 /* build up property array for all yet existing properties and queue
318 * notification for them (at least notification for internal properties
319 * will instantly be caught)
320 */
321 pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), NULL);
322 for (p = pspecs; *p; p++)
323 if ((*p)->owner_type == G_OBJECT_TYPE (settings))
324 i++;
325 priv->property_values = g_new0 (GtkSettingsPropertyValue, i);
326 i = 0;
327 g_object_freeze_notify (G_OBJECT (settings));
328
329 for (p = pspecs; *p; p++)
330 {
331 GParamSpec *pspec = *p;
332 GType value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
333
334 if (pspec->owner_type != G_OBJECT_TYPE (settings))
335 continue;
336 g_value_init (&priv->property_values[i].value, value_type);
337 g_param_value_set_default (pspec, &priv->property_values[i].value);
338
339 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
340 priv->property_values[i].source = GTK_SETTINGS_SOURCE_DEFAULT;
341 i++;
342 }
343 g_free (pspecs);
344
345 path = g_build_filename (_gtk_get_data_prefix (), "share", "gtk-3.0", "settings.ini", NULL);
346 if (g_file_test (path, G_FILE_TEST_EXISTS))
347 gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_DEFAULT);
348 g_free (path);
349
350 path = g_build_filename (_gtk_get_sysconfdir (), "gtk-3.0", "settings.ini", NULL);
351 if (g_file_test (path, G_FILE_TEST_EXISTS))
352 gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_DEFAULT);
353 g_free (path);
354
355 config_dirs = g_get_system_config_dirs ();
356 for (i = 0; config_dirs[i] != NULL; i++)
357 {
358 path = g_build_filename (config_dirs[i], "gtk-3.0", "settings.ini", NULL);
359 if (g_file_test (path, G_FILE_TEST_EXISTS))
360 gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_DEFAULT);
361 g_free (path);
362 }
363
364 path = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "settings.ini", NULL);
365 if (g_file_test (path, G_FILE_TEST_EXISTS))
366 gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_DEFAULT);
367 g_free (path);
368
369 g_object_thaw_notify (G_OBJECT (settings));
370
371 /* ensure that derived fields are initialized */
372 if (priv->font_size == 0)
373 settings_update_font_values (settings);
374 }
375
376 static void
gtk_settings_class_init(GtkSettingsClass * class)377 gtk_settings_class_init (GtkSettingsClass *class)
378 {
379 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
380 guint result;
381
382 gobject_class->finalize = gtk_settings_finalize;
383 gobject_class->get_property = gtk_settings_get_property;
384 gobject_class->set_property = gtk_settings_set_property;
385 gobject_class->notify = gtk_settings_notify;
386
387 quark_property_parser = g_quark_from_static_string ("gtk-rc-property-parser");
388 quark_gtk_settings = g_quark_from_static_string ("gtk-settings");
389
390 result = settings_install_property_parser (class,
391 g_param_spec_int ("gtk-double-click-time",
392 P_("Double Click Time"),
393 P_("Maximum time allowed between two clicks for them to be considered a double click (in milliseconds)"),
394 0, G_MAXINT, 400,
395 GTK_PARAM_READWRITE),
396 NULL);
397 g_assert (result == PROP_DOUBLE_CLICK_TIME);
398 result = settings_install_property_parser (class,
399 g_param_spec_int ("gtk-double-click-distance",
400 P_("Double Click Distance"),
401 P_("Maximum distance allowed between two clicks for them to be considered a double click (in pixels)"),
402 0, G_MAXINT, 5,
403 GTK_PARAM_READWRITE),
404 NULL);
405 g_assert (result == PROP_DOUBLE_CLICK_DISTANCE);
406
407 /**
408 * GtkSettings:gtk-cursor-blink:
409 *
410 * Whether the cursor should blink.
411 *
412 * Also see the #GtkSettings:gtk-cursor-blink-timeout setting,
413 * which allows more flexible control over cursor blinking.
414 */
415 result = settings_install_property_parser (class,
416 g_param_spec_boolean ("gtk-cursor-blink",
417 P_("Cursor Blink"),
418 P_("Whether the cursor should blink"),
419 TRUE,
420 GTK_PARAM_READWRITE ),
421 NULL);
422 g_assert (result == PROP_CURSOR_BLINK);
423 result = settings_install_property_parser (class,
424 g_param_spec_int ("gtk-cursor-blink-time",
425 P_("Cursor Blink Time"),
426 P_("Length of the cursor blink cycle, in milliseconds"),
427 100, G_MAXINT, 1200,
428 GTK_PARAM_READWRITE),
429 NULL);
430 g_assert (result == PROP_CURSOR_BLINK_TIME);
431
432 /**
433 * GtkSettings:gtk-cursor-blink-timeout:
434 *
435 * Time after which the cursor stops blinking, in seconds.
436 * The timer is reset after each user interaction.
437 *
438 * Setting this to zero has the same effect as setting
439 * #GtkSettings:gtk-cursor-blink to %FALSE.
440 *
441 * Since: 2.12
442 */
443 result = settings_install_property_parser (class,
444 g_param_spec_int ("gtk-cursor-blink-timeout",
445 P_("Cursor Blink Timeout"),
446 P_("Time after which the cursor stops blinking, in seconds"),
447 1, G_MAXINT, 10,
448 GTK_PARAM_READWRITE),
449 NULL);
450 g_assert (result == PROP_CURSOR_BLINK_TIMEOUT);
451 result = settings_install_property_parser (class,
452 g_param_spec_boolean ("gtk-split-cursor",
453 P_("Split Cursor"),
454 P_("Whether two cursors should be displayed for mixed left-to-right and right-to-left text"),
455 TRUE,
456 GTK_PARAM_READWRITE),
457 NULL);
458 g_assert (result == PROP_SPLIT_CURSOR);
459 result = settings_install_property_parser (class,
460 g_param_spec_float ("gtk-cursor-aspect-ratio",
461 P_("Cursor Aspect Ratio"),
462 P_("The aspect ratio of the text caret"),
463 0.0, 1.0, 0.04,
464 GTK_PARAM_READWRITE),
465 NULL);
466
467 g_assert (result == PROP_CURSOR_ASPECT_RATIO);
468 result = settings_install_property_parser (class,
469 g_param_spec_string ("gtk-theme-name",
470 P_("Theme Name"),
471 P_("Name of theme to load"),
472 DEFAULT_THEME_NAME,
473 GTK_PARAM_READWRITE),
474 NULL);
475 g_assert (result == PROP_THEME_NAME);
476
477 result = settings_install_property_parser (class,
478 g_param_spec_string ("gtk-icon-theme-name",
479 P_("Icon Theme Name"),
480 P_("Name of icon theme to use"),
481 DEFAULT_ICON_THEME,
482 GTK_PARAM_READWRITE),
483 NULL);
484 g_assert (result == PROP_ICON_THEME_NAME);
485
486 /**
487 * GtkSettings:gtk-fallback-icon-theme:
488 *
489 * Name of a icon theme to fall back to.
490 *
491 * Deprecated: 3.10: This setting is ignored.
492 */
493 result = settings_install_property_parser (class,
494 g_param_spec_string ("gtk-fallback-icon-theme",
495 P_("Fallback Icon Theme Name"),
496 P_("Name of a icon theme to fall back to"),
497 NULL,
498 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
499 NULL);
500 g_assert (result == PROP_FALLBACK_ICON_THEME);
501
502 result = settings_install_property_parser (class,
503 g_param_spec_string ("gtk-key-theme-name",
504 P_("Key Theme Name"),
505 P_("Name of key theme to load"),
506 NULL,
507 GTK_PARAM_READWRITE),
508 NULL);
509 g_assert (result == PROP_KEY_THEME_NAME);
510
511 /**
512 * GtkSettings:gtk-menu-bar-accel:
513 *
514 * Keybinding to activate the menu bar.
515 *
516 * Deprecated: 3.10: This setting can still be used for application
517 * overrides, but will be ignored in the future
518 */
519 result = settings_install_property_parser (class,
520 g_param_spec_string ("gtk-menu-bar-accel",
521 P_("Menu bar accelerator"),
522 P_("Keybinding to activate the menu bar"),
523 "F10",
524 GTK_PARAM_READWRITE),
525 NULL);
526 g_assert (result == PROP_MENU_BAR_ACCEL);
527
528 result = settings_install_property_parser (class,
529 g_param_spec_int ("gtk-dnd-drag-threshold",
530 P_("Drag threshold"),
531 P_("Number of pixels the cursor can move before dragging"),
532 1, G_MAXINT, 8,
533 GTK_PARAM_READWRITE),
534 NULL);
535 g_assert (result == PROP_DND_DRAG_THRESHOLD);
536
537 /**
538 * GtkSettings:gtk-font-name:
539 *
540 * The default font to use. GTK+ uses the family name and size from this string.
541 */
542 result = settings_install_property_parser (class,
543 g_param_spec_string ("gtk-font-name",
544 P_("Font Name"),
545 P_("The default font family and size to use"),
546 "Sans 10",
547 GTK_PARAM_READWRITE),
548 NULL);
549 g_assert (result == PROP_FONT_NAME);
550
551 /**
552 * GtkSettings:gtk-icon-sizes:
553 *
554 * A list of icon sizes. The list is separated by colons, and
555 * item has the form:
556 *
557 * `size-name` = `width` , `height`
558 *
559 * E.g. "gtk-menu=16,16:gtk-button=20,20:gtk-dialog=48,48".
560 * GTK+ itself use the following named icon sizes: gtk-menu,
561 * gtk-button, gtk-small-toolbar, gtk-large-toolbar, gtk-dnd,
562 * gtk-dialog. Applications can register their own named icon
563 * sizes with gtk_icon_size_register().
564 *
565 * Deprecated: 3.10: This setting is ignored.
566 */
567 result = settings_install_property_parser (class,
568 g_param_spec_string ("gtk-icon-sizes",
569 P_("Icon Sizes"),
570 P_("List of icon sizes (gtk-menu=16,16:gtk-button=20,20..."),
571 NULL,
572 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
573 NULL);
574 g_assert (result == PROP_ICON_SIZES);
575
576 result = settings_install_property_parser (class,
577 g_param_spec_string ("gtk-modules",
578 P_("GTK Modules"),
579 P_("List of currently active GTK modules"),
580 NULL,
581 GTK_PARAM_READWRITE),
582 NULL);
583 g_assert (result == PROP_MODULES);
584
585 result = settings_install_property_parser (class,
586 g_param_spec_int ("gtk-xft-antialias",
587 P_("Xft Antialias"),
588 P_("Whether to antialias Xft fonts; 0=no, 1=yes, -1=default"),
589 -1, 1, -1,
590 GTK_PARAM_READWRITE),
591 NULL);
592
593 g_assert (result == PROP_XFT_ANTIALIAS);
594
595 result = settings_install_property_parser (class,
596 g_param_spec_int ("gtk-xft-hinting",
597 P_("Xft Hinting"),
598 P_("Whether to hint Xft fonts; 0=no, 1=yes, -1=default"),
599 -1, 1, -1,
600 GTK_PARAM_READWRITE),
601 NULL);
602
603 g_assert (result == PROP_XFT_HINTING);
604
605 result = settings_install_property_parser (class,
606 g_param_spec_string ("gtk-xft-hintstyle",
607 P_("Xft Hint Style"),
608 P_("What degree of hinting to use; hintnone, hintslight, hintmedium, or hintfull"),
609 NULL,
610 GTK_PARAM_READWRITE),
611 NULL);
612
613 g_assert (result == PROP_XFT_HINTSTYLE);
614
615 result = settings_install_property_parser (class,
616 g_param_spec_string ("gtk-xft-rgba",
617 P_("Xft RGBA"),
618 P_("Type of subpixel antialiasing; none, rgb, bgr, vrgb, vbgr"),
619 NULL,
620 GTK_PARAM_READWRITE),
621 NULL);
622
623 g_assert (result == PROP_XFT_RGBA);
624
625 result = settings_install_property_parser (class,
626 g_param_spec_int ("gtk-xft-dpi",
627 P_("Xft DPI"),
628 P_("Resolution for Xft, in 1024 * dots/inch. -1 to use default value"),
629 -1, 1024*1024, -1,
630 GTK_PARAM_READWRITE),
631 NULL);
632
633 g_assert (result == PROP_XFT_DPI);
634
635 result = settings_install_property_parser (class,
636 g_param_spec_string ("gtk-cursor-theme-name",
637 P_("Cursor theme name"),
638 P_("Name of the cursor theme to use, or NULL to use the default theme"),
639 NULL,
640 GTK_PARAM_READWRITE),
641 NULL);
642 g_assert (result == PROP_CURSOR_THEME_NAME);
643
644 result = settings_install_property_parser (class,
645 g_param_spec_int ("gtk-cursor-theme-size",
646 P_("Cursor theme size"),
647 P_("Size to use for cursors, or 0 to use the default size"),
648 0, 128, 0,
649 GTK_PARAM_READWRITE),
650 NULL);
651
652 g_assert (result == PROP_CURSOR_THEME_SIZE);
653
654 result = settings_install_property_parser (class,
655 g_param_spec_boolean ("gtk-alternative-button-order",
656 P_("Alternative button order"),
657 P_("Whether buttons in dialogs should use the alternative button order"),
658 FALSE,
659 GTK_PARAM_READWRITE),
660 NULL);
661 g_assert (result == PROP_ALTERNATIVE_BUTTON_ORDER);
662
663 /**
664 * GtkSettings:gtk-alternative-sort-arrows:
665 *
666 * Controls the direction of the sort indicators in sorted list and tree
667 * views. By default an arrow pointing down means the column is sorted
668 * in ascending order. When set to %TRUE, this order will be inverted.
669 *
670 * Since: 2.12
671 */
672 result = settings_install_property_parser (class,
673 g_param_spec_boolean ("gtk-alternative-sort-arrows",
674 P_("Alternative sort indicator direction"),
675 P_("Whether the direction of the sort indicators in list and tree views is inverted compared to the default (where down means ascending)"),
676 FALSE,
677 GTK_PARAM_READWRITE),
678 NULL);
679 g_assert (result == PROP_ALTERNATIVE_SORT_ARROWS);
680
681 /**
682 * GtkSettings:gtk-show-input-method-menu:
683 *
684 * Deprecated: 3.10: This setting is ignored.
685 */
686 result = settings_install_property_parser (class,
687 g_param_spec_boolean ("gtk-show-input-method-menu",
688 P_("Show the 'Input Methods' menu"),
689 P_("Whether the context menus of entries and text views should offer to change the input method"),
690 FALSE,
691 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
692 NULL);
693 g_assert (result == PROP_SHOW_INPUT_METHOD_MENU);
694
695 /**
696 * GtkSettings:gtk-show-unicode-menu:
697 *
698 * Deprecated: 3.10: This setting is ignored.
699 */
700 result = settings_install_property_parser (class,
701 g_param_spec_boolean ("gtk-show-unicode-menu",
702 P_("Show the 'Insert Unicode Control Character' menu"),
703 P_("Whether the context menus of entries and text views should offer to insert control characters"),
704 FALSE,
705 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
706 NULL);
707 g_assert (result == PROP_SHOW_UNICODE_MENU);
708
709 /**
710 * GtkSettings:gtk-timeout-initial:
711 *
712 * Deprecated: 3.10: This setting is ignored.
713 */
714 result = settings_install_property_parser (class,
715 g_param_spec_int ("gtk-timeout-initial",
716 P_("Start timeout"),
717 P_("Starting value for timeouts, when button is pressed"),
718 0, G_MAXINT, DEFAULT_TIMEOUT_INITIAL,
719 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
720 NULL);
721
722 g_assert (result == PROP_TIMEOUT_INITIAL);
723
724 /**
725 * GtkSettings:gtk-timeout-repeat:
726 *
727 * Deprecated: 3.10: This setting is ignored.
728 */
729 result = settings_install_property_parser (class,
730 g_param_spec_int ("gtk-timeout-repeat",
731 P_("Repeat timeout"),
732 P_("Repeat value for timeouts, when button is pressed"),
733 0, G_MAXINT, DEFAULT_TIMEOUT_REPEAT,
734 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
735 NULL);
736
737 g_assert (result == PROP_TIMEOUT_REPEAT);
738
739 /**
740 * GtkSettings:gtk-timeout-expand:
741 *
742 * Deprecated: 3.10: This setting is ignored.
743 */
744 result = settings_install_property_parser (class,
745 g_param_spec_int ("gtk-timeout-expand",
746 P_("Expand timeout"),
747 P_("Expand value for timeouts, when a widget is expanding a new region"),
748 0, G_MAXINT, DEFAULT_TIMEOUT_EXPAND,
749 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
750 NULL);
751
752 g_assert (result == PROP_TIMEOUT_EXPAND);
753
754 /**
755 * GtkSettings:gtk-color-scheme:
756 *
757 * A palette of named colors for use in themes. The format of the string is
758 * |[
759 * name1: color1
760 * name2: color2
761 * ...
762 * ]|
763 * Color names must be acceptable as identifiers in the
764 * [gtkrc][gtk3-Resource-Files] syntax, and
765 * color specifications must be in the format accepted by
766 * gdk_color_parse().
767 *
768 * Note that due to the way the color tables from different sources are
769 * merged, color specifications will be converted to hexadecimal form
770 * when getting this property.
771 *
772 * Starting with GTK+ 2.12, the entries can alternatively be separated
773 * by ';' instead of newlines:
774 * |[
775 * name1: color1; name2: color2; ...
776 * ]|
777 *
778 * Since: 2.10
779 *
780 * Deprecated: 3.8: Color scheme support was dropped and is no longer supported.
781 * You can still set this property, but it will be ignored.
782 */
783 result = settings_install_property_parser (class,
784 g_param_spec_string ("gtk-color-scheme",
785 P_("Color scheme"),
786 P_("A palette of named colors for use in themes"),
787 "",
788 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
789 NULL);
790
791 g_assert (result == PROP_COLOR_SCHEME);
792
793 result = settings_install_property_parser (class,
794 g_param_spec_boolean ("gtk-enable-animations",
795 P_("Enable Animations"),
796 P_("Whether to enable toolkit-wide animations."),
797 TRUE,
798 GTK_PARAM_READWRITE),
799 NULL);
800
801 g_assert (result == PROP_ENABLE_ANIMATIONS);
802
803 /**
804 * GtkSettings:gtk-touchscreen-mode:
805 *
806 * When %TRUE, there are no motion notify events delivered on this screen,
807 * and widgets can't use the pointer hovering them for any essential
808 * functionality.
809 *
810 * Since: 2.10
811 *
812 * Deprecated: 3.4. Generally, the behavior for touchscreen input should be
813 * performed dynamically based on gdk_event_get_source_device().
814 */
815 result = settings_install_property_parser (class,
816 g_param_spec_boolean ("gtk-touchscreen-mode",
817 P_("Enable Touchscreen Mode"),
818 P_("When TRUE, there are no motion notify events delivered on this screen"),
819 FALSE,
820 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
821 NULL);
822
823 g_assert (result == PROP_TOUCHSCREEN_MODE);
824
825 /**
826 * GtkSettings:gtk-tooltip-timeout:
827 *
828 * Time, in milliseconds, after which a tooltip could appear if the
829 * cursor is hovering on top of a widget.
830 *
831 * Since: 2.12
832 *
833 * Deprecated: 3.10: This setting is ignored.
834 */
835 result = settings_install_property_parser (class,
836 g_param_spec_int ("gtk-tooltip-timeout",
837 P_("Tooltip timeout"),
838 P_("Timeout before tooltip is shown"),
839 0, G_MAXINT,
840 500,
841 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
842 NULL);
843
844 g_assert (result == PROP_TOOLTIP_TIMEOUT);
845
846 /**
847 * GtkSettings:gtk-tooltip-browse-timeout:
848 *
849 * Controls the time after which tooltips will appear when
850 * browse mode is enabled, in milliseconds.
851 *
852 * Browse mode is enabled when the mouse pointer moves off an object
853 * where a tooltip was currently being displayed. If the mouse pointer
854 * hits another object before the browse mode timeout expires (see
855 * #GtkSettings:gtk-tooltip-browse-mode-timeout), it will take the
856 * amount of milliseconds specified by this setting to popup the tooltip
857 * for the new object.
858 *
859 * Since: 2.12
860 *
861 * Deprecated: 3.10: This setting is ignored.
862 */
863 result = settings_install_property_parser (class,
864 g_param_spec_int ("gtk-tooltip-browse-timeout",
865 P_("Tooltip browse timeout"),
866 P_("Timeout before tooltip is shown when browse mode is enabled"),
867 0, G_MAXINT,
868 60,
869 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
870 NULL);
871
872 g_assert (result == PROP_TOOLTIP_BROWSE_TIMEOUT);
873
874 /**
875 * GtkSettings:gtk-tooltip-browse-mode-timeout:
876 *
877 * Amount of time, in milliseconds, after which the browse mode
878 * will be disabled.
879 *
880 * See #GtkSettings:gtk-tooltip-browse-timeout for more information
881 * about browse mode.
882 *
883 * Since: 2.12
884 *
885 * Deprecated: 3.10: This setting is ignored.
886 */
887 result = settings_install_property_parser (class,
888 g_param_spec_int ("gtk-tooltip-browse-mode-timeout",
889 P_("Tooltip browse mode timeout"),
890 P_("Timeout after which browse mode is disabled"),
891 0, G_MAXINT,
892 500,
893 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
894 NULL);
895
896 g_assert (result == PROP_TOOLTIP_BROWSE_MODE_TIMEOUT);
897
898 /**
899 * GtkSettings:gtk-keynav-cursor-only:
900 *
901 * When %TRUE, keyboard navigation should be able to reach all widgets
902 * by using the cursor keys only. Tab, Shift etc. keys can't be expected
903 * to be present on the used input device.
904 *
905 * Since: 2.12
906 *
907 * Deprecated: 3.10: Generally, the behavior for touchscreen input should be
908 * performed dynamically based on gdk_event_get_source_device().
909 */
910 result = settings_install_property_parser (class,
911 g_param_spec_boolean ("gtk-keynav-cursor-only",
912 P_("Keynav Cursor Only"),
913 P_("When TRUE, there are only cursor keys available to navigate widgets"),
914 FALSE,
915 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
916 NULL);
917
918 g_assert (result == PROP_KEYNAV_CURSOR_ONLY);
919
920 /**
921 * GtkSettings:gtk-keynav-wrap-around:
922 *
923 * When %TRUE, some widgets will wrap around when doing keyboard
924 * navigation, such as menus, menubars and notebooks.
925 *
926 * Since: 2.12
927 *
928 * Deprecated: 3.10: This setting is ignored.
929 */
930 result = settings_install_property_parser (class,
931 g_param_spec_boolean ("gtk-keynav-wrap-around",
932 P_("Keynav Wrap Around"),
933 P_("Whether to wrap around when keyboard-navigating widgets"),
934 TRUE,
935 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
936 NULL);
937
938 g_assert (result == PROP_KEYNAV_WRAP_AROUND);
939
940 /**
941 * GtkSettings:gtk-error-bell:
942 *
943 * When %TRUE, keyboard navigation and other input-related errors
944 * will cause a beep. Since the error bell is implemented using
945 * gdk_window_beep(), the windowing system may offer ways to
946 * configure the error bell in many ways, such as flashing the
947 * window or similar visual effects.
948 *
949 * Since: 2.12
950 */
951 result = settings_install_property_parser (class,
952 g_param_spec_boolean ("gtk-error-bell",
953 P_("Error Bell"),
954 P_("When TRUE, keyboard navigation and other errors will cause a beep"),
955 TRUE,
956 GTK_PARAM_READWRITE),
957 NULL);
958
959 g_assert (result == PROP_ERROR_BELL);
960
961 /**
962 * GtkSettings:color-hash: (type GLib.HashTable(utf8,Gdk.Color)) (transfer container)
963 *
964 * Holds a hash table representation of the #GtkSettings:gtk-color-scheme
965 * setting, mapping color names to #GdkColors.
966 *
967 * Since: 2.10
968 *
969 * Deprecated: 3.8: Will always return an empty hash table.
970 */
971 result = settings_install_property_parser (class,
972 g_param_spec_boxed ("color-hash",
973 P_("Color Hash"),
974 P_("A hash table representation of the color scheme."),
975 G_TYPE_HASH_TABLE,
976 GTK_PARAM_READABLE | G_PARAM_DEPRECATED),
977 NULL);
978 g_assert (result == PROP_COLOR_HASH);
979
980 /**
981 * GtkSettings:gtk-file-chooser-backend:
982 *
983 * Name of the GtkFileChooser backend to use by default.
984 *
985 * Deprecated: 3.10: This setting is ignored. #GtkFileChooser uses GIO by default.
986 */
987 result = settings_install_property_parser (class,
988 g_param_spec_string ("gtk-file-chooser-backend",
989 P_("Default file chooser backend"),
990 P_("Name of the GtkFileChooser backend to use by default"),
991 NULL,
992 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
993 NULL);
994 g_assert (result == PROP_FILE_CHOOSER_BACKEND);
995
996 /**
997 * GtkSettings:gtk-print-backends:
998 *
999 * A comma-separated list of print backends to use in the print
1000 * dialog. Available print backends depend on the GTK+ installation,
1001 * and may include "file", "cups", "lpr" or "papi".
1002 *
1003 * Since: 2.10
1004 */
1005 result = settings_install_property_parser (class,
1006 g_param_spec_string ("gtk-print-backends",
1007 P_("Default print backend"),
1008 P_("List of the GtkPrintBackend backends to use by default"),
1009 GTK_PRINT_BACKENDS,
1010 GTK_PARAM_READWRITE),
1011 NULL);
1012 g_assert (result == PROP_PRINT_BACKENDS);
1013
1014 /**
1015 * GtkSettings:gtk-print-preview-command:
1016 *
1017 * A command to run for displaying the print preview. The command
1018 * should contain a `%f` placeholder, which will get replaced by
1019 * the path to the pdf file. The command may also contain a `%s`
1020 * placeholder, which will get replaced by the path to a file
1021 * containing the print settings in the format produced by
1022 * gtk_print_settings_to_file().
1023 *
1024 * The preview application is responsible for removing the pdf file
1025 * and the print settings file when it is done.
1026 *
1027 * Since: 2.10
1028 */
1029 result = settings_install_property_parser (class,
1030 g_param_spec_string ("gtk-print-preview-command",
1031 P_("Default command to run when displaying a print preview"),
1032 P_("Command to run when displaying a print preview"),
1033 PRINT_PREVIEW_COMMAND,
1034 GTK_PARAM_READWRITE),
1035 NULL);
1036 g_assert (result == PROP_PRINT_PREVIEW_COMMAND);
1037
1038 /**
1039 * GtkSettings:gtk-enable-mnemonics:
1040 *
1041 * Whether labels and menu items should have visible mnemonics which
1042 * can be activated.
1043 *
1044 * Since: 2.12
1045 *
1046 * Deprecated: 3.10: This setting can still be used for application
1047 * overrides, but will be ignored in the future
1048 */
1049 result = settings_install_property_parser (class,
1050 g_param_spec_boolean ("gtk-enable-mnemonics",
1051 P_("Enable Mnemonics"),
1052 P_("Whether labels should have mnemonics"),
1053 TRUE,
1054 GTK_PARAM_READWRITE),
1055 NULL);
1056 g_assert (result == PROP_ENABLE_MNEMONICS);
1057
1058 /**
1059 * GtkSettings:gtk-enable-accels:
1060 *
1061 * Whether menu items should have visible accelerators which can be
1062 * activated.
1063 *
1064 * Since: 2.12
1065 */
1066 result = settings_install_property_parser (class,
1067 g_param_spec_boolean ("gtk-enable-accels",
1068 P_("Enable Accelerators"),
1069 P_("Whether menu items should have accelerators"),
1070 TRUE,
1071 GTK_PARAM_READWRITE),
1072 NULL);
1073 g_assert (result == PROP_ENABLE_ACCELS);
1074
1075 /**
1076 * GtkSettings:gtk-recent-files-limit:
1077 *
1078 * The number of recently used files that should be displayed by default by
1079 * #GtkRecentChooser implementations and by the #GtkFileChooser. A value of
1080 * -1 means every recently used file stored.
1081 *
1082 * Since: 2.12
1083 *
1084 * Deprecated: 3.10: This setting is ignored
1085 */
1086 result = settings_install_property_parser (class,
1087 g_param_spec_int ("gtk-recent-files-limit",
1088 P_("Recent Files Limit"),
1089 P_("Number of recently used files"),
1090 -1, G_MAXINT,
1091 50,
1092 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1093 NULL);
1094 g_assert (result == PROP_RECENT_FILES_LIMIT);
1095
1096 /**
1097 * GtkSettings:gtk-im-module:
1098 *
1099 * Which IM (input method) module should be used by default. This is the
1100 * input method that will be used if the user has not explicitly chosen
1101 * another input method from the IM context menu.
1102 * This also can be a colon-separated list of input methods, which GTK+
1103 * will try in turn until it finds one available on the system.
1104 *
1105 * See #GtkIMContext.
1106 */
1107 result = settings_install_property_parser (class,
1108 g_param_spec_string ("gtk-im-module",
1109 P_("Default IM module"),
1110 P_("Which IM module should be used by default"),
1111 NULL,
1112 GTK_PARAM_READWRITE),
1113 NULL);
1114 g_assert (result == PROP_IM_MODULE);
1115
1116 /**
1117 * GtkSettings:gtk-recent-files-max-age:
1118 *
1119 * The maximum age, in days, of the items inside the recently used
1120 * resources list. Items older than this setting will be excised
1121 * from the list. If set to 0, the list will always be empty; if
1122 * set to -1, no item will be removed.
1123 *
1124 * Since: 2.14
1125 */
1126 result = settings_install_property_parser (class,
1127 g_param_spec_int ("gtk-recent-files-max-age",
1128 P_("Recent Files Max Age"),
1129 P_("Maximum age of recently used files, in days"),
1130 -1, G_MAXINT,
1131 30,
1132 GTK_PARAM_READWRITE),
1133 NULL);
1134 g_assert (result == PROP_RECENT_FILES_MAX_AGE);
1135
1136 result = settings_install_property_parser (class,
1137 g_param_spec_uint ("gtk-fontconfig-timestamp",
1138 P_("Fontconfig configuration timestamp"),
1139 P_("Timestamp of current fontconfig configuration"),
1140 0, G_MAXUINT, 0,
1141 GTK_PARAM_READWRITE),
1142 NULL);
1143
1144 g_assert (result == PROP_FONTCONFIG_TIMESTAMP);
1145
1146 /**
1147 * GtkSettings:gtk-sound-theme-name:
1148 *
1149 * The XDG sound theme to use for event sounds.
1150 *
1151 * See the [Sound Theme Specifications](http://www.freedesktop.org/wiki/Specifications/sound-theme-spec)
1152 * for more information on event sounds and sound themes.
1153 *
1154 * GTK+ itself does not support event sounds, you have to use a loadable
1155 * module like the one that comes with libcanberra.
1156 *
1157 * Since: 2.14
1158 */
1159 result = settings_install_property_parser (class,
1160 g_param_spec_string ("gtk-sound-theme-name",
1161 P_("Sound Theme Name"),
1162 P_("XDG sound theme name"),
1163 "freedesktop",
1164 GTK_PARAM_READWRITE),
1165 NULL);
1166 g_assert (result == PROP_SOUND_THEME_NAME);
1167
1168 /**
1169 * GtkSettings:gtk-enable-input-feedback-sounds:
1170 *
1171 * Whether to play event sounds as feedback to user input.
1172 *
1173 * See the [Sound Theme Specifications](http://www.freedesktop.org/wiki/Specifications/sound-theme-spec)
1174 * for more information on event sounds and sound themes.
1175 *
1176 * GTK+ itself does not support event sounds, you have to use a loadable
1177 * module like the one that comes with libcanberra.
1178 *
1179 * Since: 2.14
1180 */
1181 result = settings_install_property_parser (class,
1182 g_param_spec_boolean ("gtk-enable-input-feedback-sounds",
1183 /* Translators: this means sounds that are played as feedback to user input */
1184 P_("Audible Input Feedback"),
1185 P_("Whether to play event sounds as feedback to user input"),
1186 TRUE,
1187 GTK_PARAM_READWRITE),
1188 NULL);
1189 g_assert (result == PROP_ENABLE_INPUT_FEEDBACK_SOUNDS);
1190
1191 /**
1192 * GtkSettings:gtk-enable-event-sounds:
1193 *
1194 * Whether to play any event sounds at all.
1195 *
1196 * See the [Sound Theme Specifications](http://www.freedesktop.org/wiki/Specifications/sound-theme-spec)
1197 * for more information on event sounds and sound themes.
1198 *
1199 * GTK+ itself does not support event sounds, you have to use a loadable
1200 * module like the one that comes with libcanberra.
1201 *
1202 * Since: 2.14
1203 */
1204 result = settings_install_property_parser (class,
1205 g_param_spec_boolean ("gtk-enable-event-sounds",
1206 P_("Enable Event Sounds"),
1207 P_("Whether to play any event sounds at all"),
1208 TRUE,
1209 GTK_PARAM_READWRITE),
1210 NULL);
1211 g_assert (result == PROP_ENABLE_EVENT_SOUNDS);
1212
1213 /**
1214 * GtkSettings:gtk-enable-tooltips:
1215 *
1216 * Whether tooltips should be shown on widgets.
1217 *
1218 * Since: 2.14
1219 *
1220 * Deprecated: 3.10: This setting is ignored.
1221 */
1222 result = settings_install_property_parser (class,
1223 g_param_spec_boolean ("gtk-enable-tooltips",
1224 P_("Enable Tooltips"),
1225 P_("Whether tooltips should be shown on widgets"),
1226 TRUE,
1227 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1228 NULL);
1229 g_assert (result == PROP_ENABLE_TOOLTIPS);
1230
1231 /**
1232 * GtkSettings:gtk-toolbar-style:
1233 *
1234 * The size of icons in default toolbars.
1235 *
1236 * Deprecated: 3.10: This setting is ignored.
1237 */
1238 result = settings_install_property_parser (class,
1239 g_param_spec_enum ("gtk-toolbar-style",
1240 P_("Toolbar style"),
1241 P_("Whether default toolbars have text only, text and icons, icons only, etc."),
1242 GTK_TYPE_TOOLBAR_STYLE,
1243 GTK_TOOLBAR_BOTH_HORIZ,
1244 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1245 gtk_rc_property_parse_enum);
1246 g_assert (result == PROP_TOOLBAR_STYLE);
1247
1248 /**
1249 * GtkSettings:gtk-toolbar-icon-size:
1250 *
1251 * The size of icons in default toolbars.
1252 *
1253 * Deprecated: 3.10: This setting is ignored.
1254 */
1255 result = settings_install_property_parser (class,
1256 g_param_spec_enum ("gtk-toolbar-icon-size",
1257 P_("Toolbar Icon Size"),
1258 P_("The size of icons in default toolbars."),
1259 GTK_TYPE_ICON_SIZE,
1260 GTK_ICON_SIZE_LARGE_TOOLBAR,
1261 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1262 gtk_rc_property_parse_enum);
1263 g_assert (result == PROP_TOOLBAR_ICON_SIZE);
1264
1265 /**
1266 * GtkSettings:gtk-auto-mnemonics:
1267 *
1268 * Whether mnemonics should be automatically shown and hidden when the user
1269 * presses the mnemonic activator.
1270 *
1271 * Since: 2.20
1272 *
1273 * Deprecated: 3.10: This setting is ignored
1274 */
1275 result = settings_install_property_parser (class,
1276 g_param_spec_boolean ("gtk-auto-mnemonics",
1277 P_("Auto Mnemonics"),
1278 P_("Whether mnemonics should be automatically shown and hidden when the user presses the mnemonic activator."),
1279 TRUE,
1280 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1281 NULL);
1282 g_assert (result == PROP_AUTO_MNEMONICS);
1283
1284 /**
1285 * GtkSettings:gtk-primary-button-warps-slider:
1286 *
1287 * If the value of this setting is %TRUE, clicking the primary button in a
1288 * #GtkRange trough will move the slider, and hence set the range’s value, to
1289 * the point that you clicked. If it is %FALSE, a primary click will cause the
1290 * slider/value to move by the range’s page-size towards the point clicked.
1291 *
1292 * Whichever action you choose for the primary button, the other action will
1293 * be available by holding Shift and primary-clicking, or (since GTK+ 3.22.25)
1294 * clicking the middle mouse button.
1295 *
1296 * Since: 3.6
1297 */
1298 result = settings_install_property_parser (class,
1299 g_param_spec_boolean ("gtk-primary-button-warps-slider",
1300 P_("Primary button warps slider"),
1301 P_("Whether a primary click on the trough should warp the slider into position"),
1302 TRUE,
1303 GTK_PARAM_READWRITE),
1304 NULL);
1305 g_assert (result == PROP_PRIMARY_BUTTON_WARPS_SLIDER);
1306
1307 /**
1308 * GtkSettings:gtk-visible-focus:
1309 *
1310 * Whether 'focus rectangles' should be always visible, never visible,
1311 * or hidden until the user starts to use the keyboard.
1312 *
1313 * Since: 3.2
1314 *
1315 * Deprecated: 3.10: This setting is ignored
1316 */
1317 result = settings_install_property_parser (class,
1318 g_param_spec_enum ("gtk-visible-focus",
1319 P_("Visible Focus"),
1320 P_("Whether 'focus rectangles' should be hidden until the user starts to use the keyboard."),
1321 GTK_TYPE_POLICY_TYPE,
1322 GTK_POLICY_AUTOMATIC,
1323 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1324 gtk_rc_property_parse_enum);
1325 g_assert (result == PROP_VISIBLE_FOCUS);
1326
1327 /**
1328 * GtkSettings:gtk-application-prefer-dark-theme:
1329 *
1330 * Whether the application prefers to use a dark theme. If a GTK+ theme
1331 * includes a dark variant, it will be used instead of the configured
1332 * theme.
1333 *
1334 * Some applications benefit from minimizing the amount of light pollution that
1335 * interferes with the content. Good candidates for dark themes are photo and
1336 * video editors that make the actual content get all the attention and minimize
1337 * the distraction of the chrome.
1338 *
1339 * Dark themes should not be used for documents, where large spaces are white/light
1340 * and the dark chrome creates too much contrast (web browser, text editor...).
1341 *
1342 * Since: 3.0
1343 */
1344 result = settings_install_property_parser (class,
1345 g_param_spec_boolean ("gtk-application-prefer-dark-theme",
1346 P_("Application prefers a dark theme"),
1347 P_("Whether the application prefers to have a dark theme."),
1348 FALSE,
1349 GTK_PARAM_READWRITE),
1350 NULL);
1351 g_assert (result == PROP_APPLICATION_PREFER_DARK_THEME);
1352
1353 /**
1354 * GtkSettings:gtk-button-images:
1355 *
1356 * Whether images should be shown on buttons
1357 *
1358 * Since: 2.4
1359 *
1360 * Deprecated: 3.10: This setting is deprecated. Application developers
1361 * control whether a button should show an icon or not, on a
1362 * per-button basis. If a #GtkButton should show an icon, use the
1363 * #GtkButton:always-show-image property of #GtkButton, and pack a
1364 * #GtkImage inside the #GtkButton
1365 */
1366 result = settings_install_property_parser (class,
1367 g_param_spec_boolean ("gtk-button-images",
1368 P_("Show button images"),
1369 P_("Whether images should be shown on buttons"),
1370 FALSE,
1371 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1372 NULL);
1373 g_assert (result == PROP_BUTTON_IMAGES);
1374
1375 result = settings_install_property_parser (class,
1376 g_param_spec_boolean ("gtk-entry-select-on-focus",
1377 P_("Select on focus"),
1378 P_("Whether to select the contents of an entry when it is focused"),
1379 TRUE,
1380 GTK_PARAM_READWRITE),
1381 NULL);
1382 g_assert (result == PROP_ENTRY_SELECT_ON_FOCUS);
1383
1384 /**
1385 * GtkSettings:gtk-entry-password-hint-timeout:
1386 *
1387 * How long to show the last input character in hidden
1388 * entries. This value is in milliseconds. 0 disables showing the
1389 * last char. 600 is a good value for enabling it.
1390 *
1391 * Since: 2.10
1392 */
1393 result = settings_install_property_parser (class,
1394 g_param_spec_uint ("gtk-entry-password-hint-timeout",
1395 P_("Password Hint Timeout"),
1396 P_("How long to show the last input character in hidden entries"),
1397 0, G_MAXUINT,
1398 0,
1399 GTK_PARAM_READWRITE),
1400 NULL);
1401 g_assert (result == PROP_ENTRY_PASSWORD_HINT_TIMEOUT);
1402
1403 /**
1404 * GtkSettings:gtk-menu-images:
1405 *
1406 * Whether images should be shown in menu items
1407 *
1408 * Deprecated: 3.10: This setting is deprecated. Application developers
1409 * control whether or not a #GtkMenuItem should have an icon or not,
1410 * on a per widget basis. Either use a #GtkMenuItem with a #GtkBox
1411 * containing a #GtkImage and a #GtkAccelLabel, or describe your menus
1412 * using a #GMenu XML description
1413 */
1414 result = settings_install_property_parser (class,
1415 g_param_spec_boolean ("gtk-menu-images",
1416 P_("Show menu images"),
1417 P_("Whether images should be shown in menus"),
1418 FALSE,
1419 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1420 NULL);
1421 g_assert (result == PROP_MENU_IMAGES);
1422
1423 /**
1424 * GtkSettings:gtk-menu-bar-popup-delay:
1425 *
1426 * Delay before the submenus of a menu bar appear.
1427 *
1428 * Deprecated: 3.10: This setting is ignored.
1429 */
1430 result = settings_install_property_parser (class,
1431 g_param_spec_int ("gtk-menu-bar-popup-delay",
1432 P_("Delay before drop down menus appear"),
1433 P_("Delay before the submenus of a menu bar appear"),
1434 0, G_MAXINT,
1435 0,
1436 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1437 NULL);
1438 g_assert (result == PROP_MENU_BAR_POPUP_DELAY);
1439
1440 /**
1441 * GtkSettings:gtk-scrolled-window-placement:
1442 *
1443 * Where the contents of scrolled windows are located with respect to the
1444 * scrollbars, if not overridden by the scrolled window's own placement.
1445 *
1446 * Since: 2.10
1447 *
1448 * Deprecated: 3.10: This setting is ignored.
1449 */
1450 result = settings_install_property_parser (class,
1451 g_param_spec_enum ("gtk-scrolled-window-placement",
1452 P_("Scrolled Window Placement"),
1453 P_("Where the contents of scrolled windows are located with respect to the scrollbars, if not overridden by the scrolled window's own placement."),
1454 GTK_TYPE_CORNER_TYPE,
1455 GTK_CORNER_TOP_LEFT,
1456 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1457 gtk_rc_property_parse_enum);
1458 g_assert (result == PROP_SCROLLED_WINDOW_PLACEMENT);
1459
1460 /**
1461 * GtkSettings:gtk-can-change-accels:
1462 *
1463 * Whether menu accelerators can be changed by pressing a key over the menu item.
1464 *
1465 * Deprecated: 3.10: This setting is ignored.
1466 */
1467 result = settings_install_property_parser (class,
1468 g_param_spec_boolean ("gtk-can-change-accels",
1469 P_("Can change accelerators"),
1470 P_("Whether menu accelerators can be changed by pressing a key over the menu item"),
1471 FALSE,
1472 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1473 NULL);
1474 g_assert (result == PROP_CAN_CHANGE_ACCELS);
1475
1476 /**
1477 * GtkSettings:gtk-menu-popup-delay:
1478 *
1479 * Minimum time the pointer must stay over a menu item before the submenu appear.
1480 *
1481 * Deprecated: 3.10: This setting is ignored.
1482 */
1483 result = settings_install_property_parser (class,
1484 g_param_spec_int ("gtk-menu-popup-delay",
1485 P_("Delay before submenus appear"),
1486 P_("Minimum time the pointer must stay over a menu item before the submenu appear"),
1487 0, G_MAXINT,
1488 225,
1489 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1490 NULL);
1491 g_assert (result == PROP_MENU_POPUP_DELAY);
1492
1493 /**
1494 * GtkSettings:gtk-menu-popdown-delay:
1495 *
1496 * The time before hiding a submenu when the pointer is moving towards the submenu.
1497 *
1498 * Deprecated: 3.10: This setting is ignored.
1499 */
1500 result = settings_install_property_parser (class,
1501 g_param_spec_int ("gtk-menu-popdown-delay",
1502 P_("Delay before hiding a submenu"),
1503 P_("The time before hiding a submenu when the pointer is moving towards the submenu"),
1504 0, G_MAXINT,
1505 1000,
1506 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1507 NULL);
1508 g_assert (result == PROP_MENU_POPDOWN_DELAY);
1509
1510 result = settings_install_property_parser (class,
1511 g_param_spec_boolean ("gtk-label-select-on-focus",
1512 P_("Select on focus"),
1513 P_("Whether to select the contents of a selectable label when it is focused"),
1514 TRUE,
1515 GTK_PARAM_READWRITE),
1516 NULL);
1517 g_assert (result == PROP_LABEL_SELECT_ON_FOCUS);
1518
1519 /**
1520 * GtkSettings:gtk-color-palette:
1521 *
1522 * Palette to use in the deprecated color selector.
1523 *
1524 * Deprecated: 3.10: Only used by the deprecated color selector widget.
1525 */
1526 result = settings_install_property_parser (class,
1527 g_param_spec_string ("gtk-color-palette",
1528 P_("Custom palette"),
1529 P_("Palette to use in the color selector"),
1530 default_color_palette,
1531 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1532 NULL);
1533 g_assert (result == PROP_COLOR_PALETTE);
1534
1535 /**
1536 * GtkSettings:gtk-im-preedit-style:
1537 *
1538 * How to draw the input method preedit string.
1539 *
1540 * Deprecated: 3.10: This setting is ignored.
1541 */
1542 result = settings_install_property_parser (class,
1543 g_param_spec_enum ("gtk-im-preedit-style",
1544 P_("IM Preedit style"),
1545 P_("How to draw the input method preedit string"),
1546 GTK_TYPE_IM_PREEDIT_STYLE,
1547 GTK_IM_PREEDIT_CALLBACK,
1548 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1549 gtk_rc_property_parse_enum);
1550 g_assert (result == PROP_IM_PREEDIT_STYLE);
1551
1552 /**
1553 * GtkSettings:gtk-im-status-style:
1554 *
1555 * How to draw the input method statusbar.
1556 *
1557 * Deprecated: 3.10: This setting is ignored.
1558 */
1559 result = settings_install_property_parser (class,
1560 g_param_spec_enum ("gtk-im-status-style",
1561 P_("IM Status style"),
1562 P_("How to draw the input method statusbar"),
1563 GTK_TYPE_IM_STATUS_STYLE,
1564 GTK_IM_STATUS_CALLBACK,
1565 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED),
1566 gtk_rc_property_parse_enum);
1567 g_assert (result == PROP_IM_STATUS_STYLE);
1568
1569 result = settings_install_property_parser (class,
1570 g_param_spec_boolean ("gtk-shell-shows-app-menu",
1571 P_("Desktop shell shows app menu"),
1572 P_("Set to TRUE if the desktop environment "
1573 "is displaying the app menu, FALSE if "
1574 "the app should display it itself."),
1575 FALSE, GTK_PARAM_READWRITE),
1576 NULL);
1577 g_assert (result == PROP_SHELL_SHOWS_APP_MENU);
1578
1579 result = settings_install_property_parser (class,
1580 g_param_spec_boolean ("gtk-shell-shows-menubar",
1581 P_("Desktop shell shows the menubar"),
1582 P_("Set to TRUE if the desktop environment "
1583 "is displaying the menubar, FALSE if "
1584 "the app should display it itself."),
1585 FALSE, GTK_PARAM_READWRITE),
1586 NULL);
1587 g_assert (result == PROP_SHELL_SHOWS_MENUBAR);
1588
1589 result = settings_install_property_parser (class,
1590 g_param_spec_boolean ("gtk-shell-shows-desktop",
1591 P_("Desktop environment shows the desktop folder"),
1592 P_("Set to TRUE if the desktop environment "
1593 "is displaying the desktop folder, FALSE "
1594 "if not."),
1595 TRUE, GTK_PARAM_READWRITE),
1596 NULL);
1597 g_assert (result == PROP_SHELL_SHOWS_DESKTOP);
1598
1599 /**
1600 * GtkSettings:gtk-decoration-layout:
1601 *
1602 * This setting determines which buttons should be put in the
1603 * titlebar of client-side decorated windows, and whether they
1604 * should be placed at the left of right.
1605 *
1606 * The format of the string is button names, separated by commas.
1607 * A colon separates the buttons that should appear on the left
1608 * from those on the right. Recognized button names are minimize,
1609 * maximize, close, icon (the window icon) and menu (a menu button
1610 * for the fallback app menu).
1611 *
1612 * For example, "menu:minimize,maximize,close" specifies a menu
1613 * on the left, and minimize, maximize and close buttons on the right.
1614 *
1615 * Note that buttons will only be shown when they are meaningful.
1616 * E.g. a menu button only appears when the desktop shell does not
1617 * show the app menu, and a close button only appears on a window
1618 * that can be closed.
1619 *
1620 * Also note that the setting can be overridden with the
1621 * #GtkHeaderBar:decoration-layout property.
1622 *
1623 * Since: 3.12
1624 */
1625 result = settings_install_property_parser (class,
1626 g_param_spec_string ("gtk-decoration-layout",
1627 P_("Decoration Layout"),
1628 P_("The layout for window decorations"),
1629 "menu:minimize,maximize,close", GTK_PARAM_READWRITE),
1630 NULL);
1631 g_assert (result == PROP_DECORATION_LAYOUT);
1632
1633 /**
1634 * GtkSettings:gtk-titlebar-double-click:
1635 *
1636 * This setting determines the action to take when a double-click
1637 * occurs on the titlebar of client-side decorated windows.
1638 *
1639 * Recognized actions are minimize, toggle-maximize, menu, lower
1640 * or none.
1641 *
1642 * Since: 3.14
1643 */
1644 result = settings_install_property_parser (class,
1645 g_param_spec_string ("gtk-titlebar-double-click",
1646 P_("Titlebar double-click action"),
1647 P_("The action to take on titlebar double-click"),
1648 "toggle-maximize", GTK_PARAM_READWRITE),
1649 NULL);
1650 g_assert (result == PROP_TITLEBAR_DOUBLE_CLICK);
1651
1652 /**
1653 * GtkSettings:gtk-titlebar-middle-click:
1654 *
1655 * This setting determines the action to take when a middle-click
1656 * occurs on the titlebar of client-side decorated windows.
1657 *
1658 * Recognized actions are minimize, toggle-maximize, menu, lower
1659 * or none.
1660 *
1661 * Since: 3.14
1662 */
1663 result = settings_install_property_parser (class,
1664 g_param_spec_string ("gtk-titlebar-middle-click",
1665 P_("Titlebar middle-click action"),
1666 P_("The action to take on titlebar middle-click"),
1667 "none", GTK_PARAM_READWRITE),
1668 NULL);
1669 g_assert (result == PROP_TITLEBAR_MIDDLE_CLICK);
1670
1671 /**
1672 * GtkSettings:gtk-titlebar-right-click:
1673 *
1674 * This setting determines the action to take when a right-click
1675 * occurs on the titlebar of client-side decorated windows.
1676 *
1677 * Recognized actions are minimize, toggle-maximize, menu, lower
1678 * or none.
1679 *
1680 * Since: 3.14
1681 */
1682 result = settings_install_property_parser (class,
1683 g_param_spec_string ("gtk-titlebar-right-click",
1684 P_("Titlebar right-click action"),
1685 P_("The action to take on titlebar right-click"),
1686 "menu", GTK_PARAM_READWRITE),
1687 NULL);
1688 g_assert (result == PROP_TITLEBAR_RIGHT_CLICK);
1689
1690
1691
1692
1693 /**
1694 * GtkSettings:gtk-dialogs-use-header:
1695 *
1696 * Whether builtin GTK+ dialogs such as the file chooser, the
1697 * color chooser or the font chooser will use a header bar at
1698 * the top to show action widgets, or an action area at the bottom.
1699 *
1700 * This setting does not affect custom dialogs using GtkDialog
1701 * directly, or message dialogs.
1702 *
1703 * Since: 3.12
1704 */
1705 result = settings_install_property_parser (class,
1706 g_param_spec_boolean ("gtk-dialogs-use-header",
1707 P_("Dialogs use header bar"),
1708 P_("Whether builtin GTK+ dialogs should use a header bar instead of an action area."),
1709 FALSE,
1710 GTK_PARAM_READWRITE),
1711 NULL);
1712 g_assert (result == PROP_DIALOGS_USE_HEADER);
1713
1714 /**
1715 * GtkSettings:gtk-enable-primary-paste:
1716 *
1717 * Whether a middle click on a mouse should paste the
1718 * 'PRIMARY' clipboard content at the cursor location.
1719 *
1720 * Since: 3.4
1721 */
1722 result = settings_install_property_parser (class,
1723 g_param_spec_boolean ("gtk-enable-primary-paste",
1724 P_("Enable primary paste"),
1725 P_("Whether a middle click on a mouse should paste the 'PRIMARY' clipboard content at the cursor location."),
1726 TRUE,
1727 GTK_PARAM_READWRITE),
1728 NULL);
1729 g_assert (result == PROP_ENABLE_PRIMARY_PASTE);
1730
1731 /**
1732 * GtkSettings:gtk-recent-files-enabled:
1733 *
1734 * Whether GTK+ should keep track of items inside the recently used
1735 * resources list. If set to %FALSE, the list will always be empty.
1736 *
1737 * Since: 3.8
1738 */
1739 result = settings_install_property_parser (class,
1740 g_param_spec_boolean ("gtk-recent-files-enabled",
1741 P_("Recent Files Enabled"),
1742 P_("Whether GTK+ remembers recent files"),
1743 TRUE,
1744 GTK_PARAM_READWRITE),
1745 NULL);
1746 g_assert (result == PROP_RECENT_FILES_ENABLED);
1747
1748 /**
1749 * GtkSettings:gtk-long-press-time:
1750 *
1751 * The time for a button or touch press to be considered a "long press".
1752 *
1753 * Since: 3.14
1754 */
1755 result = settings_install_property_parser (class,
1756 g_param_spec_uint ("gtk-long-press-time",
1757 P_("Long press time"),
1758 P_("Time for a button/touch press to be considered a long press (in milliseconds)"),
1759 0, G_MAXINT, 500,
1760 GTK_PARAM_READWRITE),
1761 NULL);
1762 g_assert (result == PROP_LONG_PRESS_TIME);
1763
1764 /**
1765 * GtkSettings:gtk-keynav-use-caret:
1766 *
1767 * Whether GTK+ should make sure that text can be navigated with
1768 * a caret, even if it is not editable. This is useful when using
1769 * a screen reader.
1770 *
1771 * Since: 3.20
1772 */
1773 result = settings_install_property_parser (class,
1774 g_param_spec_boolean ("gtk-keynav-use-caret",
1775 P_("Whether to show cursor in text"),
1776 P_("Whether to show cursor in text"),
1777 FALSE,
1778 GTK_PARAM_READWRITE),
1779 NULL);
1780 g_assert (result == PROP_KEYNAV_USE_CARET);
1781
1782 /**
1783 * GtkSettings:gtk-overlay-scrolling:
1784 *
1785 * Whether scrolled windows may use overlayed scrolling indicators.
1786 * If this is set to %FALSE, scrolled windows will have permanent
1787 * scrollbars.
1788 *
1789 * Since: 3.24.9
1790 */
1791 result = settings_install_property_parser (class,
1792 g_param_spec_boolean ("gtk-overlay-scrolling",
1793 P_("Whether to use overlay scrollbars"),
1794 P_("Whether to use overlay scrollbars"),
1795 TRUE,
1796 GTK_PARAM_READWRITE),
1797 NULL);
1798 g_assert (result == PROP_OVERLAY_SCROLLING);
1799 }
1800
1801 static void
gtk_settings_provider_iface_init(GtkStyleProviderIface * iface)1802 gtk_settings_provider_iface_init (GtkStyleProviderIface *iface)
1803 {
1804 }
1805
1806 static GtkSettings *
gtk_settings_style_provider_get_settings(GtkStyleProviderPrivate * provider)1807 gtk_settings_style_provider_get_settings (GtkStyleProviderPrivate *provider)
1808 {
1809 return GTK_SETTINGS (provider);
1810 }
1811
1812 static void
gtk_settings_provider_private_init(GtkStyleProviderPrivateInterface * iface)1813 gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface)
1814 {
1815 iface->get_settings = gtk_settings_style_provider_get_settings;
1816 }
1817
1818 static void
gtk_settings_finalize(GObject * object)1819 gtk_settings_finalize (GObject *object)
1820 {
1821 GtkSettings *settings = GTK_SETTINGS (object);
1822 GtkSettingsPrivate *priv = settings->priv;
1823 guint i;
1824
1825 object_list = g_slist_remove (object_list, settings);
1826
1827 for (i = 0; i < class_n_properties; i++)
1828 g_value_unset (&priv->property_values[i].value);
1829 g_free (priv->property_values);
1830
1831 g_datalist_clear (&priv->queued_settings);
1832
1833 settings_update_provider (priv->screen, &priv->theme_provider, NULL);
1834 settings_update_provider (priv->screen, &priv->key_theme_provider, NULL);
1835 g_slist_free_full (priv->style_cascades, g_object_unref);
1836
1837 g_free (priv->font_family);
1838
1839 G_OBJECT_CLASS (gtk_settings_parent_class)->finalize (object);
1840 }
1841
1842 GtkStyleCascade *
_gtk_settings_get_style_cascade(GtkSettings * settings,gint scale)1843 _gtk_settings_get_style_cascade (GtkSettings *settings,
1844 gint scale)
1845 {
1846 GtkSettingsPrivate *priv;
1847 GtkStyleCascade *new_cascade;
1848 GSList *list;
1849
1850 g_return_val_if_fail (GTK_IS_SETTINGS (settings), NULL);
1851
1852 priv = settings->priv;
1853 for (list = priv->style_cascades; list; list = list->next)
1854 {
1855 if (_gtk_style_cascade_get_scale (list->data) == scale)
1856 return list->data;
1857 }
1858
1859 /* We are guaranteed to have the special cascade with scale == 1.
1860 * It's created in gtk_settings_init()
1861 */
1862 g_assert (scale != 1);
1863
1864 new_cascade = _gtk_style_cascade_new ();
1865 _gtk_style_cascade_set_parent (new_cascade, _gtk_settings_get_style_cascade (settings, 1));
1866 _gtk_style_cascade_set_scale (new_cascade, scale);
1867
1868 priv->style_cascades = g_slist_prepend (priv->style_cascades, new_cascade);
1869
1870 return new_cascade;
1871 }
1872
1873 static void
settings_init_style(GtkSettings * settings)1874 settings_init_style (GtkSettings *settings)
1875 {
1876 static GtkCssProvider *css_provider = NULL;
1877 GtkStyleCascade *cascade;
1878
1879 /* Add provider for user file */
1880 if (G_UNLIKELY (!css_provider))
1881 {
1882 gchar *css_path;
1883
1884 css_provider = gtk_css_provider_new ();
1885 css_path = g_build_filename (g_get_user_config_dir (),
1886 "gtk-3.0",
1887 "gtk.css",
1888 NULL);
1889
1890 if (g_file_test (css_path,
1891 G_FILE_TEST_IS_REGULAR))
1892 gtk_css_provider_load_from_path (css_provider, css_path, NULL);
1893
1894 g_free (css_path);
1895 }
1896
1897 cascade = _gtk_settings_get_style_cascade (settings, 1);
1898 _gtk_style_cascade_add_provider (cascade,
1899 GTK_STYLE_PROVIDER (css_provider),
1900 GTK_STYLE_PROVIDER_PRIORITY_USER);
1901
1902 _gtk_style_cascade_add_provider (cascade,
1903 GTK_STYLE_PROVIDER (settings),
1904 GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
1905
1906 _gtk_style_cascade_add_provider (cascade,
1907 GTK_STYLE_PROVIDER (settings->priv->theme_provider),
1908 GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
1909
1910 settings_update_theme (settings);
1911 settings_update_key_theme (settings);
1912 }
1913
1914 static void
settings_display_closed(GdkDisplay * display,gboolean is_error,gpointer data)1915 settings_display_closed (GdkDisplay *display,
1916 gboolean is_error,
1917 gpointer data)
1918 {
1919 DisplaySettings *ds;
1920 int i;
1921
1922 if (G_UNLIKELY (display_settings == NULL))
1923 return;
1924
1925 ds = (DisplaySettings *)display_settings->data;
1926 for (i = 0; i < display_settings->len; i++)
1927 {
1928 if (ds[i].display == display)
1929 {
1930 g_clear_object (&ds[i].settings);
1931 display_settings = g_array_remove_index_fast (display_settings, i);
1932 break;
1933 }
1934 }
1935 }
1936
1937 static GtkSettings *
gtk_settings_create_for_display(GdkDisplay * display)1938 gtk_settings_create_for_display (GdkDisplay *display)
1939 {
1940 GtkSettings *settings;
1941 DisplaySettings v;
1942
1943 #ifdef GDK_WINDOWING_QUARTZ
1944 if (GDK_IS_QUARTZ_DISPLAY (display))
1945 settings = g_object_new (GTK_TYPE_SETTINGS,
1946 "gtk-key-theme-name", "Mac",
1947 "gtk-shell-shows-app-menu", TRUE,
1948 "gtk-shell-shows-menubar", TRUE,
1949 NULL);
1950 else
1951 #endif
1952 #ifdef GDK_WINDOWING_BROADWAY
1953 if (GDK_IS_BROADWAY_DISPLAY (display))
1954 settings = g_object_new (GTK_TYPE_SETTINGS,
1955 "gtk-im-module", "broadway",
1956 NULL);
1957 else
1958 #endif
1959 #ifdef GDK_WINDOWING_WAYLAND
1960 if (GDK_IS_WAYLAND_DISPLAY (display))
1961 {
1962 if (gdk_wayland_display_query_registry (display,
1963 "zwp_text_input_manager_v3"))
1964 {
1965 settings = g_object_new (GTK_TYPE_SETTINGS,
1966 "gtk-im-module", "wayland",
1967 NULL);
1968 }
1969 else if (gdk_wayland_display_query_registry (display,
1970 "gtk_text_input_manager"))
1971 {
1972 settings = g_object_new (GTK_TYPE_SETTINGS,
1973 "gtk-im-module", "waylandgtk",
1974 NULL);
1975 }
1976 else
1977 {
1978 /* Fallback to other IM methods if the compositor does not
1979 * implement the interface(s).
1980 */
1981 settings = g_object_new (GTK_TYPE_SETTINGS, NULL);
1982 }
1983 }
1984 else
1985 #endif
1986 settings = g_object_new (GTK_TYPE_SETTINGS, NULL);
1987
1988 settings->priv->screen = gdk_display_get_default_screen (display);
1989
1990 v.display = display;
1991 v.settings = settings;
1992 display_settings = g_array_append_val (display_settings, v);
1993 g_signal_connect (display, "closed",
1994 G_CALLBACK (settings_display_closed), NULL);
1995
1996 settings_init_style (settings);
1997 settings_update_xsettings (settings);
1998 settings_update_modules (settings);
1999 settings_update_double_click (settings);
2000 settings_update_cursor_theme (settings);
2001 settings_update_resolution (settings);
2002 settings_update_font_options (settings);
2003 settings_update_font_values (settings);
2004
2005 return settings;
2006 }
2007
2008 static GtkSettings *
gtk_settings_get_for_display(GdkDisplay * display)2009 gtk_settings_get_for_display (GdkDisplay *display)
2010 {
2011 DisplaySettings *ds;
2012 int i;
2013
2014 /* If the display is closed, we don't want to recreate the settings! */
2015 if G_UNLIKELY (gdk_display_is_closed (display))
2016 return NULL;
2017
2018 if G_UNLIKELY (display_settings == NULL)
2019 display_settings = g_array_new (FALSE, TRUE, sizeof (DisplaySettings));
2020
2021 ds = (DisplaySettings *)display_settings->data;
2022 for (i = 0; i < display_settings->len; i++)
2023 {
2024 if (ds[i].display == display)
2025 return ds[i].settings;
2026 }
2027
2028 return gtk_settings_create_for_display (display);
2029 }
2030
2031 /**
2032 * gtk_settings_get_for_screen:
2033 * @screen: a #GdkScreen.
2034 *
2035 * Gets the #GtkSettings object for @screen, creating it if necessary.
2036 *
2037 * Returns: (transfer none): a #GtkSettings object.
2038 *
2039 * Since: 2.2
2040 */
2041 GtkSettings *
gtk_settings_get_for_screen(GdkScreen * screen)2042 gtk_settings_get_for_screen (GdkScreen *screen)
2043 {
2044 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2045
2046 return gtk_settings_get_for_display (gdk_screen_get_display (screen));
2047 }
2048
2049 /**
2050 * gtk_settings_get_default:
2051 *
2052 * Gets the #GtkSettings object for the default GDK screen, creating
2053 * it if necessary. See gtk_settings_get_for_screen().
2054 *
2055 * Returns: (nullable) (transfer none): a #GtkSettings object. If there is
2056 * no default screen, then returns %NULL.
2057 **/
2058 GtkSettings*
gtk_settings_get_default(void)2059 gtk_settings_get_default (void)
2060 {
2061 GdkDisplay *display = gdk_display_get_default ();
2062
2063 if (display)
2064 return gtk_settings_get_for_display (display);
2065 else
2066 return NULL;
2067 }
2068
2069 static void
gtk_settings_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)2070 gtk_settings_set_property (GObject *object,
2071 guint property_id,
2072 const GValue *value,
2073 GParamSpec *pspec)
2074 {
2075 GtkSettings *settings = GTK_SETTINGS (object);
2076 GtkSettingsPrivate *priv = settings->priv;
2077
2078 g_value_copy (value, &priv->property_values[property_id - 1].value);
2079 priv->property_values[property_id - 1].source = GTK_SETTINGS_SOURCE_APPLICATION;
2080 }
2081
2082 static void
settings_invalidate_style(GtkSettings * settings)2083 settings_invalidate_style (GtkSettings *settings)
2084 {
2085 _gtk_style_provider_private_changed (GTK_STYLE_PROVIDER_PRIVATE (settings));
2086 }
2087
2088 static void
settings_update_font_values(GtkSettings * settings)2089 settings_update_font_values (GtkSettings *settings)
2090 {
2091 GtkSettingsPrivate *priv = settings->priv;
2092 PangoFontDescription *desc;
2093 const gchar *font_name;
2094
2095 font_name = g_value_get_string (&priv->property_values[PROP_FONT_NAME - 1].value);
2096 desc = pango_font_description_from_string (font_name);
2097
2098 if (desc != NULL &&
2099 (pango_font_description_get_set_fields (desc) & PANGO_FONT_MASK_SIZE) != 0)
2100 {
2101 priv->font_size = pango_font_description_get_size (desc);
2102 priv->font_size_absolute = pango_font_description_get_size_is_absolute (desc);
2103 }
2104 else
2105 {
2106 priv->font_size = 10 * PANGO_SCALE;
2107 priv->font_size_absolute = FALSE;
2108 }
2109
2110 g_free (priv->font_family);
2111
2112 if (desc != NULL &&
2113 (pango_font_description_get_set_fields (desc) & PANGO_FONT_MASK_FAMILY) != 0)
2114 {
2115 priv->font_family = g_strdup (pango_font_description_get_family (desc));
2116 }
2117 else
2118 {
2119 priv->font_family = g_strdup ("Sans");
2120 }
2121
2122 if (desc)
2123 pango_font_description_free (desc);
2124 }
2125
2126 static void
gtk_settings_notify(GObject * object,GParamSpec * pspec)2127 gtk_settings_notify (GObject *object,
2128 GParamSpec *pspec)
2129 {
2130 GtkSettings *settings = GTK_SETTINGS (object);
2131 GtkSettingsPrivate *priv = settings->priv;
2132 guint property_id = pspec->param_id;
2133
2134 if (priv->screen == NULL) /* initialization */
2135 return;
2136
2137 switch (property_id)
2138 {
2139 case PROP_MODULES:
2140 settings_update_modules (settings);
2141 break;
2142 case PROP_DOUBLE_CLICK_TIME:
2143 case PROP_DOUBLE_CLICK_DISTANCE:
2144 settings_update_double_click (settings);
2145 break;
2146 case PROP_FONT_NAME:
2147 settings_update_font_values (settings);
2148 settings_invalidate_style (settings);
2149 gtk_style_context_reset_widgets (priv->screen);
2150 break;
2151 case PROP_KEY_THEME_NAME:
2152 settings_update_key_theme (settings);
2153 break;
2154 case PROP_THEME_NAME:
2155 case PROP_APPLICATION_PREFER_DARK_THEME:
2156 settings_update_theme (settings);
2157 break;
2158 case PROP_XFT_DPI:
2159 settings_update_resolution (settings);
2160 /* This is a hack because with gtk_rc_reset_styles() doesn't get
2161 * widgets with gtk_widget_style_set(), and also causes more
2162 * recomputation than necessary.
2163 */
2164 gtk_style_context_reset_widgets (priv->screen);
2165 break;
2166 case PROP_XFT_ANTIALIAS:
2167 case PROP_XFT_HINTING:
2168 case PROP_XFT_HINTSTYLE:
2169 case PROP_XFT_RGBA:
2170 settings_update_font_options (settings);
2171 gtk_style_context_reset_widgets (priv->screen);
2172 break;
2173 case PROP_FONTCONFIG_TIMESTAMP:
2174 if (settings_update_fontconfig (settings))
2175 gtk_style_context_reset_widgets (priv->screen);
2176 break;
2177 case PROP_ENABLE_ANIMATIONS:
2178 gtk_style_context_reset_widgets (priv->screen);
2179 break;
2180 case PROP_CURSOR_THEME_NAME:
2181 case PROP_CURSOR_THEME_SIZE:
2182 settings_update_cursor_theme (settings);
2183 break;
2184 }
2185 }
2186
2187 gboolean
_gtk_settings_parse_convert(GtkRcPropertyParser parser,const GValue * src_value,GParamSpec * pspec,GValue * dest_value)2188 _gtk_settings_parse_convert (GtkRcPropertyParser parser,
2189 const GValue *src_value,
2190 GParamSpec *pspec,
2191 GValue *dest_value)
2192 {
2193 gboolean success = FALSE;
2194
2195 g_return_val_if_fail (G_VALUE_HOLDS (dest_value, G_PARAM_SPEC_VALUE_TYPE (pspec)), FALSE);
2196
2197 if (parser)
2198 {
2199 GString *gstring;
2200 gboolean free_gstring = TRUE;
2201
2202 if (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING))
2203 {
2204 gstring = g_value_get_boxed (src_value);
2205 free_gstring = FALSE;
2206 }
2207 else if (G_VALUE_HOLDS_LONG (src_value))
2208 {
2209 gstring = g_string_new (NULL);
2210 g_string_append_printf (gstring, "%ld", g_value_get_long (src_value));
2211 }
2212 else if (G_VALUE_HOLDS_DOUBLE (src_value))
2213 {
2214 gstring = g_string_new (NULL);
2215 g_string_append_printf (gstring, "%f", g_value_get_double (src_value));
2216 }
2217 else if (G_VALUE_HOLDS_STRING (src_value))
2218 {
2219 gchar *tstr = g_strescape (g_value_get_string (src_value), NULL);
2220
2221 gstring = g_string_new (NULL);
2222 g_string_append_c (gstring, '\"');
2223 g_string_append (gstring, tstr);
2224 g_string_append_c (gstring, '\"');
2225 g_free (tstr);
2226 }
2227 else
2228 {
2229 g_return_val_if_fail (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING), FALSE);
2230 gstring = NULL; /* silence compiler */
2231 }
2232
2233 success = (parser (pspec, gstring, dest_value) &&
2234 !g_param_value_validate (pspec, dest_value));
2235
2236 if (free_gstring)
2237 g_string_free (gstring, TRUE);
2238 }
2239 else if (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING))
2240 {
2241 if (G_VALUE_HOLDS (dest_value, G_TYPE_STRING))
2242 {
2243 GString *gstring = g_value_get_boxed (src_value);
2244
2245 g_value_set_string (dest_value, gstring ? gstring->str : NULL);
2246 success = !g_param_value_validate (pspec, dest_value);
2247 }
2248 }
2249 else if (g_value_type_transformable (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)))
2250 success = g_param_value_convert (pspec, src_value, dest_value, TRUE);
2251
2252 return success;
2253 }
2254
2255 static void
apply_queued_setting(GtkSettings * settings,GParamSpec * pspec,GtkSettingsValuePrivate * qvalue)2256 apply_queued_setting (GtkSettings *settings,
2257 GParamSpec *pspec,
2258 GtkSettingsValuePrivate *qvalue)
2259 {
2260 GtkSettingsPrivate *priv = settings->priv;
2261 GValue tmp_value = G_VALUE_INIT;
2262 GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
2263
2264 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
2265 if (_gtk_settings_parse_convert (parser, &qvalue->public.value,
2266 pspec, &tmp_value))
2267 {
2268 if (priv->property_values[pspec->param_id - 1].source <= qvalue->source)
2269 {
2270 g_value_copy (&tmp_value, &priv->property_values[pspec->param_id - 1].value);
2271 priv->property_values[pspec->param_id - 1].source = qvalue->source;
2272 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
2273 }
2274
2275 }
2276 else
2277 {
2278 gchar *debug = g_strdup_value_contents (&qvalue->public.value);
2279
2280 g_message ("%s: failed to retrieve property '%s' of type '%s' from rc file value \"%s\" of type '%s'",
2281 qvalue->public.origin ? qvalue->public.origin : "(for origin information, set GTK_DEBUG)",
2282 pspec->name,
2283 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
2284 debug,
2285 G_VALUE_TYPE_NAME (&tmp_value));
2286 g_free (debug);
2287 }
2288 g_value_unset (&tmp_value);
2289 }
2290
2291 static guint
settings_install_property_parser(GtkSettingsClass * class,GParamSpec * pspec,GtkRcPropertyParser parser)2292 settings_install_property_parser (GtkSettingsClass *class,
2293 GParamSpec *pspec,
2294 GtkRcPropertyParser parser)
2295 {
2296 GSList *node, *next;
2297
2298 switch (G_TYPE_FUNDAMENTAL (G_PARAM_SPEC_VALUE_TYPE (pspec)))
2299 {
2300 case G_TYPE_BOOLEAN:
2301 case G_TYPE_UCHAR:
2302 case G_TYPE_CHAR:
2303 case G_TYPE_UINT:
2304 case G_TYPE_INT:
2305 case G_TYPE_ULONG:
2306 case G_TYPE_LONG:
2307 case G_TYPE_FLOAT:
2308 case G_TYPE_DOUBLE:
2309 case G_TYPE_STRING:
2310 case G_TYPE_ENUM:
2311 break;
2312 case G_TYPE_BOXED:
2313 if (strcmp (g_param_spec_get_name (pspec), "color-hash") == 0)
2314 {
2315 break;
2316 }
2317 /* fall through */
2318 default:
2319 if (!parser)
2320 {
2321 g_warning (G_STRLOC ": parser needs to be specified for property \"%s\" of type '%s'",
2322 pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
2323 return 0;
2324 }
2325 }
2326 if (g_object_class_find_property (G_OBJECT_CLASS (class), pspec->name))
2327 {
2328 g_warning (G_STRLOC ": an rc-data property \"%s\" already exists",
2329 pspec->name);
2330 return 0;
2331 }
2332
2333 for (node = object_list; node; node = node->next)
2334 g_object_freeze_notify (node->data);
2335
2336 g_object_class_install_property (G_OBJECT_CLASS (class), ++class_n_properties, pspec);
2337 g_param_spec_set_qdata (pspec, quark_property_parser, (gpointer) parser);
2338
2339 for (node = object_list; node; node = node->next)
2340 {
2341 GtkSettings *settings = node->data;
2342 GtkSettingsPrivate *priv = settings->priv;
2343 GtkSettingsValuePrivate *qvalue;
2344
2345 priv->property_values = g_renew (GtkSettingsPropertyValue, priv->property_values, class_n_properties);
2346 priv->property_values[class_n_properties - 1].value.g_type = 0;
2347 g_value_init (&priv->property_values[class_n_properties - 1].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
2348 g_param_value_set_default (pspec, &priv->property_values[class_n_properties - 1].value);
2349 priv->property_values[class_n_properties - 1].source = GTK_SETTINGS_SOURCE_DEFAULT;
2350 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
2351
2352 qvalue = g_datalist_id_dup_data (&priv->queued_settings, g_param_spec_get_name_quark (pspec), NULL, NULL);
2353 if (qvalue)
2354 apply_queued_setting (settings, pspec, qvalue);
2355 }
2356
2357 for (node = object_list; node; node = next)
2358 {
2359 next = node->next;
2360 g_object_thaw_notify (node->data);
2361 }
2362
2363 return class_n_properties;
2364 }
2365
2366 GtkRcPropertyParser
_gtk_rc_property_parser_from_type(GType type)2367 _gtk_rc_property_parser_from_type (GType type)
2368 {
2369 if (type == g_type_from_name ("GdkColor"))
2370 return gtk_rc_property_parse_color;
2371 else if (type == GTK_TYPE_REQUISITION)
2372 return gtk_rc_property_parse_requisition;
2373 else if (type == GTK_TYPE_BORDER)
2374 return gtk_rc_property_parse_border;
2375 else if (G_TYPE_FUNDAMENTAL (type) == G_TYPE_ENUM && G_TYPE_IS_DERIVED (type))
2376 return gtk_rc_property_parse_enum;
2377 else if (G_TYPE_FUNDAMENTAL (type) == G_TYPE_FLAGS && G_TYPE_IS_DERIVED (type))
2378 return gtk_rc_property_parse_flags;
2379 else
2380 return NULL;
2381 }
2382
2383 /**
2384 * gtk_settings_install_property:
2385 * @pspec:
2386 *
2387 * Deprecated: 3.16: This function is not useful outside GTK+.
2388 */
2389 void
gtk_settings_install_property(GParamSpec * pspec)2390 gtk_settings_install_property (GParamSpec *pspec)
2391 {
2392 static GtkSettingsClass *klass = NULL;
2393
2394 GtkRcPropertyParser parser;
2395
2396 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
2397
2398 if (! klass)
2399 klass = g_type_class_ref (GTK_TYPE_SETTINGS);
2400
2401 parser = _gtk_rc_property_parser_from_type (G_PARAM_SPEC_VALUE_TYPE (pspec));
2402
2403 settings_install_property_parser (klass, pspec, parser);
2404 }
2405
2406 /**
2407 * gtk_settings_install_property_parser:
2408 * @pspec:
2409 * @parser: (scope call):
2410 *
2411 * Deprecated: 3.16: This function is not useful outside GTK+.
2412 */
2413 void
gtk_settings_install_property_parser(GParamSpec * pspec,GtkRcPropertyParser parser)2414 gtk_settings_install_property_parser (GParamSpec *pspec,
2415 GtkRcPropertyParser parser)
2416 {
2417 static GtkSettingsClass *klass = NULL;
2418
2419 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
2420 g_return_if_fail (parser != NULL);
2421
2422 if (! klass)
2423 klass = g_type_class_ref (GTK_TYPE_SETTINGS);
2424
2425 settings_install_property_parser (klass, pspec, parser);
2426 }
2427
2428 static void
free_value(gpointer data)2429 free_value (gpointer data)
2430 {
2431 GtkSettingsValuePrivate *qvalue = data;
2432
2433 g_value_unset (&qvalue->public.value);
2434 g_free (qvalue->public.origin);
2435 g_slice_free (GtkSettingsValuePrivate, qvalue);
2436 }
2437
2438 static void
gtk_settings_set_property_value_internal(GtkSettings * settings,const gchar * prop_name,const GtkSettingsValue * new_value,GtkSettingsSource source)2439 gtk_settings_set_property_value_internal (GtkSettings *settings,
2440 const gchar *prop_name,
2441 const GtkSettingsValue *new_value,
2442 GtkSettingsSource source)
2443 {
2444 GtkSettingsPrivate *priv = settings->priv;
2445 GtkSettingsValuePrivate *qvalue;
2446 GParamSpec *pspec;
2447 gchar *name;
2448 GQuark name_quark;
2449
2450 if (!G_VALUE_HOLDS_LONG (&new_value->value) &&
2451 !G_VALUE_HOLDS_FLOAT (&new_value->value) &&
2452 !G_VALUE_HOLDS_DOUBLE (&new_value->value) &&
2453 !G_VALUE_HOLDS_STRING (&new_value->value) &&
2454 !G_VALUE_HOLDS (&new_value->value, G_TYPE_GSTRING))
2455 {
2456 g_warning (G_STRLOC ": value type invalid (%s)", g_type_name (G_VALUE_TYPE (&new_value->value)));
2457 return;
2458 }
2459
2460 name = g_strdup (prop_name);
2461 g_strcanon (name, G_CSET_DIGITS "-" G_CSET_a_2_z G_CSET_A_2_Z, '-');
2462 name_quark = g_quark_from_string (name);
2463 g_free (name);
2464
2465 qvalue = g_datalist_id_dup_data (&priv->queued_settings, name_quark, NULL, NULL);
2466 if (!qvalue)
2467 {
2468 qvalue = g_slice_new0 (GtkSettingsValuePrivate);
2469 g_datalist_id_set_data_full (&priv->queued_settings, name_quark, qvalue, free_value);
2470 }
2471 else
2472 {
2473 g_free (qvalue->public.origin);
2474 g_value_unset (&qvalue->public.value);
2475 }
2476 qvalue->public.origin = g_strdup (new_value->origin);
2477 g_value_init (&qvalue->public.value, G_VALUE_TYPE (&new_value->value));
2478 g_value_copy (&new_value->value, &qvalue->public.value);
2479 qvalue->source = source;
2480 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), g_quark_to_string (name_quark));
2481 if (pspec)
2482 apply_queued_setting (settings, pspec, qvalue);
2483 }
2484
2485 /**
2486 * gtk_settings_set_property_value:
2487 * @settings:
2488 * @name:
2489 * @svalue:
2490 *
2491 * Deprecated: 3.16: Use g_object_set() instead.
2492 */
2493 void
gtk_settings_set_property_value(GtkSettings * settings,const gchar * name,const GtkSettingsValue * svalue)2494 gtk_settings_set_property_value (GtkSettings *settings,
2495 const gchar *name,
2496 const GtkSettingsValue *svalue)
2497 {
2498 g_return_if_fail (GTK_SETTINGS (settings));
2499 g_return_if_fail (name != NULL);
2500 g_return_if_fail (svalue != NULL);
2501
2502 gtk_settings_set_property_value_internal (settings, name, svalue,
2503 GTK_SETTINGS_SOURCE_APPLICATION);
2504 }
2505
2506 void
_gtk_settings_set_property_value_from_rc(GtkSettings * settings,const gchar * prop_name,const GtkSettingsValue * new_value)2507 _gtk_settings_set_property_value_from_rc (GtkSettings *settings,
2508 const gchar *prop_name,
2509 const GtkSettingsValue *new_value)
2510 {
2511 g_return_if_fail (GTK_SETTINGS (settings));
2512 g_return_if_fail (prop_name != NULL);
2513 g_return_if_fail (new_value != NULL);
2514
2515 gtk_settings_set_property_value_internal (settings, prop_name, new_value,
2516 GTK_SETTINGS_SOURCE_THEME);
2517 }
2518
2519 /**
2520 * gtk_settings_set_string_property:
2521 * @settings:
2522 * @name:
2523 * @v_string:
2524 * @origin:
2525 *
2526 * Deprecated: 3.16: Use g_object_set() instead.
2527 */
2528 void
gtk_settings_set_string_property(GtkSettings * settings,const gchar * name,const gchar * v_string,const gchar * origin)2529 gtk_settings_set_string_property (GtkSettings *settings,
2530 const gchar *name,
2531 const gchar *v_string,
2532 const gchar *origin)
2533 {
2534 GtkSettingsValue svalue = { NULL, { 0, }, };
2535
2536 g_return_if_fail (GTK_SETTINGS (settings));
2537 g_return_if_fail (name != NULL);
2538 g_return_if_fail (v_string != NULL);
2539
2540 svalue.origin = (gchar*) origin;
2541 g_value_init (&svalue.value, G_TYPE_STRING);
2542 g_value_set_static_string (&svalue.value, v_string);
2543 gtk_settings_set_property_value_internal (settings, name, &svalue,
2544 GTK_SETTINGS_SOURCE_APPLICATION);
2545 g_value_unset (&svalue.value);
2546 }
2547
2548 /**
2549 * gtk_settings_set_long_property:
2550 * @settings:
2551 * @name:
2552 * @v_long:
2553 * @origin:
2554 *
2555 * Deprecated: 3.16: Use g_object_set() instead.
2556 */
2557 void
gtk_settings_set_long_property(GtkSettings * settings,const gchar * name,glong v_long,const gchar * origin)2558 gtk_settings_set_long_property (GtkSettings *settings,
2559 const gchar *name,
2560 glong v_long,
2561 const gchar *origin)
2562 {
2563 GtkSettingsValue svalue = { NULL, { 0, }, };
2564
2565 g_return_if_fail (GTK_SETTINGS (settings));
2566 g_return_if_fail (name != NULL);
2567
2568 svalue.origin = (gchar*) origin;
2569 g_value_init (&svalue.value, G_TYPE_LONG);
2570 g_value_set_long (&svalue.value, v_long);
2571 gtk_settings_set_property_value_internal (settings, name, &svalue,
2572 GTK_SETTINGS_SOURCE_APPLICATION);
2573 g_value_unset (&svalue.value);
2574 }
2575
2576 /**
2577 * gtk_settings_set_double_property:
2578 * @settings:
2579 * @name:
2580 * @v_double:
2581 * @origin:
2582 *
2583 * Deprecated: 3.16: Use g_object_set() instead.
2584 */
2585 void
gtk_settings_set_double_property(GtkSettings * settings,const gchar * name,gdouble v_double,const gchar * origin)2586 gtk_settings_set_double_property (GtkSettings *settings,
2587 const gchar *name,
2588 gdouble v_double,
2589 const gchar *origin)
2590 {
2591 GtkSettingsValue svalue = { NULL, { 0, }, };
2592
2593 g_return_if_fail (GTK_SETTINGS (settings));
2594 g_return_if_fail (name != NULL);
2595
2596 svalue.origin = (gchar*) origin;
2597 g_value_init (&svalue.value, G_TYPE_DOUBLE);
2598 g_value_set_double (&svalue.value, v_double);
2599 gtk_settings_set_property_value_internal (settings, name, &svalue,
2600 GTK_SETTINGS_SOURCE_APPLICATION);
2601 g_value_unset (&svalue.value);
2602 }
2603
2604 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2605
2606 /**
2607 * gtk_rc_property_parse_color:
2608 * @pspec: a #GParamSpec
2609 * @gstring: the #GString to be parsed
2610 * @property_value: a #GValue which must hold #GdkColor values.
2611 *
2612 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2613 * or gtk_widget_class_install_style_property_parser() which parses a
2614 * color given either by its name or in the form
2615 * `{ red, green, blue }` where red, green and
2616 * blue are integers between 0 and 65535 or floating-point numbers
2617 * between 0 and 1.
2618 *
2619 * Returns: %TRUE if @gstring could be parsed and @property_value
2620 * has been set to the resulting #GdkColor.
2621 **/
2622 gboolean
gtk_rc_property_parse_color(const GParamSpec * pspec,const GString * gstring,GValue * property_value)2623 gtk_rc_property_parse_color (const GParamSpec *pspec,
2624 const GString *gstring,
2625 GValue *property_value)
2626 {
2627 GdkColor color = { 0, 0, 0, 0, };
2628 GScanner *scanner;
2629 gboolean success;
2630
2631 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2632 g_return_val_if_fail (G_VALUE_HOLDS (property_value, GDK_TYPE_COLOR), FALSE);
2633
2634 scanner = gtk_rc_scanner_new ();
2635 g_scanner_input_text (scanner, gstring->str, gstring->len);
2636 if (gtk_rc_parse_color (scanner, &color) == G_TOKEN_NONE &&
2637 g_scanner_get_next_token (scanner) == G_TOKEN_EOF)
2638 {
2639 g_value_set_boxed (property_value, &color);
2640 success = TRUE;
2641 }
2642 else
2643 success = FALSE;
2644 g_scanner_destroy (scanner);
2645
2646 return success;
2647 }
2648
2649 /**
2650 * gtk_rc_property_parse_enum:
2651 * @pspec: a #GParamSpec
2652 * @gstring: the #GString to be parsed
2653 * @property_value: a #GValue which must hold enum values.
2654 *
2655 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2656 * or gtk_widget_class_install_style_property_parser() which parses a single
2657 * enumeration value.
2658 *
2659 * The enumeration value can be specified by its name, its nickname or
2660 * its numeric value. For consistency with flags parsing, the value
2661 * may be surrounded by parentheses.
2662 *
2663 * Returns: %TRUE if @gstring could be parsed and @property_value
2664 * has been set to the resulting #GEnumValue.
2665 **/
2666 gboolean
gtk_rc_property_parse_enum(const GParamSpec * pspec,const GString * gstring,GValue * property_value)2667 gtk_rc_property_parse_enum (const GParamSpec *pspec,
2668 const GString *gstring,
2669 GValue *property_value)
2670 {
2671 gboolean need_closing_brace = FALSE, success = FALSE;
2672 GScanner *scanner;
2673 GEnumValue *enum_value = NULL;
2674
2675 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2676 g_return_val_if_fail (G_VALUE_HOLDS_ENUM (property_value), FALSE);
2677
2678 scanner = gtk_rc_scanner_new ();
2679 g_scanner_input_text (scanner, gstring->str, gstring->len);
2680
2681 /* we just want to parse _one_ value, but for consistency with flags parsing
2682 * we support optional parenthesis
2683 */
2684 g_scanner_get_next_token (scanner);
2685 if (scanner->token == '(')
2686 {
2687 need_closing_brace = TRUE;
2688 g_scanner_get_next_token (scanner);
2689 }
2690 if (scanner->token == G_TOKEN_IDENTIFIER)
2691 {
2692 GEnumClass *class = G_PARAM_SPEC_ENUM (pspec)->enum_class;
2693
2694 enum_value = g_enum_get_value_by_name (class, scanner->value.v_identifier);
2695 if (!enum_value)
2696 enum_value = g_enum_get_value_by_nick (class, scanner->value.v_identifier);
2697 if (enum_value)
2698 {
2699 g_value_set_enum (property_value, enum_value->value);
2700 success = TRUE;
2701 }
2702 }
2703 else if (scanner->token == G_TOKEN_INT)
2704 {
2705 g_value_set_enum (property_value, scanner->value.v_int);
2706 success = TRUE;
2707 }
2708 if (need_closing_brace && g_scanner_get_next_token (scanner) != ')')
2709 success = FALSE;
2710 if (g_scanner_get_next_token (scanner) != G_TOKEN_EOF)
2711 success = FALSE;
2712
2713 g_scanner_destroy (scanner);
2714
2715 return success;
2716 }
2717
2718 static guint
parse_flags_value(GScanner * scanner,GFlagsClass * class,guint * number)2719 parse_flags_value (GScanner *scanner,
2720 GFlagsClass *class,
2721 guint *number)
2722 {
2723 g_scanner_get_next_token (scanner);
2724 if (scanner->token == G_TOKEN_IDENTIFIER)
2725 {
2726 GFlagsValue *flags_value;
2727
2728 flags_value = g_flags_get_value_by_name (class, scanner->value.v_identifier);
2729 if (!flags_value)
2730 flags_value = g_flags_get_value_by_nick (class, scanner->value.v_identifier);
2731 if (flags_value)
2732 {
2733 *number |= flags_value->value;
2734 return G_TOKEN_NONE;
2735 }
2736 }
2737 else if (scanner->token == G_TOKEN_INT)
2738 {
2739 *number |= scanner->value.v_int;
2740 return G_TOKEN_NONE;
2741 }
2742 return G_TOKEN_IDENTIFIER;
2743 }
2744
2745 /**
2746 * gtk_rc_property_parse_flags:
2747 * @pspec: a #GParamSpec
2748 * @gstring: the #GString to be parsed
2749 * @property_value: a #GValue which must hold flags values.
2750 *
2751 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2752 * or gtk_widget_class_install_style_property_parser() which parses flags.
2753 *
2754 * Flags can be specified by their name, their nickname or
2755 * numerically. Multiple flags can be specified in the form
2756 * `"( flag1 | flag2 | ... )"`.
2757 *
2758 * Returns: %TRUE if @gstring could be parsed and @property_value
2759 * has been set to the resulting flags value.
2760 **/
2761 gboolean
gtk_rc_property_parse_flags(const GParamSpec * pspec,const GString * gstring,GValue * property_value)2762 gtk_rc_property_parse_flags (const GParamSpec *pspec,
2763 const GString *gstring,
2764 GValue *property_value)
2765 {
2766 GFlagsClass *class;
2767 gboolean success = FALSE;
2768 GScanner *scanner;
2769
2770 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2771 g_return_val_if_fail (G_VALUE_HOLDS_FLAGS (property_value), FALSE);
2772
2773 class = G_PARAM_SPEC_FLAGS (pspec)->flags_class;
2774 scanner = gtk_rc_scanner_new ();
2775 g_scanner_input_text (scanner, gstring->str, gstring->len);
2776
2777 /* parse either a single flags value or a "\( ... [ \| ... ] \)" compound */
2778 if (g_scanner_peek_next_token (scanner) == G_TOKEN_IDENTIFIER ||
2779 scanner->next_token == G_TOKEN_INT)
2780 {
2781 guint token, flags_value = 0;
2782
2783 token = parse_flags_value (scanner, class, &flags_value);
2784
2785 if (token == G_TOKEN_NONE && g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
2786 {
2787 success = TRUE;
2788 g_value_set_flags (property_value, flags_value);
2789 }
2790
2791 }
2792 else if (g_scanner_get_next_token (scanner) == '(')
2793 {
2794 guint token, flags_value = 0;
2795
2796 /* parse first value */
2797 token = parse_flags_value (scanner, class, &flags_value);
2798
2799 /* parse nth values, preceeded by '|' */
2800 while (token == G_TOKEN_NONE && g_scanner_get_next_token (scanner) == '|')
2801 token = parse_flags_value (scanner, class, &flags_value);
2802
2803 /* done, last token must have closed expression */
2804 if (token == G_TOKEN_NONE && scanner->token == ')' &&
2805 g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
2806 {
2807 g_value_set_flags (property_value, flags_value);
2808 success = TRUE;
2809 }
2810 }
2811 g_scanner_destroy (scanner);
2812
2813 return success;
2814 }
2815
2816 static gboolean
get_braced_int(GScanner * scanner,gboolean first,gboolean last,gint * value)2817 get_braced_int (GScanner *scanner,
2818 gboolean first,
2819 gboolean last,
2820 gint *value)
2821 {
2822 if (first)
2823 {
2824 g_scanner_get_next_token (scanner);
2825 if (scanner->token != '{')
2826 return FALSE;
2827 }
2828
2829 g_scanner_get_next_token (scanner);
2830 if (scanner->token != G_TOKEN_INT)
2831 return FALSE;
2832
2833 *value = scanner->value.v_int;
2834
2835 if (last)
2836 {
2837 g_scanner_get_next_token (scanner);
2838 if (scanner->token != '}')
2839 return FALSE;
2840 }
2841 else
2842 {
2843 g_scanner_get_next_token (scanner);
2844 if (scanner->token != ',')
2845 return FALSE;
2846 }
2847
2848 return TRUE;
2849 }
2850
2851 /**
2852 * gtk_rc_property_parse_requisition:
2853 * @pspec: a #GParamSpec
2854 * @gstring: the #GString to be parsed
2855 * @property_value: a #GValue which must hold boxed values.
2856 *
2857 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2858 * or gtk_widget_class_install_style_property_parser() which parses a
2859 * requisition in the form
2860 * `"{ width, height }"` for integers %width and %height.
2861 *
2862 * Returns: %TRUE if @gstring could be parsed and @property_value
2863 * has been set to the resulting #GtkRequisition.
2864 **/
2865 gboolean
gtk_rc_property_parse_requisition(const GParamSpec * pspec,const GString * gstring,GValue * property_value)2866 gtk_rc_property_parse_requisition (const GParamSpec *pspec,
2867 const GString *gstring,
2868 GValue *property_value)
2869 {
2870 GtkRequisition requisition;
2871 GScanner *scanner;
2872 gboolean success = FALSE;
2873
2874 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2875 g_return_val_if_fail (G_VALUE_HOLDS_BOXED (property_value), FALSE);
2876
2877 scanner = gtk_rc_scanner_new ();
2878 g_scanner_input_text (scanner, gstring->str, gstring->len);
2879
2880 if (get_braced_int (scanner, TRUE, FALSE, &requisition.width) &&
2881 get_braced_int (scanner, FALSE, TRUE, &requisition.height))
2882 {
2883 g_value_set_boxed (property_value, &requisition);
2884 success = TRUE;
2885 }
2886
2887 g_scanner_destroy (scanner);
2888
2889 return success;
2890 }
2891
2892 /**
2893 * gtk_rc_property_parse_border:
2894 * @pspec: a #GParamSpec
2895 * @gstring: the #GString to be parsed
2896 * @property_value: a #GValue which must hold boxed values.
2897 *
2898 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2899 * or gtk_widget_class_install_style_property_parser() which parses
2900 * borders in the form
2901 * `"{ left, right, top, bottom }"` for integers
2902 * left, right, top and bottom.
2903 *
2904 * Returns: %TRUE if @gstring could be parsed and @property_value
2905 * has been set to the resulting #GtkBorder.
2906 **/
2907 gboolean
gtk_rc_property_parse_border(const GParamSpec * pspec,const GString * gstring,GValue * property_value)2908 gtk_rc_property_parse_border (const GParamSpec *pspec,
2909 const GString *gstring,
2910 GValue *property_value)
2911 {
2912 GtkBorder border;
2913 GScanner *scanner;
2914 gboolean success = FALSE;
2915 int left, right, top, bottom;
2916
2917 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2918 g_return_val_if_fail (G_VALUE_HOLDS_BOXED (property_value), FALSE);
2919
2920 scanner = gtk_rc_scanner_new ();
2921 g_scanner_input_text (scanner, gstring->str, gstring->len);
2922
2923 if (get_braced_int (scanner, TRUE, FALSE, &left) &&
2924 get_braced_int (scanner, FALSE, FALSE, &right) &&
2925 get_braced_int (scanner, FALSE, FALSE, &top) &&
2926 get_braced_int (scanner, FALSE, TRUE, &bottom))
2927 {
2928 border.left = left;
2929 border.right = right;
2930 border.top = top;
2931 border.bottom = bottom;
2932 g_value_set_boxed (property_value, &border);
2933 success = TRUE;
2934 }
2935
2936 g_scanner_destroy (scanner);
2937
2938 return success;
2939 }
2940
2941 G_GNUC_END_IGNORE_DEPRECATIONS
2942
2943 void
_gtk_settings_handle_event(GdkEventSetting * event)2944 _gtk_settings_handle_event (GdkEventSetting *event)
2945 {
2946 GdkScreen *screen;
2947 GtkSettings *settings;
2948 GParamSpec *pspec;
2949
2950 screen = gdk_window_get_screen (event->window);
2951 settings = gtk_settings_get_for_screen (screen);
2952 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), event->name);
2953
2954 if (!pspec)
2955 return;
2956
2957 if (settings_update_xsetting (settings, pspec, TRUE))
2958 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
2959 }
2960
2961 static void
reset_rc_values_foreach(GQuark key_id,gpointer data,gpointer user_data)2962 reset_rc_values_foreach (GQuark key_id,
2963 gpointer data,
2964 gpointer user_data)
2965 {
2966 GtkSettingsValuePrivate *qvalue = data;
2967 GSList **to_reset = user_data;
2968
2969 if (qvalue->source == GTK_SETTINGS_SOURCE_THEME)
2970 *to_reset = g_slist_prepend (*to_reset, GUINT_TO_POINTER (key_id));
2971 }
2972
2973 void
_gtk_settings_reset_rc_values(GtkSettings * settings)2974 _gtk_settings_reset_rc_values (GtkSettings *settings)
2975 {
2976 GtkSettingsPrivate *priv = settings->priv;
2977 GSList *to_reset = NULL;
2978 GSList *tmp_list;
2979 GParamSpec **pspecs, **p;
2980 gint i;
2981
2982 /* Remove any queued settings */
2983 g_datalist_foreach (&priv->queued_settings,
2984 reset_rc_values_foreach,
2985 &to_reset);
2986
2987 for (tmp_list = to_reset; tmp_list; tmp_list = tmp_list->next)
2988 {
2989 GQuark key_id = GPOINTER_TO_UINT (tmp_list->data);
2990 g_datalist_id_remove_data (&priv->queued_settings, key_id);
2991 }
2992
2993 g_slist_free (to_reset);
2994
2995 /* Now reset the active settings
2996 */
2997 pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), NULL);
2998 i = 0;
2999
3000 g_object_freeze_notify (G_OBJECT (settings));
3001 for (p = pspecs; *p; p++)
3002 {
3003 if (priv->property_values[i].source == GTK_SETTINGS_SOURCE_THEME)
3004 {
3005 GParamSpec *pspec = *p;
3006
3007 g_param_value_set_default (pspec, &priv->property_values[i].value);
3008 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
3009 }
3010 i++;
3011 }
3012 g_object_thaw_notify (G_OBJECT (settings));
3013 g_free (pspecs);
3014 }
3015
3016 static void
settings_update_double_click(GtkSettings * settings)3017 settings_update_double_click (GtkSettings *settings)
3018 {
3019 GtkSettingsPrivate *priv = settings->priv;
3020 GdkDisplay *display = gdk_screen_get_display (priv->screen);
3021 gint double_click_time;
3022 gint double_click_distance;
3023
3024 g_object_get (settings,
3025 "gtk-double-click-time", &double_click_time,
3026 "gtk-double-click-distance", &double_click_distance,
3027 NULL);
3028
3029 gdk_display_set_double_click_time (display, double_click_time);
3030 gdk_display_set_double_click_distance (display, double_click_distance);
3031 }
3032
3033 static void
settings_update_modules(GtkSettings * settings)3034 settings_update_modules (GtkSettings *settings)
3035 {
3036 gchar *modules;
3037
3038 g_object_get (settings,
3039 "gtk-modules", &modules,
3040 NULL);
3041
3042 _gtk_modules_settings_changed (settings, modules);
3043
3044 g_free (modules);
3045 }
3046
3047 static void
settings_update_cursor_theme(GtkSettings * settings)3048 settings_update_cursor_theme (GtkSettings *settings)
3049 {
3050 gchar *theme = NULL;
3051 gint size = 0;
3052 #if defined(GDK_WINDOWING_X11) || defined(GDK_WINDOWING_WAYLAND) || defined(GDK_WINDOWING_WIN32)
3053 GdkDisplay *display = gdk_screen_get_display (settings->priv->screen);
3054 #endif
3055
3056 g_object_get (settings,
3057 "gtk-cursor-theme-name", &theme,
3058 "gtk-cursor-theme-size", &size,
3059 NULL);
3060 if (theme == NULL)
3061 return;
3062 #ifdef GDK_WINDOWING_X11
3063 if (GDK_IS_X11_DISPLAY (display))
3064 gdk_x11_display_set_cursor_theme (display, theme, size);
3065 else
3066 #endif
3067 #ifdef GDK_WINDOWING_WAYLAND
3068 if (GDK_IS_WAYLAND_DISPLAY (display))
3069 gdk_wayland_display_set_cursor_theme (display, theme, size);
3070 else
3071 #endif
3072 #ifdef GDK_WINDOWING_WIN32
3073 if (GDK_IS_WIN32_DISPLAY (display))
3074 gdk_win32_display_set_cursor_theme (display, theme, size);
3075 else
3076 #endif
3077 g_warning ("GtkSettings Cursor Theme: Unsupported GDK backend");
3078 g_free (theme);
3079 }
3080
3081 static void
settings_update_font_options(GtkSettings * settings)3082 settings_update_font_options (GtkSettings *settings)
3083 {
3084 GtkSettingsPrivate *priv = settings->priv;
3085 gint hinting;
3086 gchar *hint_style_str;
3087 cairo_hint_style_t hint_style;
3088 gint antialias;
3089 cairo_antialias_t antialias_mode;
3090 gchar *rgba_str;
3091 cairo_subpixel_order_t subpixel_order;
3092 cairo_font_options_t *options;
3093
3094 g_object_get (settings,
3095 "gtk-xft-antialias", &antialias,
3096 "gtk-xft-hinting", &hinting,
3097 "gtk-xft-hintstyle", &hint_style_str,
3098 "gtk-xft-rgba", &rgba_str,
3099 NULL);
3100
3101 options = cairo_font_options_create ();
3102
3103 cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
3104
3105 hint_style = CAIRO_HINT_STYLE_DEFAULT;
3106 if (hinting == 0)
3107 {
3108 hint_style = CAIRO_HINT_STYLE_NONE;
3109 }
3110 else if (hinting == 1)
3111 {
3112 if (hint_style_str)
3113 {
3114 if (strcmp (hint_style_str, "hintnone") == 0)
3115 hint_style = CAIRO_HINT_STYLE_NONE;
3116 else if (strcmp (hint_style_str, "hintslight") == 0)
3117 hint_style = CAIRO_HINT_STYLE_SLIGHT;
3118 else if (strcmp (hint_style_str, "hintmedium") == 0)
3119 hint_style = CAIRO_HINT_STYLE_MEDIUM;
3120 else if (strcmp (hint_style_str, "hintfull") == 0)
3121 hint_style = CAIRO_HINT_STYLE_FULL;
3122 }
3123 }
3124
3125 g_free (hint_style_str);
3126
3127 cairo_font_options_set_hint_style (options, hint_style);
3128
3129 subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
3130 if (rgba_str)
3131 {
3132 if (strcmp (rgba_str, "rgb") == 0)
3133 subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
3134 else if (strcmp (rgba_str, "bgr") == 0)
3135 subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
3136 else if (strcmp (rgba_str, "vrgb") == 0)
3137 subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
3138 else if (strcmp (rgba_str, "vbgr") == 0)
3139 subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
3140 }
3141
3142 g_free (rgba_str);
3143
3144 cairo_font_options_set_subpixel_order (options, subpixel_order);
3145
3146 antialias_mode = CAIRO_ANTIALIAS_DEFAULT;
3147 if (antialias == 0)
3148 {
3149 antialias_mode = CAIRO_ANTIALIAS_NONE;
3150 }
3151 else if (antialias == 1)
3152 {
3153 if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
3154 antialias_mode = CAIRO_ANTIALIAS_SUBPIXEL;
3155 else
3156 antialias_mode = CAIRO_ANTIALIAS_GRAY;
3157 }
3158
3159 cairo_font_options_set_antialias (options, antialias_mode);
3160
3161 gdk_screen_set_font_options (priv->screen, options);
3162
3163 cairo_font_options_destroy (options);
3164 }
3165
3166 static gboolean
settings_update_fontconfig(GtkSettings * settings)3167 settings_update_fontconfig (GtkSettings *settings)
3168 {
3169 #if defined(GDK_WINDOWING_X11) || defined(GDK_WINDOWING_WAYLAND)
3170 static guint last_update_timestamp;
3171 static gboolean last_update_needed;
3172
3173 guint timestamp;
3174
3175 g_object_get (settings,
3176 "gtk-fontconfig-timestamp", ×tamp,
3177 NULL);
3178
3179 /* if timestamp is the same as last_update_timestamp, we already have
3180 * updated fontconig on this timestamp (another screen requested it perhaps?),
3181 * just return the cached result.*/
3182
3183 if (timestamp != last_update_timestamp)
3184 {
3185 PangoFontMap *fontmap = pango_cairo_font_map_get_default ();
3186 gboolean update_needed = FALSE;
3187
3188 /* bug 547680 */
3189 if (PANGO_IS_FC_FONT_MAP (fontmap) && !FcConfigUptoDate (NULL))
3190 {
3191 pango_fc_font_map_config_changed (PANGO_FC_FONT_MAP (fontmap));
3192 if (FcInitReinitialize ())
3193 update_needed = TRUE;
3194 }
3195
3196 last_update_timestamp = timestamp;
3197 last_update_needed = update_needed;
3198 }
3199
3200 return last_update_needed;
3201 #else
3202 return FALSE;
3203 #endif /* GDK_WINDOWING_X11 || GDK_WINDOWING_WAYLAND */
3204 }
3205
3206 static void
settings_update_resolution(GtkSettings * settings)3207 settings_update_resolution (GtkSettings *settings)
3208 {
3209 GtkSettingsPrivate *priv = settings->priv;
3210 gint dpi_int;
3211 gdouble dpi;
3212 const char *scale_env;
3213 double scale;
3214
3215 /* We handle this here in the case that the dpi was set on the GtkSettings
3216 * object by the application. Other cases are handled in
3217 * xsettings-client.c:read-settings(). See comment there for the rationale.
3218 */
3219 if (priv->property_values[PROP_XFT_DPI - 1].source == GTK_SETTINGS_SOURCE_APPLICATION)
3220 {
3221 g_object_get (settings,
3222 "gtk-xft-dpi", &dpi_int,
3223 NULL);
3224
3225 if (dpi_int > 0)
3226 dpi = dpi_int / 1024.;
3227 else
3228 dpi = -1.;
3229
3230 scale_env = g_getenv ("GDK_DPI_SCALE");
3231 if (scale_env)
3232 {
3233 scale = g_ascii_strtod (scale_env, NULL);
3234 if (scale != 0 && dpi > 0)
3235 dpi *= scale;
3236 }
3237
3238 gdk_screen_set_resolution (priv->screen, dpi);
3239 }
3240 }
3241
3242 static void
settings_update_provider(GdkScreen * screen,GtkCssProvider ** old,GtkCssProvider * new)3243 settings_update_provider (GdkScreen *screen,
3244 GtkCssProvider **old,
3245 GtkCssProvider *new)
3246 {
3247 if (screen != NULL && *old != new)
3248 {
3249 if (*old)
3250 {
3251 gtk_style_context_remove_provider_for_screen (screen,
3252 GTK_STYLE_PROVIDER (*old));
3253 g_object_unref (*old);
3254 *old = NULL;
3255 }
3256
3257 if (new)
3258 {
3259 gtk_style_context_add_provider_for_screen (screen,
3260 GTK_STYLE_PROVIDER (new),
3261 GTK_STYLE_PROVIDER_PRIORITY_THEME);
3262 *old = g_object_ref (new);
3263 }
3264 }
3265 }
3266
3267 static void
get_theme_name(GtkSettings * settings,gchar ** theme_name,gchar ** theme_variant)3268 get_theme_name (GtkSettings *settings,
3269 gchar **theme_name,
3270 gchar **theme_variant)
3271 {
3272 gboolean prefer_dark;
3273
3274 *theme_name = NULL;
3275 *theme_variant = NULL;
3276
3277 if (g_getenv ("GTK_THEME"))
3278 *theme_name = g_strdup (g_getenv ("GTK_THEME"));
3279
3280 if (*theme_name && **theme_name)
3281 {
3282 char *p;
3283 p = strrchr (*theme_name, ':');
3284 if (p) {
3285 *p = '\0';
3286 p++;
3287 *theme_variant = g_strdup (p);
3288 }
3289
3290 return;
3291 }
3292
3293 g_free (*theme_name);
3294
3295 g_object_get (settings,
3296 "gtk-theme-name", theme_name,
3297 "gtk-application-prefer-dark-theme", &prefer_dark,
3298 NULL);
3299
3300 if (prefer_dark)
3301 *theme_variant = g_strdup ("dark");
3302
3303 if (*theme_name && **theme_name)
3304 return;
3305
3306 g_free (*theme_name);
3307 *theme_name = g_strdup (DEFAULT_THEME_NAME);
3308 }
3309
3310 static void
settings_update_theme(GtkSettings * settings)3311 settings_update_theme (GtkSettings *settings)
3312 {
3313 GtkSettingsPrivate *priv = settings->priv;
3314 gchar *theme_name;
3315 gchar *theme_variant;
3316 const gchar *theme_dir;
3317 gchar *path;
3318
3319 get_theme_name (settings, &theme_name, &theme_variant);
3320
3321 _gtk_css_provider_load_named (priv->theme_provider,
3322 theme_name, theme_variant);
3323
3324 /* reload per-theme settings */
3325 theme_dir = _gtk_css_provider_get_theme_dir (priv->theme_provider);
3326 if (theme_dir)
3327 {
3328 path = g_build_filename (theme_dir, "settings.ini", NULL);
3329 if (g_file_test (path, G_FILE_TEST_EXISTS))
3330 gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_THEME);
3331 g_free (path);
3332 }
3333
3334 g_free (theme_name);
3335 g_free (theme_variant);
3336 }
3337
3338 static void
settings_update_key_theme(GtkSettings * settings)3339 settings_update_key_theme (GtkSettings *settings)
3340 {
3341 GtkSettingsPrivate *priv = settings->priv;
3342 GtkCssProvider *provider = NULL;
3343 gchar *key_theme_name;
3344
3345 g_object_get (settings,
3346 "gtk-key-theme-name", &key_theme_name,
3347 NULL);
3348
3349 if (key_theme_name && *key_theme_name)
3350 provider = gtk_css_provider_get_named (key_theme_name, "keys");
3351
3352 settings_update_provider (priv->screen, &priv->key_theme_provider, provider);
3353 g_free (key_theme_name);
3354 }
3355
3356
3357 GdkScreen *
_gtk_settings_get_screen(GtkSettings * settings)3358 _gtk_settings_get_screen (GtkSettings *settings)
3359 {
3360 return settings->priv->screen;
3361 }
3362
3363 static void
gvalue_free(gpointer data)3364 gvalue_free (gpointer data)
3365 {
3366 g_value_unset (data);
3367 g_free (data);
3368 }
3369
3370 static void
gtk_settings_load_from_key_file(GtkSettings * settings,const gchar * path,GtkSettingsSource source)3371 gtk_settings_load_from_key_file (GtkSettings *settings,
3372 const gchar *path,
3373 GtkSettingsSource source)
3374 {
3375 GError *error;
3376 GKeyFile *keyfile;
3377 gchar **keys;
3378 gsize n_keys;
3379 gint i;
3380
3381 error = NULL;
3382 keys = NULL;
3383
3384 keyfile = g_key_file_new ();
3385
3386 if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error))
3387 {
3388 g_warning ("Failed to parse %s: %s", path, error->message);
3389
3390 g_error_free (error);
3391
3392 goto out;
3393 }
3394
3395 keys = g_key_file_get_keys (keyfile, "Settings", &n_keys, &error);
3396 if (error)
3397 {
3398 g_warning ("Failed to parse %s: %s", path, error->message);
3399 g_error_free (error);
3400 goto out;
3401 }
3402
3403 for (i = 0; i < n_keys; i++)
3404 {
3405 gchar *key;
3406 GParamSpec *pspec;
3407 GType value_type;
3408 GtkSettingsValue svalue = { NULL, { 0, }, };
3409
3410 key = keys[i];
3411 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), key);
3412 if (!pspec)
3413 {
3414 g_warning ("Unknown key %s in %s", key, path);
3415 continue;
3416 }
3417
3418 if (pspec->owner_type != G_OBJECT_TYPE (settings))
3419 continue;
3420
3421 value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
3422 switch (value_type)
3423 {
3424 case G_TYPE_BOOLEAN:
3425 {
3426 gboolean b_val;
3427
3428 g_value_init (&svalue.value, G_TYPE_LONG);
3429 b_val = g_key_file_get_boolean (keyfile, "Settings", key, &error);
3430 if (!error)
3431 g_value_set_long (&svalue.value, b_val);
3432 break;
3433 }
3434
3435 case G_TYPE_INT:
3436 case G_TYPE_UINT:
3437 {
3438 gint i_val;
3439
3440 g_value_init (&svalue.value, G_TYPE_LONG);
3441 i_val = g_key_file_get_integer (keyfile, "Settings", key, &error);
3442 if (!error)
3443 g_value_set_long (&svalue.value, i_val);
3444 break;
3445 }
3446
3447 case G_TYPE_FLOAT:
3448 case G_TYPE_DOUBLE:
3449 {
3450 gdouble d_val;
3451
3452 g_value_init (&svalue.value, value_type);
3453 d_val = g_key_file_get_double (keyfile, "Settings", key, &error);
3454 if (!error)
3455 {
3456 if (value_type == G_TYPE_FLOAT)
3457 g_value_set_float (&svalue.value, (float) d_val);
3458 else
3459 g_value_set_double (&svalue.value, d_val);
3460 }
3461 break;
3462 }
3463
3464 default:
3465 {
3466 gchar *s_val;
3467
3468 g_value_init (&svalue.value, G_TYPE_GSTRING);
3469 s_val = g_key_file_get_string (keyfile, "Settings", key, &error);
3470 if (!error)
3471 g_value_take_boxed (&svalue.value, g_string_new (s_val));
3472 g_free (s_val);
3473 break;
3474 }
3475 }
3476 if (error)
3477 {
3478 g_warning ("Error setting %s in %s: %s", key, path, error->message);
3479 g_error_free (error);
3480 error = NULL;
3481 }
3482 else
3483 {
3484 GValue *copy;
3485
3486 copy = g_new0 (GValue, 1);
3487
3488 g_value_init (copy, G_VALUE_TYPE (&svalue.value));
3489 g_value_copy (&svalue.value, copy);
3490
3491 g_param_spec_set_qdata_full (pspec, g_quark_from_string (key),
3492 copy, gvalue_free);
3493
3494 if (g_getenv ("GTK_DEBUG"))
3495 svalue.origin = (gchar *)path;
3496
3497 gtk_settings_set_property_value_internal (settings, key, &svalue, source);
3498 g_value_unset (&svalue.value);
3499 }
3500 }
3501
3502 out:
3503 g_strfreev (keys);
3504 g_key_file_free (keyfile);
3505 }
3506
3507 static gboolean
settings_update_xsetting(GtkSettings * settings,GParamSpec * pspec,gboolean force)3508 settings_update_xsetting (GtkSettings *settings,
3509 GParamSpec *pspec,
3510 gboolean force)
3511 {
3512 GtkSettingsPrivate *priv = settings->priv;
3513 GType value_type;
3514 GType fundamental_type;
3515 gboolean retval = FALSE;
3516
3517 if (priv->property_values[pspec->param_id - 1].source == GTK_SETTINGS_SOURCE_APPLICATION)
3518 return FALSE;
3519
3520 if (priv->property_values[pspec->param_id - 1].source == GTK_SETTINGS_SOURCE_XSETTING && !force)
3521 return FALSE;
3522
3523 value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
3524 fundamental_type = G_TYPE_FUNDAMENTAL (value_type);
3525
3526 if ((g_value_type_transformable (G_TYPE_INT, value_type) &&
3527 !(fundamental_type == G_TYPE_ENUM || fundamental_type == G_TYPE_FLAGS)) ||
3528 g_value_type_transformable (G_TYPE_STRING, value_type) ||
3529 g_value_type_transformable (GDK_TYPE_RGBA, value_type))
3530 {
3531 GValue val = G_VALUE_INIT;
3532
3533 g_value_init (&val, value_type);
3534
3535 if (!gdk_screen_get_setting (priv->screen, pspec->name, &val))
3536 return FALSE;
3537
3538 g_param_value_validate (pspec, &val);
3539 g_value_copy (&val, &priv->property_values[pspec->param_id - 1].value);
3540 priv->property_values[pspec->param_id - 1].source = GTK_SETTINGS_SOURCE_XSETTING;
3541
3542 g_value_unset (&val);
3543
3544 retval = TRUE;
3545 }
3546 else
3547 {
3548 GValue tmp_value = G_VALUE_INIT;
3549 GValue gstring_value = G_VALUE_INIT;
3550 GValue val = G_VALUE_INIT;
3551 GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
3552
3553 g_value_init (&val, G_TYPE_STRING);
3554
3555 if (!gdk_screen_get_setting (priv->screen, pspec->name, &val))
3556 return FALSE;
3557
3558 g_value_init (&gstring_value, G_TYPE_GSTRING);
3559 g_value_take_boxed (&gstring_value, g_string_new (g_value_get_string (&val)));
3560
3561 g_value_init (&tmp_value, value_type);
3562 if (parser && _gtk_settings_parse_convert (parser, &gstring_value,
3563 pspec, &tmp_value))
3564 {
3565 g_param_value_validate (pspec, &tmp_value);
3566 g_value_copy (&tmp_value, &priv->property_values[pspec->param_id - 1].value);
3567 priv->property_values[pspec->param_id - 1].source = GTK_SETTINGS_SOURCE_XSETTING;
3568 retval = TRUE;
3569 }
3570
3571 g_value_unset (&gstring_value);
3572 g_value_unset (&tmp_value);
3573
3574 g_value_unset (&val);
3575 }
3576
3577 return retval;
3578 }
3579
3580 static void
settings_update_xsettings(GtkSettings * settings)3581 settings_update_xsettings (GtkSettings *settings)
3582 {
3583 GParamSpec **pspecs;
3584 gint i;
3585
3586 pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), NULL);
3587 for (i = 0; pspecs[i]; i++)
3588 settings_update_xsetting (settings, pspecs[i], FALSE);
3589 g_free (pspecs);
3590 }
3591
3592 static void
gtk_settings_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)3593 gtk_settings_get_property (GObject *object,
3594 guint property_id,
3595 GValue *value,
3596 GParamSpec *pspec)
3597 {
3598 GtkSettings *settings = GTK_SETTINGS (object);
3599 GtkSettingsPrivate *priv = settings->priv;
3600
3601 /* handle internal properties */
3602 switch (property_id)
3603 {
3604 case PROP_COLOR_HASH:
3605 g_value_take_boxed (value, g_hash_table_new (g_str_hash, g_str_equal));
3606 return;
3607 default: ;
3608 }
3609
3610 settings_update_xsetting (settings, pspec, FALSE);
3611
3612 g_value_copy (&priv->property_values[property_id - 1].value, value);
3613 }
3614
3615 GtkSettingsSource
_gtk_settings_get_setting_source(GtkSettings * settings,const gchar * name)3616 _gtk_settings_get_setting_source (GtkSettings *settings,
3617 const gchar *name)
3618 {
3619 GtkSettingsPrivate *priv = settings->priv;
3620 GParamSpec *pspec;
3621
3622 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), name);
3623 if (!pspec)
3624 return GTK_SETTINGS_SOURCE_DEFAULT;
3625
3626 return priv->property_values[pspec->param_id - 1].source;
3627 }
3628
3629 /**
3630 * gtk_settings_reset_property:
3631 * @settings: a #GtkSettings object
3632 * @name: the name of the setting to reset
3633 *
3634 * Undoes the effect of calling g_object_set() to install an
3635 * application-specific value for a setting. After this call,
3636 * the setting will again follow the session-wide value for
3637 * this setting.
3638 *
3639 * Since: 3.20
3640 */
3641 void
gtk_settings_reset_property(GtkSettings * settings,const gchar * name)3642 gtk_settings_reset_property (GtkSettings *settings,
3643 const gchar *name)
3644 {
3645 GtkSettingsPrivate *priv = settings->priv;
3646 GParamSpec *pspec;
3647 GtkRcPropertyParser parser;
3648 GValue *value;
3649 GValue tmp_value = G_VALUE_INIT;
3650
3651 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), name);
3652
3653 g_return_if_fail (pspec != NULL);
3654
3655 parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
3656 value = g_param_spec_get_qdata (pspec, g_quark_from_string (name));
3657
3658 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
3659 if (value && _gtk_settings_parse_convert (parser, value, pspec, &tmp_value))
3660 g_value_copy (&tmp_value, &priv->property_values[pspec->param_id - 1].value);
3661 else
3662 g_param_value_set_default (pspec, &priv->property_values[pspec->param_id - 1].value);
3663
3664 priv->property_values[pspec->param_id - 1].source = GTK_SETTINGS_SOURCE_DEFAULT;
3665 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
3666 }
3667
3668 gboolean
gtk_settings_get_enable_animations(GtkSettings * settings)3669 gtk_settings_get_enable_animations (GtkSettings *settings)
3670 {
3671 GtkSettingsPrivate *priv = settings->priv;
3672 GtkSettingsPropertyValue *svalue = &priv->property_values[PROP_ENABLE_ANIMATIONS - 1];
3673
3674 if (svalue->source < GTK_SETTINGS_SOURCE_XSETTING)
3675 {
3676 GParamSpec *pspec;
3677
3678 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), "gtk-enable-animations");
3679 if (settings_update_xsetting (settings, pspec, FALSE))
3680 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
3681 }
3682
3683 return g_value_get_boolean (&svalue->value);
3684 }
3685
3686 gint
gtk_settings_get_dnd_drag_threshold(GtkSettings * settings)3687 gtk_settings_get_dnd_drag_threshold (GtkSettings *settings)
3688 {
3689 GtkSettingsPrivate *priv = settings->priv;
3690 GtkSettingsPropertyValue *svalue = &priv->property_values[PROP_DND_DRAG_THRESHOLD - 1];
3691
3692 if (svalue->source < GTK_SETTINGS_SOURCE_XSETTING)
3693 {
3694 GParamSpec *pspec;
3695
3696 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), "gtk-dnd-drag-threshold");
3697 if (settings_update_xsetting (settings, pspec, FALSE))
3698 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
3699 }
3700
3701 return g_value_get_int (&svalue->value);
3702 }
3703
3704 static void
settings_update_font_name(GtkSettings * settings)3705 settings_update_font_name (GtkSettings *settings)
3706 {
3707 GtkSettingsPrivate *priv = settings->priv;
3708 GtkSettingsPropertyValue *svalue = &priv->property_values[PROP_FONT_NAME - 1];
3709
3710 if (svalue->source < GTK_SETTINGS_SOURCE_XSETTING)
3711 {
3712 GParamSpec *pspec;
3713
3714 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), "gtk-font-name");
3715 if (settings_update_xsetting (settings, pspec, FALSE))
3716 g_object_notify_by_pspec (G_OBJECT (settings), pspec);
3717 }
3718 }
3719
3720 const gchar *
gtk_settings_get_font_family(GtkSettings * settings)3721 gtk_settings_get_font_family (GtkSettings *settings)
3722 {
3723 settings_update_font_name (settings);
3724
3725 return settings->priv->font_family;
3726 }
3727
3728 gint
gtk_settings_get_font_size(GtkSettings * settings)3729 gtk_settings_get_font_size (GtkSettings *settings)
3730 {
3731 settings_update_font_name (settings);
3732
3733 return settings->priv->font_size;
3734 }
3735
3736 gboolean
gtk_settings_get_font_size_is_absolute(GtkSettings * settings)3737 gtk_settings_get_font_size_is_absolute (GtkSettings *settings)
3738 {
3739 settings_update_font_name (settings);
3740
3741 return settings->priv->font_size_absolute;
3742 }
3743