mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
3958a019bb
There is no reason to use Xsettings for the X11 backend, as it comes from the GSetting store anyway, so move the font setting reading to ClutterSettings and read directly from GSettings. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1364
1017 lines
28 KiB
C
1017 lines
28 KiB
C
/**
|
|
* SECTION:clutter-settings
|
|
* @Title: ClutterSettings
|
|
* @Short_Description: Settings configuration
|
|
*
|
|
* Clutter depends on some settings to perform operations like detecting
|
|
* multiple button press events, or font options to render text.
|
|
*
|
|
* Usually, Clutter will strive to use the platform's settings in order
|
|
* to be as much integrated as possible. It is, however, possible to
|
|
* change these settings on a per-application basis, by using the
|
|
* #ClutterSettings singleton object and setting its properties. It is
|
|
* also possible, for toolkit developers, to retrieve the settings from
|
|
* the #ClutterSettings properties when implementing new UI elements,
|
|
* for instance the default font name.
|
|
*
|
|
* #ClutterSettings is available since Clutter 1.4
|
|
*/
|
|
|
|
#include "clutter-build-config.h"
|
|
|
|
#include "clutter-settings.h"
|
|
|
|
#ifdef HAVE_PANGO_FT2
|
|
/* for pango_fc_font_map_cache_clear() */
|
|
#define PANGO_ENABLE_BACKEND
|
|
#include <pango/pangofc-fontmap.h>
|
|
#endif /* HAVE_PANGO_FT2 */
|
|
|
|
#include "clutter-debug.h"
|
|
#include "clutter-settings-private.h"
|
|
#include "clutter-stage-private.h"
|
|
#include "clutter-private.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#define DEFAULT_FONT_NAME "Sans 12"
|
|
|
|
#define CLUTTER_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SETTINGS, ClutterSettingsClass))
|
|
#define CLUTTER_IS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SETTINGS))
|
|
#define CLUTTER_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SETTINGS, ClutterSettingsClass))
|
|
|
|
typedef struct
|
|
{
|
|
cairo_antialias_t cairo_antialias;
|
|
gint clutter_font_antialias;
|
|
|
|
cairo_hint_style_t cairo_hint_style;
|
|
const char *clutter_font_hint_style;
|
|
|
|
cairo_subpixel_order_t cairo_subpixel_order;
|
|
const char *clutter_font_subpixel_order;
|
|
} FontSettings;
|
|
|
|
/**
|
|
* ClutterSettings:
|
|
*
|
|
* `ClutterSettings` is an opaque structure whose
|
|
* members cannot be directly accessed.
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
struct _ClutterSettings
|
|
{
|
|
GObject parent_instance;
|
|
|
|
ClutterBackend *backend;
|
|
GSettings *xsettings;
|
|
|
|
gint double_click_time;
|
|
gint double_click_distance;
|
|
|
|
gint dnd_drag_threshold;
|
|
|
|
gdouble resolution;
|
|
|
|
gchar *font_name;
|
|
gint font_dpi;
|
|
|
|
gint xft_hinting;
|
|
gint xft_antialias;
|
|
gchar *xft_hint_style;
|
|
gchar *xft_rgba;
|
|
|
|
gint long_press_duration;
|
|
|
|
guint last_fontconfig_timestamp;
|
|
|
|
guint password_hint_time;
|
|
|
|
gint unscaled_font_dpi;
|
|
};
|
|
|
|
struct _ClutterSettingsClass
|
|
{
|
|
GObjectClass parent_class;
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
|
|
PROP_BACKEND,
|
|
|
|
PROP_DOUBLE_CLICK_TIME,
|
|
PROP_DOUBLE_CLICK_DISTANCE,
|
|
|
|
PROP_DND_DRAG_THRESHOLD,
|
|
|
|
PROP_FONT_NAME,
|
|
|
|
PROP_FONT_ANTIALIAS,
|
|
PROP_FONT_DPI,
|
|
PROP_FONT_HINTING,
|
|
PROP_FONT_HINT_STYLE,
|
|
PROP_FONT_RGBA,
|
|
|
|
PROP_LONG_PRESS_DURATION,
|
|
|
|
PROP_FONTCONFIG_TIMESTAMP,
|
|
|
|
PROP_PASSWORD_HINT_TIME,
|
|
|
|
PROP_UNSCALED_FONT_DPI,
|
|
|
|
PROP_LAST
|
|
};
|
|
|
|
static GParamSpec *obj_props[PROP_LAST];
|
|
|
|
G_DEFINE_TYPE (ClutterSettings, clutter_settings, G_TYPE_OBJECT);
|
|
|
|
static inline void
|
|
settings_update_font_options (ClutterSettings *self)
|
|
{
|
|
cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE;
|
|
cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_GRAY;
|
|
cairo_subpixel_order_t subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
|
cairo_font_options_t *options;
|
|
|
|
if (self->backend == NULL)
|
|
return;
|
|
|
|
options = cairo_font_options_create ();
|
|
|
|
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
|
|
|
|
if (self->xft_hinting >= 0 &&
|
|
self->xft_hint_style == NULL)
|
|
{
|
|
hint_style = CAIRO_HINT_STYLE_NONE;
|
|
}
|
|
else if (self->xft_hint_style != NULL)
|
|
{
|
|
if (strcmp (self->xft_hint_style, "hintnone") == 0)
|
|
hint_style = CAIRO_HINT_STYLE_NONE;
|
|
else if (strcmp (self->xft_hint_style, "hintslight") == 0)
|
|
hint_style = CAIRO_HINT_STYLE_SLIGHT;
|
|
else if (strcmp (self->xft_hint_style, "hintmedium") == 0)
|
|
hint_style = CAIRO_HINT_STYLE_MEDIUM;
|
|
else if (strcmp (self->xft_hint_style, "hintfull") == 0)
|
|
hint_style = CAIRO_HINT_STYLE_FULL;
|
|
}
|
|
|
|
cairo_font_options_set_hint_style (options, hint_style);
|
|
|
|
if (self->xft_rgba)
|
|
{
|
|
if (strcmp (self->xft_rgba, "rgb") == 0)
|
|
subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
|
|
else if (strcmp (self->xft_rgba, "bgr") == 0)
|
|
subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
|
|
else if (strcmp (self->xft_rgba, "vrgb") == 0)
|
|
subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
|
|
else if (strcmp (self->xft_rgba, "vbgr") == 0)
|
|
subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
|
|
}
|
|
|
|
cairo_font_options_set_subpixel_order (options, subpixel_order);
|
|
|
|
if (self->xft_antialias >= 0 && !self->xft_antialias)
|
|
antialias_mode = CAIRO_ANTIALIAS_NONE;
|
|
else if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
|
antialias_mode = CAIRO_ANTIALIAS_SUBPIXEL;
|
|
else if (self->xft_antialias >= 0)
|
|
antialias_mode = CAIRO_ANTIALIAS_GRAY;
|
|
|
|
cairo_font_options_set_antialias (options, antialias_mode);
|
|
|
|
CLUTTER_NOTE (BACKEND, "New font options:\n"
|
|
" - font-name: %s\n"
|
|
" - antialias: %d\n"
|
|
" - hinting: %d\n"
|
|
" - hint-style: %s\n"
|
|
" - rgba: %s\n",
|
|
self->font_name != NULL ? self->font_name : DEFAULT_FONT_NAME,
|
|
self->xft_antialias,
|
|
self->xft_hinting,
|
|
self->xft_hint_style != NULL ? self->xft_hint_style : "<null>",
|
|
self->xft_rgba != NULL ? self->xft_rgba : "<null>");
|
|
|
|
clutter_backend_set_font_options (self->backend, options);
|
|
cairo_font_options_destroy (options);
|
|
}
|
|
|
|
static void
|
|
settings_update_font_name (ClutterSettings *self)
|
|
{
|
|
CLUTTER_NOTE (BACKEND, "New font-name: %s", self->font_name);
|
|
|
|
if (self->backend != NULL)
|
|
g_signal_emit_by_name (self->backend, "font-changed");
|
|
}
|
|
|
|
static void
|
|
settings_update_resolution (ClutterSettings *self)
|
|
{
|
|
const char *scale_env = NULL;
|
|
|
|
if (self->font_dpi > 0)
|
|
self->resolution = (gdouble) self->font_dpi / 1024.0;
|
|
else
|
|
self->resolution = 96.0;
|
|
|
|
scale_env = g_getenv ("GDK_DPI_SCALE");
|
|
if (scale_env != NULL)
|
|
{
|
|
double scale = g_ascii_strtod (scale_env, NULL);
|
|
if (scale != 0 && self->resolution > 0)
|
|
self->resolution *= scale;
|
|
}
|
|
|
|
CLUTTER_NOTE (BACKEND, "New resolution: %.2f (%s)",
|
|
self->resolution,
|
|
self->unscaled_font_dpi > 0 ? "unscaled" : "scaled");
|
|
|
|
if (self->backend != NULL)
|
|
g_signal_emit_by_name (self->backend, "resolution-changed");
|
|
}
|
|
|
|
static void
|
|
settings_update_fontmap (ClutterSettings *self,
|
|
guint stamp)
|
|
{
|
|
if (self->backend == NULL)
|
|
return;
|
|
|
|
#ifdef HAVE_PANGO_FT2
|
|
CLUTTER_NOTE (BACKEND, "Update fontmaps (stamp: %d)", stamp);
|
|
|
|
if (self->last_fontconfig_timestamp != stamp)
|
|
{
|
|
ClutterMainContext *context;
|
|
gboolean update_needed = FALSE;
|
|
|
|
context = _clutter_context_get_default ();
|
|
|
|
/* If there is no font map yet then we don't need to do anything
|
|
* because the config for fontconfig will be read when it is
|
|
* created */
|
|
if (context->font_map)
|
|
{
|
|
PangoFontMap *fontmap = PANGO_FONT_MAP (context->font_map);
|
|
|
|
if (PANGO_IS_FC_FONT_MAP (fontmap) &&
|
|
!FcConfigUptoDate (NULL))
|
|
{
|
|
pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (fontmap));
|
|
|
|
if (FcInitReinitialize ())
|
|
update_needed = TRUE;
|
|
}
|
|
}
|
|
|
|
self->last_fontconfig_timestamp = stamp;
|
|
|
|
if (update_needed)
|
|
g_signal_emit_by_name (self->backend, "font-changed");
|
|
}
|
|
#endif /* HAVE_PANGO_FT2 */
|
|
}
|
|
|
|
static void
|
|
get_font_gsettings (GSettings *xsettings,
|
|
FontSettings *output)
|
|
{
|
|
/* org.gnome.settings-daemon.GsdFontAntialiasingMode */
|
|
static const struct
|
|
{
|
|
cairo_antialias_t cairo_antialias;
|
|
gint clutter_font_antialias;
|
|
}
|
|
antialiasings[] =
|
|
{
|
|
/* none=0 */ {CAIRO_ANTIALIAS_NONE, 0},
|
|
/* grayscale=1 */ {CAIRO_ANTIALIAS_GRAY, 1},
|
|
/* rgba=2 */ {CAIRO_ANTIALIAS_SUBPIXEL, 1},
|
|
};
|
|
|
|
/* org.gnome.settings-daemon.GsdFontHinting */
|
|
static const struct
|
|
{
|
|
cairo_hint_style_t cairo_hint_style;
|
|
const char *clutter_font_hint_style;
|
|
}
|
|
hintings[] =
|
|
{
|
|
/* none=0 */ {CAIRO_HINT_STYLE_NONE, "hintnone"},
|
|
/* slight=1 */ {CAIRO_HINT_STYLE_SLIGHT, "hintslight"},
|
|
/* medium=2 */ {CAIRO_HINT_STYLE_MEDIUM, "hintmedium"},
|
|
/* full=3 */ {CAIRO_HINT_STYLE_FULL, "hintfull"},
|
|
};
|
|
|
|
/* org.gnome.settings-daemon.GsdFontRgbaOrder */
|
|
static const struct
|
|
{
|
|
cairo_subpixel_order_t cairo_subpixel_order;
|
|
const char *clutter_font_subpixel_order;
|
|
}
|
|
rgba_orders[] =
|
|
{
|
|
/* rgba=0 */ {CAIRO_SUBPIXEL_ORDER_RGB, "rgb"}, /* XXX what is 'rgba'? */
|
|
/* rgb=1 */ {CAIRO_SUBPIXEL_ORDER_RGB, "rgb"},
|
|
/* bgr=2 */ {CAIRO_SUBPIXEL_ORDER_BGR, "bgr"},
|
|
/* vrgb=3 */ {CAIRO_SUBPIXEL_ORDER_VRGB, "vrgb"},
|
|
/* vbgr=4 */ {CAIRO_SUBPIXEL_ORDER_VBGR, "vbgr"},
|
|
};
|
|
guint i;
|
|
|
|
i = g_settings_get_enum (xsettings, "hinting");
|
|
if (i < G_N_ELEMENTS (hintings))
|
|
{
|
|
output->cairo_hint_style = hintings[i].cairo_hint_style;
|
|
output->clutter_font_hint_style = hintings[i].clutter_font_hint_style;
|
|
}
|
|
else
|
|
{
|
|
output->cairo_hint_style = CAIRO_HINT_STYLE_DEFAULT;
|
|
output->clutter_font_hint_style = NULL;
|
|
}
|
|
|
|
i = g_settings_get_enum (xsettings, "antialiasing");
|
|
if (i < G_N_ELEMENTS (antialiasings))
|
|
{
|
|
output->cairo_antialias = antialiasings[i].cairo_antialias;
|
|
output->clutter_font_antialias = antialiasings[i].clutter_font_antialias;
|
|
}
|
|
else
|
|
{
|
|
output->cairo_antialias = CAIRO_ANTIALIAS_DEFAULT;
|
|
output->clutter_font_antialias = -1;
|
|
}
|
|
|
|
i = g_settings_get_enum (xsettings, "rgba-order");
|
|
if (i < G_N_ELEMENTS (rgba_orders))
|
|
{
|
|
output->cairo_subpixel_order = rgba_orders[i].cairo_subpixel_order;
|
|
output->clutter_font_subpixel_order = rgba_orders[i].clutter_font_subpixel_order;
|
|
}
|
|
else
|
|
{
|
|
output->cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
|
output->clutter_font_subpixel_order = NULL;
|
|
}
|
|
|
|
if (output->cairo_antialias == CAIRO_ANTIALIAS_GRAY)
|
|
output->clutter_font_subpixel_order = "none";
|
|
}
|
|
|
|
static void
|
|
init_font_options (ClutterSettings *self)
|
|
{
|
|
GSettings *xsettings = self->xsettings;
|
|
cairo_font_options_t *options = cairo_font_options_create ();
|
|
FontSettings fs;
|
|
|
|
get_font_gsettings (xsettings, &fs);
|
|
|
|
cairo_font_options_set_hint_style (options, fs.cairo_hint_style);
|
|
cairo_font_options_set_antialias (options, fs.cairo_antialias);
|
|
cairo_font_options_set_subpixel_order (options, fs.cairo_subpixel_order);
|
|
|
|
clutter_backend_set_font_options (self->backend, options);
|
|
|
|
cairo_font_options_destroy (options);
|
|
}
|
|
|
|
static gboolean
|
|
on_xsettings_change_event (GSettings *xsettings,
|
|
gpointer keys,
|
|
gint n_keys,
|
|
gpointer user_data)
|
|
{
|
|
ClutterSettings *self = CLUTTER_SETTINGS (user_data);
|
|
FontSettings fs;
|
|
gint hinting;
|
|
|
|
get_font_gsettings (xsettings, &fs);
|
|
hinting = fs.cairo_hint_style == CAIRO_HINT_STYLE_NONE ? 0 : 1;
|
|
g_object_set (self,
|
|
"font-hinting", hinting,
|
|
"font-hint-style", fs.clutter_font_hint_style,
|
|
"font-antialias", fs.clutter_font_antialias,
|
|
"font-subpixel-order", fs.clutter_font_subpixel_order,
|
|
NULL);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
load_initial_settings (ClutterSettings *self)
|
|
{
|
|
static const gchar xsettings_path[] =
|
|
"org.gnome.settings-daemon.plugins.xsettings";
|
|
GSettingsSchemaSource *source = g_settings_schema_source_get_default ();
|
|
GSettingsSchema *schema;
|
|
|
|
schema = g_settings_schema_source_lookup (source, xsettings_path, TRUE);
|
|
if (!schema)
|
|
{
|
|
g_warning ("Failed to find schema: %s", xsettings_path);
|
|
}
|
|
else
|
|
{
|
|
self->xsettings = g_settings_new_full (schema, NULL, NULL);
|
|
if (self->xsettings)
|
|
{
|
|
init_font_options (self);
|
|
g_signal_connect (self->xsettings, "change-event",
|
|
G_CALLBACK (on_xsettings_change_event),
|
|
self);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_settings_finalize (GObject *gobject)
|
|
{
|
|
ClutterSettings *self = CLUTTER_SETTINGS (gobject);
|
|
|
|
g_free (self->font_name);
|
|
g_free (self->xft_hint_style);
|
|
g_free (self->xft_rgba);
|
|
|
|
g_clear_object (&self->xsettings);
|
|
|
|
G_OBJECT_CLASS (clutter_settings_parent_class)->finalize (gobject);
|
|
}
|
|
|
|
static void
|
|
clutter_settings_set_property (GObject *gobject,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ClutterSettings *self = CLUTTER_SETTINGS (gobject);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_BACKEND:
|
|
self->backend = g_value_get_object (value);
|
|
break;
|
|
|
|
case PROP_DOUBLE_CLICK_TIME:
|
|
self->double_click_time = g_value_get_int (value);
|
|
break;
|
|
|
|
case PROP_DOUBLE_CLICK_DISTANCE:
|
|
self->double_click_distance = g_value_get_int (value);
|
|
break;
|
|
|
|
case PROP_DND_DRAG_THRESHOLD:
|
|
self->dnd_drag_threshold = g_value_get_int (value);
|
|
break;
|
|
|
|
case PROP_FONT_NAME:
|
|
g_free (self->font_name);
|
|
self->font_name = g_value_dup_string (value);
|
|
settings_update_font_name (self);
|
|
break;
|
|
|
|
case PROP_FONT_ANTIALIAS:
|
|
self->xft_antialias = g_value_get_int (value);
|
|
settings_update_font_options (self);
|
|
break;
|
|
|
|
case PROP_FONT_DPI:
|
|
self->font_dpi = g_value_get_int (value);
|
|
settings_update_resolution (self);
|
|
break;
|
|
|
|
case PROP_FONT_HINTING:
|
|
self->xft_hinting = g_value_get_int (value);
|
|
settings_update_font_options (self);
|
|
break;
|
|
|
|
case PROP_FONT_HINT_STYLE:
|
|
g_free (self->xft_hint_style);
|
|
self->xft_hint_style = g_value_dup_string (value);
|
|
settings_update_font_options (self);
|
|
break;
|
|
|
|
case PROP_FONT_RGBA:
|
|
g_free (self->xft_rgba);
|
|
self->xft_rgba = g_value_dup_string (value);
|
|
settings_update_font_options (self);
|
|
break;
|
|
|
|
case PROP_LONG_PRESS_DURATION:
|
|
self->long_press_duration = g_value_get_int (value);
|
|
break;
|
|
|
|
case PROP_FONTCONFIG_TIMESTAMP:
|
|
settings_update_fontmap (self, g_value_get_uint (value));
|
|
break;
|
|
|
|
case PROP_PASSWORD_HINT_TIME:
|
|
self->password_hint_time = g_value_get_uint (value);
|
|
break;
|
|
|
|
case PROP_UNSCALED_FONT_DPI:
|
|
self->font_dpi = g_value_get_int (value);
|
|
settings_update_resolution (self);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
clutter_settings_set_property_internal (ClutterSettings *self,
|
|
const char *property,
|
|
GValue *value)
|
|
{
|
|
|
|
property = g_intern_string (property);
|
|
|
|
g_object_set_property (G_OBJECT (self), property, value);
|
|
}
|
|
|
|
static void
|
|
clutter_settings_get_property (GObject *gobject,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ClutterSettings *self = CLUTTER_SETTINGS (gobject);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_DOUBLE_CLICK_TIME:
|
|
g_value_set_int (value, self->double_click_time);
|
|
break;
|
|
|
|
case PROP_DOUBLE_CLICK_DISTANCE:
|
|
g_value_set_int (value, self->double_click_distance);
|
|
break;
|
|
|
|
case PROP_DND_DRAG_THRESHOLD:
|
|
g_value_set_int (value, self->dnd_drag_threshold);
|
|
break;
|
|
|
|
case PROP_FONT_NAME:
|
|
g_value_set_string (value, self->font_name);
|
|
break;
|
|
|
|
case PROP_FONT_ANTIALIAS:
|
|
g_value_set_int (value, self->xft_antialias);
|
|
break;
|
|
|
|
case PROP_FONT_DPI:
|
|
g_value_set_int (value, self->resolution * 1024);
|
|
break;
|
|
|
|
case PROP_FONT_HINTING:
|
|
g_value_set_int (value, self->xft_hinting);
|
|
break;
|
|
|
|
case PROP_FONT_HINT_STYLE:
|
|
g_value_set_string (value, self->xft_hint_style);
|
|
break;
|
|
|
|
case PROP_FONT_RGBA:
|
|
g_value_set_string (value, self->xft_rgba);
|
|
break;
|
|
|
|
case PROP_LONG_PRESS_DURATION:
|
|
g_value_set_int (value, self->long_press_duration);
|
|
break;
|
|
|
|
case PROP_PASSWORD_HINT_TIME:
|
|
g_value_set_uint (value, self->password_hint_time);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_settings_dispatch_properties_changed (GObject *gobject,
|
|
guint n_pspecs,
|
|
GParamSpec **pspecs)
|
|
{
|
|
ClutterSettings *self = CLUTTER_SETTINGS (gobject);
|
|
GObjectClass *klass;
|
|
|
|
/* chain up to emit ::notify */
|
|
klass = G_OBJECT_CLASS (clutter_settings_parent_class);
|
|
klass->dispatch_properties_changed (gobject, n_pspecs, pspecs);
|
|
|
|
/* emit settings-changed just once for multiple properties */
|
|
if (self->backend != NULL)
|
|
g_signal_emit_by_name (self->backend, "settings-changed");
|
|
}
|
|
|
|
static void
|
|
clutter_settings_class_init (ClutterSettingsClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
/**
|
|
* ClutterSettings:backend:
|
|
*
|
|
* A back pointer to the #ClutterBackend
|
|
*
|
|
* Since: 1.4
|
|
*
|
|
* Deprecated: 1.10
|
|
*/
|
|
obj_props[PROP_BACKEND] =
|
|
g_param_spec_object ("backend",
|
|
"Backend",
|
|
"A pointer to the backend",
|
|
CLUTTER_TYPE_BACKEND,
|
|
CLUTTER_PARAM_WRITABLE |
|
|
G_PARAM_DEPRECATED |
|
|
G_PARAM_CONSTRUCT_ONLY);
|
|
|
|
/**
|
|
* ClutterSettings:double-click-time:
|
|
*
|
|
* The time, in milliseconds, that should elapse between button-press
|
|
* events in order to increase the click count by 1.
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
obj_props[PROP_DOUBLE_CLICK_TIME] =
|
|
g_param_spec_int ("double-click-time",
|
|
P_("Double Click Time"),
|
|
P_("The time between clicks necessary to detect a multiple click"),
|
|
0, G_MAXINT,
|
|
250,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
/**
|
|
* ClutterSettings:double-click-distance:
|
|
*
|
|
* The maximum distance, in pixels, between button-press events that
|
|
* determines whether or not to increase the click count by 1.
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
obj_props[PROP_DOUBLE_CLICK_DISTANCE] =
|
|
g_param_spec_int ("double-click-distance",
|
|
P_("Double Click Distance"),
|
|
P_("The distance between clicks necessary to detect a multiple click"),
|
|
0, G_MAXINT,
|
|
5,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
/**
|
|
* ClutterSettings:dnd-drag-threshold:
|
|
*
|
|
* The default distance that the cursor of a pointer device
|
|
* should travel before a drag operation should start.
|
|
*
|
|
* Since: 1.8
|
|
*/
|
|
obj_props[PROP_DND_DRAG_THRESHOLD] =
|
|
g_param_spec_int ("dnd-drag-threshold",
|
|
P_("Drag Threshold"),
|
|
P_("The distance the cursor should travel before starting to drag"),
|
|
1, G_MAXINT,
|
|
8,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
/**
|
|
* ClutterSettings:font-name:
|
|
*
|
|
* The default font name that should be used by text actors, as
|
|
* a string that can be passed to pango_font_description_from_string().
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
obj_props[PROP_FONT_NAME] =
|
|
g_param_spec_string ("font-name",
|
|
P_("Font Name"),
|
|
P_("The description of the default font, as one that could be parsed by Pango"),
|
|
NULL,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
/**
|
|
* ClutterSettings:font-antialias:
|
|
*
|
|
* Whether or not to use antialiasing when rendering text; a value
|
|
* of 1 enables it unconditionally; a value of 0 disables it
|
|
* unconditionally; and -1 will use the system's default.
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
obj_props[PROP_FONT_ANTIALIAS] =
|
|
g_param_spec_int ("font-antialias",
|
|
P_("Font Antialias"),
|
|
P_("Whether to use antialiasing (1 to enable, 0 to disable, and -1 to use the default)"),
|
|
-1, 1,
|
|
-1,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
/**
|
|
* ClutterSettings:font-dpi:
|
|
*
|
|
* The DPI used when rendering text, as a value of 1024 * dots/inch.
|
|
*
|
|
* If set to -1, the system's default will be used instead
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
obj_props[PROP_FONT_DPI] =
|
|
g_param_spec_int ("font-dpi",
|
|
P_("Font DPI"),
|
|
P_("The resolution of the font, in 1024 * dots/inch, or -1 to use the default"),
|
|
-1, 1024 * 1024,
|
|
-1,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
obj_props[PROP_UNSCALED_FONT_DPI] =
|
|
g_param_spec_int ("unscaled-font-dpi",
|
|
P_("Font DPI"),
|
|
P_("The resolution of the font, in 1024 * dots/inch, or -1 to use the default"),
|
|
-1, 1024 * 1024,
|
|
-1,
|
|
CLUTTER_PARAM_WRITABLE);
|
|
|
|
/**
|
|
* ClutterSettings:font-hinting:
|
|
*
|
|
* Whether or not to use hinting when rendering text; a value of 1
|
|
* unconditionally enables it; a value of 0 unconditionally disables
|
|
* it; and a value of -1 will use the system's default.
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
obj_props[PROP_FONT_HINTING] =
|
|
g_param_spec_int ("font-hinting",
|
|
P_("Font Hinting"),
|
|
P_("Whether to use hinting (1 to enable, 0 to disable and -1 to use the default)"),
|
|
-1, 1,
|
|
-1,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
/**
|
|
* ClutterSettings:font-hint-style:
|
|
*
|
|
* The style of the hinting used when rendering text. Valid values
|
|
* are:
|
|
*
|
|
* - hintnone
|
|
* - hintslight
|
|
* - hintmedium
|
|
* - hintfull
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
obj_props[PROP_FONT_HINT_STYLE] =
|
|
g_param_spec_string ("font-hint-style",
|
|
P_("Font Hint Style"),
|
|
P_("The style of hinting (hintnone, hintslight, hintmedium, hintfull)"),
|
|
NULL,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
/**
|
|
* ClutterSettings:font-subpixel-order:
|
|
*
|
|
* The type of sub-pixel antialiasing used when rendering text. Valid
|
|
* values are:
|
|
*
|
|
* - none
|
|
* - rgb
|
|
* - bgr
|
|
* - vrgb
|
|
* - vbgr
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
obj_props[PROP_FONT_RGBA] =
|
|
g_param_spec_string ("font-subpixel-order",
|
|
P_("Font Subpixel Order"),
|
|
P_("The type of subpixel antialiasing (none, rgb, bgr, vrgb, vbgr)"),
|
|
NULL,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
/**
|
|
* ClutterSettings:long-press-duration:
|
|
*
|
|
* Sets the minimum duration for a press to be recognized as a long press
|
|
* gesture. The duration is expressed in milliseconds.
|
|
*
|
|
* See also #ClutterClickAction:long-press-duration.
|
|
*
|
|
* Since: 1.8
|
|
*/
|
|
obj_props[PROP_LONG_PRESS_DURATION] =
|
|
g_param_spec_int ("long-press-duration",
|
|
P_("Long Press Duration"),
|
|
P_("The minimum duration for a long press gesture to be recognized"),
|
|
0, G_MAXINT,
|
|
500,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
obj_props[PROP_FONTCONFIG_TIMESTAMP] =
|
|
g_param_spec_uint ("fontconfig-timestamp",
|
|
P_("Fontconfig configuration timestamp"),
|
|
P_("Timestamp of the current fontconfig configuration"),
|
|
0, G_MAXUINT,
|
|
0,
|
|
CLUTTER_PARAM_WRITABLE);
|
|
|
|
/**
|
|
* ClutterText:password-hint-time:
|
|
*
|
|
* How long should Clutter show the last input character in editable
|
|
* ClutterText actors. The value is in milliseconds. A value of 0
|
|
* disables showing the password hint. 600 is a good value for
|
|
* enabling the hint.
|
|
*
|
|
* Since: 1.10
|
|
*/
|
|
obj_props[PROP_PASSWORD_HINT_TIME] =
|
|
g_param_spec_uint ("password-hint-time",
|
|
P_("Password Hint Time"),
|
|
P_("How long to show the last input character in hidden entries"),
|
|
0, G_MAXUINT,
|
|
0,
|
|
CLUTTER_PARAM_READWRITE);
|
|
|
|
gobject_class->set_property = clutter_settings_set_property;
|
|
gobject_class->get_property = clutter_settings_get_property;
|
|
gobject_class->dispatch_properties_changed =
|
|
clutter_settings_dispatch_properties_changed;
|
|
gobject_class->finalize = clutter_settings_finalize;
|
|
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
|
}
|
|
|
|
static void
|
|
clutter_settings_init (ClutterSettings *self)
|
|
{
|
|
self->resolution = -1.0;
|
|
|
|
self->font_dpi = -1;
|
|
self->unscaled_font_dpi = -1;
|
|
|
|
self->double_click_time = 250;
|
|
self->double_click_distance = 5;
|
|
|
|
self->dnd_drag_threshold = 8;
|
|
|
|
self->font_name = g_strdup (DEFAULT_FONT_NAME);
|
|
|
|
self->xft_antialias = -1;
|
|
self->xft_hinting = -1;
|
|
self->xft_hint_style = NULL;
|
|
self->xft_rgba = NULL;
|
|
|
|
self->long_press_duration = 500;
|
|
}
|
|
|
|
/**
|
|
* clutter_settings_get_default:
|
|
*
|
|
* Retrieves the singleton instance of #ClutterSettings
|
|
*
|
|
* Return value: (transfer none): the instance of #ClutterSettings. The
|
|
* returned object is owned by Clutter and it should not be unreferenced
|
|
* directly
|
|
*
|
|
* Since: 1.4
|
|
*/
|
|
ClutterSettings *
|
|
clutter_settings_get_default (void)
|
|
{
|
|
static ClutterSettings *settings = NULL;
|
|
|
|
if (G_UNLIKELY (settings == NULL))
|
|
settings = g_object_new (CLUTTER_TYPE_SETTINGS, NULL);
|
|
|
|
return settings;
|
|
}
|
|
|
|
void
|
|
_clutter_settings_set_backend (ClutterSettings *settings,
|
|
ClutterBackend *backend)
|
|
{
|
|
g_assert (CLUTTER_IS_SETTINGS (settings));
|
|
g_assert (CLUTTER_IS_BACKEND (backend));
|
|
|
|
settings->backend = backend;
|
|
|
|
load_initial_settings (settings);
|
|
}
|
|
|
|
#define SETTINGS_GROUP "Settings"
|
|
|
|
void
|
|
_clutter_settings_read_from_key_file (ClutterSettings *settings,
|
|
GKeyFile *keyfile)
|
|
{
|
|
GObjectClass *settings_class;
|
|
GObject *settings_obj;
|
|
GParamSpec **pspecs;
|
|
guint n_pspecs, i;
|
|
|
|
if (!g_key_file_has_group (keyfile, SETTINGS_GROUP))
|
|
return;
|
|
|
|
settings_obj = G_OBJECT (settings);
|
|
settings_class = G_OBJECT_GET_CLASS (settings);
|
|
pspecs = g_object_class_list_properties (settings_class, &n_pspecs);
|
|
|
|
for (i = 0; i < n_pspecs; i++)
|
|
{
|
|
GParamSpec *pspec = pspecs[i];
|
|
const gchar *p_name = pspec->name;
|
|
GType p_type = G_TYPE_FUNDAMENTAL (pspec->value_type);
|
|
GValue value = G_VALUE_INIT;
|
|
GError *key_error = NULL;
|
|
|
|
g_value_init (&value, p_type);
|
|
|
|
switch (p_type)
|
|
{
|
|
case G_TYPE_INT:
|
|
case G_TYPE_UINT:
|
|
{
|
|
gint val;
|
|
|
|
val = g_key_file_get_integer (keyfile,
|
|
SETTINGS_GROUP, p_name,
|
|
&key_error);
|
|
if (p_type == G_TYPE_INT)
|
|
g_value_set_int (&value, val);
|
|
else
|
|
g_value_set_uint (&value, val);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_BOOLEAN:
|
|
{
|
|
gboolean val;
|
|
|
|
val = g_key_file_get_boolean (keyfile,
|
|
SETTINGS_GROUP, p_name,
|
|
&key_error);
|
|
g_value_set_boolean (&value, val);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
case G_TYPE_DOUBLE:
|
|
{
|
|
gdouble val;
|
|
|
|
val = g_key_file_get_double (keyfile,
|
|
SETTINGS_GROUP, p_name,
|
|
&key_error);
|
|
if (p_type == G_TYPE_FLOAT)
|
|
g_value_set_float (&value, val);
|
|
else
|
|
g_value_set_double (&value, val);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_STRING:
|
|
{
|
|
gchar *val;
|
|
|
|
val = g_key_file_get_string (keyfile,
|
|
SETTINGS_GROUP, p_name,
|
|
&key_error);
|
|
g_value_take_string (&value, val);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (key_error != NULL &&
|
|
key_error->domain != G_KEY_FILE_ERROR &&
|
|
key_error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
|
|
{
|
|
g_critical ("Unable to read the value for setting '%s': %s",
|
|
p_name,
|
|
key_error->message);
|
|
}
|
|
|
|
if (key_error == NULL)
|
|
g_object_set_property (settings_obj, p_name, &value);
|
|
else
|
|
g_error_free (key_error);
|
|
|
|
g_value_unset (&value);
|
|
}
|
|
|
|
g_free (pspecs);
|
|
}
|