2 * SECTION:clutter-settings
3 * @Title: ClutterSettings
4 * @Short_Description: Settings configuration
6 * Clutter depends on some settings to perform operations like detecting
7 * multiple button press events, or font options to render text.
9 * Usually, Clutter will strive to use the platform's settings in order
10 * to be as much integrated as possible. It is, however, possible to
11 * change these settings on a per-application basis, by using the
12 * #ClutterSettings singleton object and setting its properties. It is
13 * also possible, for toolkit developers, to retrieve the settings from
14 * the #ClutterSettings properties when implementing new UI elements,
15 * for instance the default font name.
17 * #ClutterSettings is available since Clutter 1.4
24 #include "clutter-settings.h"
27 /* for pango_fc_font_map_cache_clear() */
28 #define PANGO_ENABLE_BACKEND
29 #include <pango/pangofc-fontmap.h>
30 #endif /* HAVE_PANGO_FT2 */
32 #include "clutter-debug.h"
33 #include "clutter-settings-private.h"
34 #include "clutter-private.h"
36 #define DEFAULT_FONT_NAME "Sans 12"
38 #define CLUTTER_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SETTINGS, ClutterSettingsClass))
39 #define CLUTTER_IS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SETTINGS))
40 #define CLUTTER_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SETTINGS, ClutterSettingsClass))
45 * <structname>ClutterSettings</structname> is an opaque structure whose
46 * members cannot be directly accessed.
50 struct _ClutterSettings
52 GObject parent_instance;
54 ClutterBackend *backend;
56 gint double_click_time;
57 gint double_click_distance;
59 gint dnd_drag_threshold;
67 gchar *xft_hint_style;
70 gint long_press_duration;
72 guint last_fontconfig_timestamp;
74 guint password_hint_time;
77 struct _ClutterSettingsClass
79 GObjectClass parent_class;
88 PROP_DOUBLE_CLICK_TIME,
89 PROP_DOUBLE_CLICK_DISTANCE,
91 PROP_DND_DRAG_THRESHOLD,
101 PROP_LONG_PRESS_DURATION,
103 PROP_FONTCONFIG_TIMESTAMP,
105 PROP_PASSWORD_HINT_TIME,
110 static GParamSpec *obj_props[PROP_LAST];
112 G_DEFINE_TYPE (ClutterSettings, clutter_settings, G_TYPE_OBJECT);
115 settings_update_font_options (ClutterSettings *self)
117 cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE;
118 cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_GRAY;
119 cairo_subpixel_order_t subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
120 cairo_font_options_t *options;
122 if (self->backend == NULL)
125 options = cairo_font_options_create ();
127 cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
129 if (self->xft_hinting >= 0 &&
130 self->xft_hint_style == NULL)
132 hint_style = CAIRO_HINT_STYLE_NONE;
134 else if (self->xft_hint_style != NULL)
136 if (strcmp (self->xft_hint_style, "hintnone") == 0)
137 hint_style = CAIRO_HINT_STYLE_NONE;
138 else if (strcmp (self->xft_hint_style, "hintslight") == 0)
139 hint_style = CAIRO_HINT_STYLE_SLIGHT;
140 else if (strcmp (self->xft_hint_style, "hintmedium") == 0)
141 hint_style = CAIRO_HINT_STYLE_MEDIUM;
142 else if (strcmp (self->xft_hint_style, "hintfull") == 0)
143 hint_style = CAIRO_HINT_STYLE_FULL;
146 cairo_font_options_set_hint_style (options, hint_style);
150 if (strcmp (self->xft_rgba, "rgb") == 0)
151 subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
152 else if (strcmp (self->xft_rgba, "bgr") == 0)
153 subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
154 else if (strcmp (self->xft_rgba, "vrgb") == 0)
155 subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
156 else if (strcmp (self->xft_rgba, "vbgr") == 0)
157 subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
160 cairo_font_options_set_subpixel_order (options, subpixel_order);
162 if (self->xft_antialias >= 0 && !self->xft_antialias)
163 antialias_mode = CAIRO_ANTIALIAS_NONE;
164 else if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
165 antialias_mode = CAIRO_ANTIALIAS_SUBPIXEL;
166 else if (self->xft_antialias >= 0)
167 antialias_mode = CAIRO_ANTIALIAS_GRAY;
169 cairo_font_options_set_antialias (options, antialias_mode);
171 CLUTTER_NOTE (BACKEND, "New font options:\n"
175 " - hint-style: %s\n"
178 self->font_name != NULL ? self->font_name : DEFAULT_FONT_NAME,
181 self->xft_hint_style != NULL ? self->xft_hint_style : "<null>",
182 self->xft_rgba != NULL ? self->xft_rgba : "<null>",
185 clutter_backend_set_font_options (self->backend, options);
186 cairo_font_options_destroy (options);
190 settings_update_font_name (ClutterSettings *self)
192 CLUTTER_NOTE (BACKEND, "New font-name: %s", self->font_name);
194 if (self->backend != NULL)
195 g_signal_emit_by_name (self->backend, "font-changed");
199 settings_update_resolution (ClutterSettings *self)
201 CLUTTER_NOTE (BACKEND, "New resolution: %.2f", self->resolution);
203 if (self->backend != NULL)
204 g_signal_emit_by_name (self->backend, "resolution-changed");
208 settings_update_fontmap (ClutterSettings *self,
211 if (self->backend == NULL)
214 #ifdef HAVE_PANGO_FT2
215 CLUTTER_NOTE (BACKEND, "Update fontmaps (stamp: %d)", stamp);
217 if (self->last_fontconfig_timestamp != stamp)
219 PangoFontMap *fontmap;
220 gboolean update_needed = FALSE;
222 fontmap = clutter_get_font_map ();
224 if (PANGO_IS_FC_FONT_MAP (fontmap) &&
225 !FcConfigUptoDate (NULL))
227 pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (fontmap));
229 if (FcInitReinitialize ())
230 update_needed = TRUE;
233 self->last_fontconfig_timestamp = stamp;
236 g_signal_emit_by_name (self->backend, "font-changed");
238 #endif /* HAVE_PANGO_FT2 */
242 clutter_settings_finalize (GObject *gobject)
244 ClutterSettings *self = CLUTTER_SETTINGS (gobject);
246 g_free (self->font_name);
247 g_free (self->xft_hint_style);
248 g_free (self->xft_rgba);
250 G_OBJECT_CLASS (clutter_settings_parent_class)->finalize (gobject);
254 clutter_settings_set_property (GObject *gobject,
259 ClutterSettings *self = CLUTTER_SETTINGS (gobject);
264 self->backend = g_value_get_object (value);
267 case PROP_DOUBLE_CLICK_TIME:
268 self->double_click_time = g_value_get_int (value);
271 case PROP_DOUBLE_CLICK_DISTANCE:
272 self->double_click_distance = g_value_get_int (value);
275 case PROP_DND_DRAG_THRESHOLD:
276 self->dnd_drag_threshold = g_value_get_int (value);
280 g_free (self->font_name);
281 self->font_name = g_value_dup_string (value);
282 settings_update_font_name (self);
285 case PROP_FONT_ANTIALIAS:
286 self->xft_antialias = g_value_get_int (value);
287 settings_update_font_options (self);
291 self->resolution = (gdouble) g_value_get_int (value) / 1024.0;
292 settings_update_resolution (self);
295 case PROP_FONT_HINTING:
296 self->xft_hinting = g_value_get_int (value);
297 settings_update_font_options (self);
300 case PROP_FONT_HINT_STYLE:
301 g_free (self->xft_hint_style);
302 self->xft_hint_style = g_value_dup_string (value);
303 settings_update_font_options (self);
307 g_free (self->xft_rgba);
308 self->xft_rgba = g_value_dup_string (value);
309 settings_update_font_options (self);
312 case PROP_LONG_PRESS_DURATION:
313 self->long_press_duration = g_value_get_int (value);
316 case PROP_FONTCONFIG_TIMESTAMP:
317 settings_update_fontmap (self, g_value_get_uint (value));
320 case PROP_PASSWORD_HINT_TIME:
321 self->password_hint_time = g_value_get_uint (value);
325 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
331 clutter_settings_get_property (GObject *gobject,
336 ClutterSettings *self = CLUTTER_SETTINGS (gobject);
340 case PROP_DOUBLE_CLICK_TIME:
341 g_value_set_int (value, self->double_click_time);
344 case PROP_DOUBLE_CLICK_DISTANCE:
345 g_value_set_int (value, self->double_click_distance);
348 case PROP_DND_DRAG_THRESHOLD:
349 g_value_set_int (value, self->dnd_drag_threshold);
353 g_value_set_string (value, self->font_name);
356 case PROP_FONT_ANTIALIAS:
357 g_value_set_int (value, self->xft_antialias);
361 g_value_set_int (value, self->resolution * 1024);
364 case PROP_FONT_HINTING:
365 g_value_set_int (value, self->xft_hinting);
368 case PROP_FONT_HINT_STYLE:
369 g_value_set_string (value, self->xft_hint_style);
373 g_value_set_string (value, self->xft_rgba);
376 case PROP_LONG_PRESS_DURATION:
377 g_value_set_int (value, self->long_press_duration);
380 case PROP_PASSWORD_HINT_TIME:
381 g_value_set_uint (value, self->password_hint_time);
385 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
391 clutter_settings_dispatch_properties_changed (GObject *gobject,
395 ClutterSettings *self = CLUTTER_SETTINGS (gobject);
398 /* chain up to emit ::notify */
399 klass = G_OBJECT_CLASS (clutter_settings_parent_class);
400 klass->dispatch_properties_changed (gobject, n_pspecs, pspecs);
402 /* emit settings-changed just once for multiple properties */
403 if (self->backend != NULL)
404 g_signal_emit_by_name (self->backend, "settings-changed");
408 clutter_settings_class_init (ClutterSettingsClass *klass)
410 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
413 * ClutterSettings:backend:
415 * A back pointer to the #ClutterBackend
421 obj_props[PROP_BACKEND] =
422 g_param_spec_object ("backend",
424 "A pointer to the backend",
425 CLUTTER_TYPE_BACKEND,
426 CLUTTER_PARAM_WRITABLE |
428 G_PARAM_CONSTRUCT_ONLY);
431 * ClutterSettings:double-click-time:
433 * The time, in milliseconds, that should elapse between button-press
434 * events in order to increase the click count by 1.
438 obj_props[PROP_DOUBLE_CLICK_TIME] =
439 g_param_spec_int ("double-click-time",
440 P_("Double Click Time"),
441 P_("The time between clicks necessary to detect a multiple click"),
444 CLUTTER_PARAM_READWRITE);
447 * ClutterSettings:double-click-distance:
449 * The maximum distance, in pixels, between button-press events that
450 * determines whether or not to increase the click count by 1.
454 obj_props[PROP_DOUBLE_CLICK_DISTANCE] =
455 g_param_spec_int ("double-click-distance",
456 P_("Double Click Distance"),
457 P_("The distance between clicks necessary to detect a multiple click"),
460 CLUTTER_PARAM_READWRITE);
463 * ClutterSettings:dnd-drag-threshold:
465 * The default distance that the cursor of a pointer device
466 * should travel before a drag operation should start.
470 obj_props[PROP_DND_DRAG_THRESHOLD] =
471 g_param_spec_int ("dnd-drag-threshold",
472 P_("Drag Threshold"),
473 P_("The distance the cursor should travel before starting to drag"),
476 CLUTTER_PARAM_READWRITE);
479 * ClutterSettings:font-name:
481 * The default font name that should be used by text actors, as
482 * a string that can be passed to pango_font_description_from_string().
486 obj_props[PROP_FONT_NAME] =
487 g_param_spec_string ("font-name",
489 P_("The description of the default font, as one that could be parsed by Pango"),
491 CLUTTER_PARAM_READWRITE);
494 * ClutterSettings:font-antialias:
496 * Whether or not to use antialiasing when rendering text; a value
497 * of 1 enables it unconditionally; a value of 0 disables it
498 * unconditionally; and -1 will use the system's default.
502 obj_props[PROP_FONT_ANTIALIAS] =
503 g_param_spec_int ("font-antialias",
504 P_("Font Antialias"),
505 P_("Whether to use antialiasing (1 to enable, 0 to disable, and -1 to use the default)"),
508 CLUTTER_PARAM_READWRITE);
511 * ClutterSettings:font-dpi:
513 * The DPI used when rendering text, as a value of 1024 * dots/inch.
515 * If set to -1, the system's default will be used instead
519 obj_props[PROP_FONT_DPI] =
520 g_param_spec_int ("font-dpi",
522 P_("The resolution of the font, in 1024 * dots/inch, or -1 to use the default"),
525 CLUTTER_PARAM_READWRITE);
528 * ClutterSettings:font-hinting:
530 * Whether or not to use hinting when rendering text; a value of 1
531 * unconditionally enables it; a value of 0 unconditionally disables
532 * it; and a value of -1 will use the system's default.
536 obj_props[PROP_FONT_HINTING] =
537 g_param_spec_int ("font-hinting",
539 P_("Whether to use hinting (1 to enable, 0 to disable and -1 to use the default)"),
542 CLUTTER_PARAM_READWRITE);
545 * ClutterSettings:font-hint-style:
547 * The style of the hinting used when rendering text. Valid values
550 * <listitem><simpara>hintnone</simpara></listitem>
551 * <listitem><simpara>hintslight</simpara></listitem>
552 * <listitem><simpara>hintmedium</simpara></listitem>
553 * <listitem><simpara>hintfull</simpara></listitem>
558 obj_props[PROP_FONT_HINT_STYLE] =
559 g_param_spec_string ("font-hint-style",
560 P_("Font Hint Style"),
561 P_("The style of hinting (hintnone, hintslight, hintmedium, hintfull)"),
563 CLUTTER_PARAM_READWRITE);
566 * ClutterSettings:font-subpixel-order:
568 * The type of sub-pixel antialiasing used when rendering text. Valid
571 * <listitem><simpara>none</simpara></listitem>
572 * <listitem><simpara>rgb</simpara></listitem>
573 * <listitem><simpara>bgr</simpara></listitem>
574 * <listitem><simpara>vrgb</simpara></listitem>
575 * <listitem><simpara>vbgr</simpara></listitem>
580 obj_props[PROP_FONT_RGBA] =
581 g_param_spec_string ("font-subpixel-order",
582 P_("Font Subpixel Order"),
583 P_("The type of subpixel antialiasing (none, rgb, bgr, vrgb, vbgr)"),
585 CLUTTER_PARAM_READWRITE);
588 * ClutterSettings:long-press-duration:
590 * Sets the minimum duration for a press to be recognized as a long press
591 * gesture. The duration is expressed in milliseconds.
593 * See also #ClutterClickAction:long-press-duration.
597 obj_props[PROP_LONG_PRESS_DURATION] =
598 g_param_spec_int ("long-press-duration",
599 P_("Long Press Duration"),
600 P_("The minimum duration for a long press gesture to be recognized"),
603 CLUTTER_PARAM_READWRITE);
605 obj_props[PROP_FONTCONFIG_TIMESTAMP] =
606 g_param_spec_uint ("fontconfig-timestamp",
607 P_("Fontconfig configuration timestamp"),
608 P_("Timestamp of the current fontconfig configuration"),
611 CLUTTER_PARAM_WRITABLE);
614 * ClutterText:password-hint-time:
616 * How long should Clutter show the last input character in editable
617 * ClutterText actors. The value is in milliseconds. A value of 0
618 * disables showing the password hint. 600 is a good value for
623 obj_props[PROP_PASSWORD_HINT_TIME] =
624 g_param_spec_uint ("password-hint-time",
625 P_("Password Hint Time"),
626 P_("How long to show the last input character in hidden entries"),
629 CLUTTER_PARAM_READWRITE);
631 gobject_class->set_property = clutter_settings_set_property;
632 gobject_class->get_property = clutter_settings_get_property;
633 gobject_class->dispatch_properties_changed =
634 clutter_settings_dispatch_properties_changed;
635 gobject_class->finalize = clutter_settings_finalize;
636 g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
640 clutter_settings_init (ClutterSettings *self)
642 self->resolution = -1.0;
644 self->double_click_time = 250;
645 self->double_click_distance = 5;
647 self->dnd_drag_threshold = 8;
649 self->font_name = g_strdup (DEFAULT_FONT_NAME);
651 self->xft_antialias = -1;
652 self->xft_hinting = -1;
653 self->xft_hint_style = NULL;
654 self->xft_rgba = NULL;
656 self->long_press_duration = 500;
660 * clutter_settings_get_default:
662 * Retrieves the singleton instance of #ClutterSettings
664 * Return value: (transfer none): the instance of #ClutterSettings. The
665 * returned object is owned by Clutter and it should not be unreferenced
671 clutter_settings_get_default (void)
673 static ClutterSettings *settings = NULL;
675 if (G_UNLIKELY (settings == NULL))
676 settings = g_object_new (CLUTTER_TYPE_SETTINGS, NULL);
682 _clutter_settings_set_backend (ClutterSettings *settings,
683 ClutterBackend *backend)
685 g_assert (CLUTTER_IS_SETTINGS (settings));
686 g_assert (CLUTTER_IS_BACKEND (backend));
688 settings->backend = backend;
691 #define SETTINGS_GROUP "Settings"
694 _clutter_settings_read_from_key_file (ClutterSettings *settings,
697 GObjectClass *settings_class;
698 GObject *settings_obj;
702 if (!g_key_file_has_group (keyfile, SETTINGS_GROUP))
705 settings_obj = G_OBJECT (settings);
706 settings_class = G_OBJECT_GET_CLASS (settings);
707 pspecs = g_object_class_list_properties (settings_class, &n_pspecs);
709 for (i = 0; i < n_pspecs; i++)
711 GParamSpec *pspec = pspecs[i];
712 const gchar *p_name = pspec->name;
713 GType p_type = G_TYPE_FUNDAMENTAL (pspec->value_type);
714 GValue value = G_VALUE_INIT;
715 GError *key_error = NULL;
717 g_value_init (&value, p_type);
726 val = g_key_file_get_integer (keyfile,
727 SETTINGS_GROUP, p_name,
729 if (p_type == G_TYPE_INT)
730 g_value_set_int (&value, val);
732 g_value_set_uint (&value, val);
740 val = g_key_file_get_boolean (keyfile,
741 SETTINGS_GROUP, p_name,
743 g_value_set_boolean (&value, val);
752 val = g_key_file_get_double (keyfile,
753 SETTINGS_GROUP, p_name,
755 if (p_type == G_TYPE_FLOAT)
756 g_value_set_float (&value, val);
758 g_value_set_double (&value, val);
766 val = g_key_file_get_string (keyfile,
767 SETTINGS_GROUP, p_name,
769 g_value_take_string (&value, val);
774 if (key_error != NULL &&
775 key_error->domain != G_KEY_FILE_ERROR &&
776 key_error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
778 g_critical ("Unable to read the value for setting '%s': %s",
783 if (key_error == NULL)
784 g_object_set_property (settings_obj, p_name, &value);
786 g_error_free (key_error);
788 g_value_unset (&value);