gnome-control-center/panels/universal-access/cc-ua-panel.c
Bastien Nocera 3686cf7eb8 shell: Make all control-center plugins static
This makes loading faster, with less I/O, avoids unnecessary
code duplication (around 1k lines shaved), and ensures that
all the panels link and work appropriately.

By the same token, it will stop external panels from being
created, and loaded.

https://bugzilla.gnome.org/show_bug.cgi?id=690036
2012-12-11 17:07:39 +01:00

654 lines
20 KiB
C

/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2010 Intel, Inc
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Authors: Thomas Wood <thomas.wood@intel.com>
* Rodrigo Moya <rodrigo@gnome.org>
*
*/
#include <config.h>
#include <math.h>
#include <glib/gi18n-lib.h>
#include <gdesktop-enums.h>
#include "cc-ua-panel.h"
#include "zoom-options.h"
#define WID(b, w) (GtkWidget *) gtk_builder_get_object (b, w)
#define DPI_FACTOR_LARGE 1.25
#define DPI_FACTOR_NORMAL 1.0
#define HIGH_CONTRAST_THEME "HighContrast"
#define KEY_TEXT_SCALING_FACTOR "text-scaling-factor"
#define KEY_GTK_THEME "gtk-theme"
#define KEY_ICON_THEME "icon-theme"
#define KEY_WM_THEME "theme"
CC_PANEL_REGISTER (CcUaPanel, cc_ua_panel)
#define UA_PANEL_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_UA_PANEL, CcUaPanelPrivate))
struct _CcUaPanelPrivate
{
GtkBuilder *builder;
GSettings *wm_settings;
GSettings *interface_settings;
GSettings *kb_settings;
GSettings *mouse_settings;
GSettings *application_settings;
GSettings *mediakeys_settings;
ZoomOptions *zoom_options;
};
static void
cc_ua_panel_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
switch (property_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
cc_ua_panel_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
switch (property_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
cc_ua_panel_dispose (GObject *object)
{
CcUaPanelPrivate *priv = CC_UA_PANEL (object)->priv;
if (priv->builder)
{
g_object_unref (priv->builder);
priv->builder = NULL;
}
if (priv->wm_settings)
{
g_object_unref (priv->wm_settings);
priv->wm_settings = NULL;
}
if (priv->interface_settings)
{
g_object_unref (priv->interface_settings);
priv->interface_settings = NULL;
}
if (priv->kb_settings)
{
g_object_unref (priv->kb_settings);
priv->kb_settings = NULL;
}
if (priv->mouse_settings)
{
g_object_unref (priv->mouse_settings);
priv->mouse_settings = NULL;
}
if (priv->application_settings)
{
g_object_unref (priv->application_settings);
priv->application_settings = NULL;
}
if (priv->mediakeys_settings)
{
g_object_unref (priv->mediakeys_settings);
priv->mediakeys_settings = NULL;
}
if (priv->zoom_options)
{
g_object_unref (priv->zoom_options);
priv->zoom_options = NULL;
}
G_OBJECT_CLASS (cc_ua_panel_parent_class)->dispose (object);
}
static void
cc_ua_panel_finalize (GObject *object)
{
G_OBJECT_CLASS (cc_ua_panel_parent_class)->finalize (object);
}
static const char *
cc_ua_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/a11y";
}
static void
cc_ua_panel_class_init (CcUaPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
g_type_class_add_private (klass, sizeof (CcUaPanelPrivate));
panel_class->get_help_uri = cc_ua_panel_get_help_uri;
object_class->get_property = cc_ua_panel_get_property;
object_class->set_property = cc_ua_panel_set_property;
object_class->dispose = cc_ua_panel_dispose;
object_class->finalize = cc_ua_panel_finalize;
}
static gchar *sticky_keys_section[] = {
"typing_sticky_keys_disable_two_keys_checkbutton",
"typing_sticky_keys_beep_modifier_checkbutton",
NULL
};
static gchar *slow_keys_section[]= {
"typing_slowkeys_delay_box",
"typing_slow_keys_beeb_box",
NULL
};
static gchar *bounce_keys_section[] = {
"typing_bouncekeys_delay_box",
"typing_bounce_keys_beep_rejected_checkbutton",
NULL
};
static gchar *secondary_click_section[] = {
"pointing_secondary_click_scale_box",
NULL
};
static gchar *dwell_click_section[] = {
"pointing_hover_click_delay_scale_box",
"pointing_hover_click_threshold_scale_box",
NULL
};
static gchar *visual_alerts_section[] = {
"hearing_test_flash_button",
"hearing_flash_window_title_button",
"hearing_flash_screen_button",
NULL
};
/* zoom options dialog */
static void
zoom_options_launch_cb (GtkWidget *options_button, CcUaPanel *self)
{
if (self->priv->zoom_options == NULL)
self->priv->zoom_options = zoom_options_new ();
if (self->priv->zoom_options != NULL)
zoom_options_set_parent (self->priv->zoom_options,
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))));
}
static void
cc_ua_panel_section_switched (GObject *object,
GParamSpec *pspec,
GtkBuilder *builder)
{
GtkWidget *w;
gboolean enabled;
gchar **widgets, **s;
widgets = g_object_get_data (object, "section-widgets");
g_object_get (object, "active", &enabled, NULL);
for (s = widgets; *s; s++)
{
w = WID (builder, *s);
gtk_widget_set_sensitive (w, enabled);
}
}
static void
settings_on_off_editor_new (CcUaPanelPrivate *priv,
GSettings *settings,
const gchar *key,
GtkWidget *widget,
gchar **section)
{
/* set data to enable/disable the section this on/off switch controls */
if (section)
{
g_object_set_data (G_OBJECT (widget), "section-widgets", section);
g_signal_connect (widget, "notify::active",
G_CALLBACK (cc_ua_panel_section_switched),
priv->builder);
}
/* set up the boolean editor */
g_settings_bind (settings, key, widget, "active", G_SETTINGS_BIND_DEFAULT);
}
/* seeing section */
static void
cc_ua_panel_set_shortcut_label (CcUaPanel *self,
const char *label,
const char *key)
{
GtkWidget *widget;
char *value;
char *text;
guint accel_key, *keycode;
GdkModifierType mods;
widget = WID (self->priv->builder, label);
value = g_settings_get_string (self->priv->mediakeys_settings, key);
if (value == NULL || *value == '\0') {
gtk_label_set_text (GTK_LABEL (widget), _("No shortcut set"));
g_free (value);
return;
}
gtk_accelerator_parse_with_keycode (value, &accel_key, &keycode, &mods);
if (accel_key == 0 && keycode == NULL && mods == 0) {
gtk_label_set_text (GTK_LABEL (widget), _("No shortcut set"));
g_free (value);
g_warning ("Failed to parse keyboard shortcut: '%s'", value);
return;
}
g_free (value);
text = gtk_accelerator_get_label_with_keycode (gtk_widget_get_display (widget), accel_key, *keycode, mods);
g_free (keycode);
gtk_label_set_text (GTK_LABEL (widget), text);
g_free (text);
}
static gboolean
get_large_text_mapping (GValue *value,
GVariant *variant,
gpointer user_data)
{
gdouble factor;
gboolean large;
factor = g_variant_get_double (variant);
large = factor > DPI_FACTOR_NORMAL;
g_value_set_boolean (value, large);
return TRUE;
}
static GVariant *
set_large_text_mapping (const GValue *value,
const GVariantType *expected_type,
gpointer user_data)
{
gboolean large;
GSettings *settings = user_data;
GVariant *ret = NULL;
large = g_value_get_boolean (value);
if (large)
ret = g_variant_new_double (DPI_FACTOR_LARGE);
else
g_settings_reset (settings, KEY_TEXT_SCALING_FACTOR);
return ret;
}
static gboolean
get_contrast_mapping (GValue *value,
GVariant *variant,
gpointer user_data)
{
const char *theme;
gboolean hc;
theme = g_variant_get_string (variant, NULL);
hc = (g_strcmp0 (theme, HIGH_CONTRAST_THEME) == 0);
g_value_set_boolean (value, hc);
return TRUE;
}
static GVariant *
set_contrast_mapping (const GValue *value,
const GVariantType *expected_type,
gpointer user_data)
{
gboolean hc;
CcUaPanel *self = user_data;
CcUaPanelPrivate *priv = self->priv;
GVariant *ret = NULL;
hc = g_value_get_boolean (value);
if (hc)
{
ret = g_variant_new_string (HIGH_CONTRAST_THEME);
g_settings_set_string (priv->interface_settings, KEY_ICON_THEME, HIGH_CONTRAST_THEME);
g_settings_set_string (priv->wm_settings, KEY_WM_THEME, HIGH_CONTRAST_THEME);
}
else
{
g_settings_reset (priv->interface_settings, KEY_GTK_THEME);
g_settings_reset (priv->interface_settings, KEY_ICON_THEME);
g_settings_reset (priv->wm_settings, KEY_WM_THEME);
}
return ret;
}
static void
cc_ua_panel_init_seeing (CcUaPanel *self)
{
CcUaPanelPrivate *priv = self->priv;
g_settings_bind_with_mapping (priv->interface_settings, KEY_GTK_THEME,
WID (priv->builder, "seeing_contrast_switch"),
"active", G_SETTINGS_BIND_DEFAULT,
get_contrast_mapping,
set_contrast_mapping,
self,
NULL);
g_settings_bind_with_mapping (priv->interface_settings, KEY_TEXT_SCALING_FACTOR,
WID (priv->builder, "seeing_large_text_switch"),
"active", G_SETTINGS_BIND_DEFAULT,
get_large_text_mapping,
set_large_text_mapping,
priv->interface_settings,
NULL);
g_settings_bind (priv->kb_settings, "togglekeys-enable",
WID (priv->builder, "seeing_toggle_keys_switch"), "active",
G_SETTINGS_BIND_DEFAULT);
g_signal_connect (WID (priv->builder, "seeing_zoom_preferences_button"),
"clicked",
G_CALLBACK (zoom_options_launch_cb), self);
g_settings_bind (priv->application_settings, "screen-magnifier-enabled",
WID (priv->builder, "seeing_zoom_switch"), "active",
G_SETTINGS_BIND_DEFAULT);
settings_on_off_editor_new (priv, priv->application_settings,
"screen-reader-enabled",
WID (priv->builder, "seeing_reader_switch"),
NULL);
cc_ua_panel_set_shortcut_label (self, "seeing_zoom_enable_keybinding_label", "magnifier");
cc_ua_panel_set_shortcut_label (self, "seeing_zoom_in_keybinding_label", "magnifier-zoom-in");
cc_ua_panel_set_shortcut_label (self, "seeing_zoom_out_keybinding_label", "magnifier-zoom-out");
cc_ua_panel_set_shortcut_label (self, "seeing_reader_enable_keybinding_label", "screenreader");
}
/* hearing/sound section */
static void
visual_bell_type_notify_cb (GSettings *settings,
const gchar *key,
CcUaPanel *panel)
{
GtkWidget *widget;
GDesktopVisualBellType type;
type = g_settings_get_enum (panel->priv->wm_settings, "visual-bell-type");
if (type == G_DESKTOP_VISUAL_BELL_FRAME_FLASH)
widget = WID (panel->priv->builder, "hearing_flash_window_title_button");
else
widget = WID (panel->priv->builder, "hearing_flash_screen_button");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
}
static void
visual_bell_type_toggle_cb (GtkWidget *button,
CcUaPanel *panel)
{
gboolean frame_flash;
GDesktopVisualBellType type;
frame_flash = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
if (frame_flash)
type = G_DESKTOP_VISUAL_BELL_FRAME_FLASH;
else
type = G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH;
g_settings_set_enum (panel->priv->wm_settings, "visual-bell-type", type);
}
static gboolean
hearing_sound_preferences_clicked (GtkButton *button,
CcUaPanel *panel)
{
CcShell *shell;
shell = cc_panel_get_shell (CC_PANEL (panel));
cc_shell_set_active_panel_from_id (shell, "sound", NULL, NULL);
return TRUE;
}
static void
cc_ua_panel_init_hearing (CcUaPanel *self)
{
CcUaPanelPrivate *priv = self->priv;
GtkWidget *w;
/* set the initial visual bell values */
visual_bell_type_notify_cb (NULL, NULL, self);
/* and listen */
w = WID (priv->builder, "hearing_visual_alerts_switch");
settings_on_off_editor_new (priv, priv->wm_settings, "visual-bell", w, visual_alerts_section);
g_signal_connect (priv->wm_settings, "changed::visual-bell-type",
G_CALLBACK (visual_bell_type_notify_cb), self);
g_signal_connect (WID (priv->builder, "hearing_flash_window_title_button"),
"toggled", G_CALLBACK (visual_bell_type_toggle_cb), self);
/* test flash */
g_signal_connect (WID (priv->builder, "hearing_test_flash_button"),
"clicked", G_CALLBACK (gdk_beep), NULL);
g_signal_connect (WID (priv->builder, "hearing_sound_preferences_link"),
"activate-link",
G_CALLBACK (hearing_sound_preferences_clicked), self);
}
/* typing/keyboard section */
static void
cc_ua_panel_init_keyboard (CcUaPanel *self)
{
CcUaPanelPrivate *priv = self->priv;
GtkWidget *w;
/* Typing assistant (on-screen keyboard) */
w = WID (priv->builder, "typing_assistant_switch");
g_settings_bind (priv->application_settings, "screen-keyboard-enabled",
w, "active", G_SETTINGS_BIND_DEFAULT);
/* enable shortcuts */
w = WID (priv->builder, "typing_keyboard_toggle_switch");
g_settings_bind (priv->kb_settings, "enable", w, "active", G_SETTINGS_BIND_DEFAULT);
/* sticky keys */
w = WID (priv->builder, "typing_sticky_keys_switch");
settings_on_off_editor_new (priv, priv->kb_settings, "stickykeys-enable", w, sticky_keys_section);
w = WID (priv->builder, "typing_sticky_keys_disable_two_keys_checkbutton");
g_settings_bind (priv->kb_settings, "stickykeys-two-key-off", w, "active", G_SETTINGS_BIND_NO_SENSITIVITY);
w = WID (priv->builder, "typing_sticky_keys_beep_modifier_checkbutton");
g_settings_bind (priv->kb_settings, "stickykeys-modifier-beep", w, "active", G_SETTINGS_BIND_NO_SENSITIVITY);
/* slow keys */
w = WID (priv->builder, "typing_slow_keys_switch");
settings_on_off_editor_new (priv, priv->kb_settings, "slowkeys-enable", w, slow_keys_section);
w = WID (priv->builder, "typing_slowkeys_delay_scale");
g_settings_bind (priv->kb_settings, "slowkeys-delay",
gtk_range_get_adjustment (GTK_RANGE (w)), "value",
G_SETTINGS_BIND_DEFAULT);
w = WID (priv->builder, "typing_slow_keys_beep_pressed_checkbutton");
g_settings_bind (priv->kb_settings, "slowkeys-beep-press", w, "active", G_SETTINGS_BIND_DEFAULT);
w = WID (priv->builder, "typing_slow_keys_beep_accepted_checkbutton");
g_settings_bind (priv->kb_settings, "slowkeys-beep-accept", w, "active", G_SETTINGS_BIND_DEFAULT);
w = WID (priv->builder, "typing_slow_keys_beep_rejected_checkbutton");
g_settings_bind (priv->kb_settings, "slowkeys-beep-reject", w, "active", G_SETTINGS_BIND_DEFAULT);
/* bounce keys */
w = WID (priv->builder, "typing_bounce_keys_switch");
settings_on_off_editor_new (priv, priv->kb_settings, "bouncekeys-enable", w, bounce_keys_section);
w = WID (priv->builder, "typing_bouncekeys_delay_scale");
g_settings_bind (priv->kb_settings, "bouncekeys-delay",
gtk_range_get_adjustment (GTK_RANGE (w)), "value",
G_SETTINGS_BIND_DEFAULT);
w = WID (priv->builder, "typing_bounce_keys_beep_rejected_checkbutton");
g_settings_bind (priv->kb_settings, "bouncekeys-beep-reject", w, "active", G_SETTINGS_BIND_NO_SENSITIVITY);
}
/* mouse/pointing & clicking section */
static gboolean
pointing_mouse_preferences_clicked_cb (GtkButton *button,
CcUaPanel *panel)
{
CcShell *shell;
shell = cc_panel_get_shell (CC_PANEL (panel));
cc_shell_set_active_panel_from_id (shell, "mouse", NULL, NULL);
return TRUE;
}
static void
cc_ua_panel_init_mouse (CcUaPanel *self)
{
CcUaPanelPrivate *priv = self->priv;
GtkWidget *w;
/* mouse keys */
w = WID (priv->builder, "pointing_mouse_keys_switch");
settings_on_off_editor_new (priv, priv->kb_settings, "mousekeys-enable", w, NULL);
/* simulated secondary click */
w = WID (priv->builder, "pointing_second_click_switch");
settings_on_off_editor_new (priv, priv->mouse_settings, "secondary-click-enabled", w, secondary_click_section);
w = WID (priv->builder, "pointing_secondary_click_delay_scale");
g_settings_bind (priv->mouse_settings, "secondary-click-time",
gtk_range_get_adjustment (GTK_RANGE (w)), "value",
G_SETTINGS_BIND_DEFAULT);
/* dwell click */
w = WID (priv->builder, "pointing_hover_click_switch");
settings_on_off_editor_new (priv, priv->mouse_settings, "dwell-click-enabled", w, dwell_click_section);
w = WID (priv->builder, "pointing_dwell_delay_scale");
g_settings_bind (priv->mouse_settings, "dwell-time",
gtk_range_get_adjustment (GTK_RANGE (w)), "value",
G_SETTINGS_BIND_DEFAULT);
w = WID (priv->builder, "pointing_dwell_threshold_scale");
g_settings_bind (priv->mouse_settings, "dwell-threshold",
gtk_range_get_adjustment (GTK_RANGE (w)), "value",
G_SETTINGS_BIND_DEFAULT);
/* mouse preferences button */
g_signal_connect (WID (priv->builder, "pointing_mouse_preferences_link"),
"activate-link",
G_CALLBACK (pointing_mouse_preferences_clicked_cb), self);
}
static void
cc_ua_panel_init (CcUaPanel *self)
{
CcUaPanelPrivate *priv;
GtkWidget *widget;
GError *err = NULL;
gchar *objects[] = { "universal_access_box", "contrast_model",
"text_size_model", "slowkeys_delay_adjustment",
"bouncekeys_delay_adjustment", "click_delay_adjustment",
"dwell_time_adjustment", "dwell_threshold_adjustment",
"seeing_sizegroup", "typing_sizegroup",
"pointing_sizegroup", "pointing_sizegroup2",
"pointing_scale_sizegroup", "sizegroup1",
"hearing_sizegroup",
NULL };
priv = self->priv = UA_PANEL_PRIVATE (self);
priv->builder = gtk_builder_new ();
gtk_builder_add_objects_from_file (priv->builder,
GNOMECC_UI_DIR "/uap.ui",
objects,
&err);
if (err)
{
g_warning ("Could not load interface file: %s", err->message);
g_error_free (err);
g_object_unref (priv->builder);
priv->builder = NULL;
return;
}
priv->interface_settings = g_settings_new ("org.gnome.desktop.interface");
priv->wm_settings = g_settings_new ("org.gnome.desktop.wm.preferences");
priv->kb_settings = g_settings_new ("org.gnome.desktop.a11y.keyboard");
priv->mouse_settings = g_settings_new ("org.gnome.desktop.a11y.mouse");
priv->application_settings = g_settings_new ("org.gnome.desktop.a11y.applications");
priv->mediakeys_settings = g_settings_new ("org.gnome.settings-daemon.plugins.media-keys");
cc_ua_panel_init_keyboard (self);
cc_ua_panel_init_mouse (self);
cc_ua_panel_init_hearing (self);
cc_ua_panel_init_seeing (self);
widget = (GtkWidget*) gtk_builder_get_object (priv->builder,
"universal_access_box");
gtk_container_add (GTK_CONTAINER (self), widget);
}